X Tutup
Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions modules/angular2/src/compiler/template_parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -554,6 +554,9 @@ class TemplateParseVisitor implements HtmlAstVisitor {
} else {
if (parts[0] == ATTRIBUTE_PREFIX) {
boundPropertyName = parts[1];
if (boundPropertyName.indexOf(':') > -1) {
boundPropertyName = '@' + boundPropertyName;
}
bindingType = PropertyBindingType.Attribute;
} else if (parts[0] == CLASS_PREFIX) {
boundPropertyName = parts[1];
Expand Down
7 changes: 7 additions & 0 deletions modules/angular2/src/platform/browser/browser_adapter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,9 @@ class BrowserDomAdapter extends GenericBrowserDomAdapter {
String getAttribute(Element element, String attribute) =>
element.getAttribute(attribute);

String getAttributeNS(Element element, String ns, String attribute) =>
element.getAttributeNS(ns, attribute);

void setAttribute(Element element, String name, String value) {
element.setAttribute(name, value);
}
Expand All @@ -382,6 +385,10 @@ class BrowserDomAdapter extends GenericBrowserDomAdapter {
element.attributes.remove(name);
}

void removeAttributeNS(Element element, String ns, String name) {
element.getNamespacedAttributes(ns).remove(name);
}

Node templateAwareRoot(Element el) => el is TemplateElement ? el.content : el;

HtmlDocument createHtmlDocument() =>
Expand Down
10 changes: 7 additions & 3 deletions modules/angular2/src/platform/browser/browser_adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -224,13 +224,17 @@ export class BrowserDomAdapter extends GenericBrowserDomAdapter {
}
return res;
}
hasAttribute(element, attribute: string): boolean { return element.hasAttribute(attribute); }
getAttribute(element, attribute: string): string { return element.getAttribute(attribute); }
hasAttribute(element, name: string): boolean { return element.hasAttribute(name); }
getAttribute(element, name: string): string { return element.getAttribute(name); }
getAttributeNS(element, ns: string, name: string): string {
return element.getAttributeNS(ns, name);
}
setAttribute(element, name: string, value: string) { element.setAttribute(name, value); }
setAttributeNS(element, ns: string, name: string, value: string) {
element.setAttributeNS(ns, name, value);
}
removeAttribute(element, attribute: string) { element.removeAttribute(attribute); }
removeAttribute(element, name: string) { element.removeAttribute(name); }
removeAttributeNS(element, ns: string, name: string) { element.removeAttributeNS(ns, name); }
templateAwareRoot(el): any { return this.isTemplateElement(el) ? this.content(el) : el; }
createHtmlDocument(): HTMLDocument {
return document.implementation.createHTMLDocument('fakeTitle');
Expand Down
8 changes: 5 additions & 3 deletions modules/angular2/src/platform/dom/dom_adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,11 +92,13 @@ export abstract class DomAdapter {
abstract hasStyle(element, styleName: string, styleValue?: string): boolean;
abstract tagName(element): string;
abstract attributeMap(element): Map<string, string>;
abstract hasAttribute(element, attribute: string): boolean;
abstract getAttribute(element, attribute: string): string;
abstract hasAttribute(element, name: string): boolean;
abstract getAttribute(element, name: string): string;
abstract getAttributeNS(element, ns: string, name: string): string;
abstract setAttribute(element, name: string, value: string);
abstract setAttributeNS(element, ns: string, name: string, value: string);
abstract removeAttribute(element, attribute: string);
abstract removeAttribute(element, name: string);
abstract removeAttributeNS(element, ns: string, name: string);
abstract templateAwareRoot(el);
abstract createHtmlDocument(): HTMLDocument;
abstract defaultDoc(): HTMLDocument;
Expand Down
33 changes: 23 additions & 10 deletions modules/angular2/src/platform/dom/dom_renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,14 +135,27 @@ export abstract class DomRenderer extends Renderer implements NodeFactory<Node>
propertyValue);
}

setElementAttribute(location: RenderElementRef, attributeName: string,
attributeValue: string): void {
setElementAttribute(location: RenderElementRef, attrName: string, attrValue: string): void {
var view = resolveInternalDomView(location.renderView);
var element = view.boundElements[location.boundElementIndex];
if (isPresent(attributeValue)) {
DOM.setAttribute(element, attributeName, stringify(attributeValue));
var attrNs;
var nsAndName = splitNsName(attrName);
if (isPresent(nsAndName[0])) {
attrName = nsAndName[1];
attrNs = NAMESPACE_URIS[nsAndName[0]];
}
if (isPresent(attrValue)) {
if (isPresent(attrNs)) {
DOM.setAttributeNS(element, attrNs, attrName, attrValue);
} else {
DOM.setAttribute(element, nsAndName[1], attrValue);
}
} else {
DOM.removeAttribute(element, attributeName);
if (isPresent(attrNs)) {
DOM.removeAttributeNS(element, attrNs, attrName);
} else {
DOM.removeAttribute(element, attrName);
}
}
}

Expand Down Expand Up @@ -307,7 +320,7 @@ export class DomRenderer_ extends DomRenderer {
wtfLeave(s);
}
createElement(name: string, attrNameAndValues: string[]): Node {
var nsAndName = splitNamespace(name);
var nsAndName = splitNsName(name);
var el = isPresent(nsAndName[0]) ?
DOM.createElementNS(NAMESPACE_URIS[nsAndName[0]], nsAndName[1]) :
DOM.createElement(nsAndName[1]);
Expand All @@ -320,11 +333,11 @@ export class DomRenderer_ extends DomRenderer {
}
private _setAttributes(node: Node, attrNameAndValues: string[]) {
for (var attrIdx = 0; attrIdx < attrNameAndValues.length; attrIdx += 2) {
var attrNs;
var attrNs = null;
var attrName = attrNameAndValues[attrIdx];
var nsAndName = splitNamespace(attrName);
var nsAndName = splitNsName(attrName);
if (isPresent(nsAndName[0])) {
attrName = nsAndName[0] + ':' + nsAndName[1];
attrName = nsAndName[1];
attrNs = NAMESPACE_URIS[nsAndName[0]];
}
var attrValue = attrNameAndValues[attrIdx + 1];
Expand Down Expand Up @@ -392,7 +405,7 @@ function decoratePreventDefault(eventHandler: Function): Function {

var NS_PREFIX_RE = /^@([^:]+):(.+)/g;

function splitNamespace(name: string): string[] {
function splitNsName(name: string): string[] {
if (name[0] != '@') {
return [null, name];
}
Expand Down
20 changes: 14 additions & 6 deletions modules/angular2/src/platform/server/abstract_html_adapter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -290,18 +290,22 @@ abstract class AbstractHtml5LibAdapter implements DomAdapter {
return map;
}

hasAttribute(element, String attribute) {
hasAttribute(element, String name) {
// `attributes` keys can be {@link AttributeName}s.
return element.attributes.keys.any((key) => '$key' == attribute);
return element.attributes.keys.any((key) => '$key' == name);
}

getAttribute(element, String attribute) {
getAttribute(element, String name) {
// `attributes` keys can be {@link AttributeName}s.
var key = element.attributes.keys.firstWhere((key) => '$key' == attribute,
var key = element.attributes.keys.firstWhere((key) => '$key' == name,
orElse: () {});
return element.attributes[key];
}

getAttributeNS(element, String ns, String name) {
throw 'not implemented';
}

setAttribute(element, String name, String value) {
element.attributes[name] = value;
}
Expand All @@ -310,8 +314,12 @@ abstract class AbstractHtml5LibAdapter implements DomAdapter {
throw 'not implemented';
}

removeAttribute(element, String attribute) {
element.attributes.remove(attribute);
removeAttribute(element, String name) {
element.attributes.remove(name);
}

removeAttributeNS(element, String ns, String name) {
throw 'not implemented';
}

templateAwareRoot(el) => el;
Expand Down
33 changes: 17 additions & 16 deletions modules/angular2/src/platform/server/parse5_adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -426,28 +426,29 @@ export class Parse5DomAdapter extends DomAdapter {
}
return res;
}
hasAttribute(element, attribute: string): boolean {
return element.attribs && element.attribs.hasOwnProperty(attribute);
}
getAttribute(element, attribute: string): string {
return element.attribs && element.attribs.hasOwnProperty(attribute) ?
element.attribs[attribute] :
null;
}
setAttribute(element, attribute: string, value: string) {
if (attribute) {
element.attribs[attribute] = value;
if (attribute === 'class') {
hasAttribute(element, name: string): boolean {
return element.attribs && element.attribs.hasOwnProperty(name);
}
getAttribute(element, name: string): string {
return element.attribs && element.attribs.hasOwnProperty(name) ? element.attribs[name] : null;
}
getAttributeNS(element, name: string): string { throw 'not implemented'; }
setAttribute(element, name: string, value: string) {
if (name) {
element.attribs[name] = value;
if (name === 'class') {
element.className = value;
}
}
}
setAttributeNS(element, ns: string, attribute: string, value: string) { throw 'not implemented'; }
removeAttribute(element, attribute: string) {
if (attribute) {
StringMapWrapper.delete(element.attribs, attribute);
setAttributeNS(element, ns: string, name: string, value: string) { throw 'not implemented'; }
removeAttribute(element, name: string) {
if (name) {
StringMapWrapper.delete(element.attribs, name);
}
}
removeAttributeNS(element, ns: string, name: string) { throw 'not implemented'; }

templateAwareRoot(el): any { return this.isTemplateElement(el) ? this.content(el) : el; }
createHtmlDocument(): Document {
var newDoc = treeAdapter.createDocument();
Expand Down
10 changes: 2 additions & 8 deletions modules/angular2/test/core/linker/integration_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1820,14 +1820,8 @@ export function main() {
expect(DOM.getProperty(<Element>use, 'namespaceURI'))
.toEqual('http://www.w3.org/2000/svg');

if (!IS_DART) {
var firstAttribute = DOM.getProperty(<Element>use, 'attributes')[0];
expect(firstAttribute.name).toEqual('xlink:href');
expect(firstAttribute.namespaceURI).toEqual('http://www.w3.org/1999/xlink');
} else {
// For Dart where '_Attr' has no instance getter 'namespaceURI'
expect(DOM.getOuterHTML(<HTMLElement>use)).toContain('xmlns:xlink');
}
expect(DOM.getAttributeNS(use, 'http://www.w3.org/1999/xlink', 'href'))
.toEqual('Port');

async.done();
});
Expand Down
57 changes: 44 additions & 13 deletions modules/angular2/test/platform/dom/dom_renderer_integration_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,55 @@ import {
xit,
beforeEachProviders,
SpyObject,
TestComponentBuilder,
} from 'angular2/testing_internal';

// import {MapWrapper} from 'angular2/src/facade/collection';
// import {DOM} from 'angular2/src/platform/dom/dom_adapter';
import {Component, ViewMetadata} from 'angular2/src/core/metadata';

// import {DomTestbed, TestRootView, elRef} from './dom_testbed';

// import {
// ViewDefinition,
// RenderDirectiveMetadata,
// RenderViewRef,
// ViewEncapsulation
// } from 'angular2/src/core/render/api';
import {DOM} from 'angular2/src/platform/dom/dom_adapter';

export function main() {
describe('DomRenderer integration', () => {
it('should work', () => {
// TODO
});

describe('attributes', () => {

it('should support attributes with namespace',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
tcb.overrideView(MyCmp, new ViewMetadata({template: '<svg:use xlink:href="#id" />'}))
.createAsync(MyCmp)
.then((fixture) => {
let useEl = DOM.firstChild(fixture.debugElement.nativeElement);
expect(DOM.getAttributeNS(useEl, 'http://www.w3.org/1999/xlink', 'href'))
.toEqual('#id');
async.done();
});
}));

it('should support binding to attributes with namespace',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
tcb.overrideView(MyCmp,
new ViewMetadata({template: '<svg:use [attr.xlink:href]="value" />'}))
.createAsync(MyCmp)
.then((fixture) => {
let cmp = fixture.debugElement.componentInstance;
let useEl = DOM.firstChild(fixture.debugElement.nativeElement);

cmp.value = "#id";
fixture.detectChanges();

expect(DOM.getAttributeNS(useEl, 'http://www.w3.org/1999/xlink', 'href'))
.toEqual('#id');

async.done();
});
}));

});

});
}

@Component({selector: 'my-cmp', inputs: ['value']})
class MyCmp {
value: any;
}
2 changes: 2 additions & 0 deletions modules/angular2/test/public_api_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1582,6 +1582,7 @@ var NG_PLATFORM_BROWSER = [
'BrowserDomAdapter.firstChild():js',
'BrowserDomAdapter.getAnimationPrefix():js',
'BrowserDomAdapter.getAttribute():js',
'BrowserDomAdapter.getAttributeNS():js',
'BrowserDomAdapter.getBaseHref():js',
'BrowserDomAdapter.getBoundingClientRect():js',
'BrowserDomAdapter.getChecked():js',
Expand Down Expand Up @@ -1641,6 +1642,7 @@ var NG_PLATFORM_BROWSER = [
'BrowserDomAdapter.querySelectorAll():js',
'BrowserDomAdapter.remove():js',
'BrowserDomAdapter.removeAttribute():js',
'BrowserDomAdapter.removeAttributeNS():js',
'BrowserDomAdapter.removeChild():js',
'BrowserDomAdapter.removeClass():js',
'BrowserDomAdapter.removeStyle():js',
Expand Down
1 change: 1 addition & 0 deletions tools/broccoli/trees/node_tree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ module.exports = function makeNodeTree(projects, destinationPath) {
'angular2/test/testing/testing_public_spec.ts',
'angular2/test/platform/xhr_impl_spec.ts',
'angular2/test/platform/browser/**/*.ts',
'angular2/test/platform/dom/dom_renderer_integration_spec.ts',
'angular2/test/common/forms/**',

// we call browser's bootstrap
Expand Down
X Tutup