fix(platform-browser): should not throw for debug attrs containing $ (#14353)
Closes #9566 PR Close #14353
This commit is contained in:
parent
e5a144d902
commit
1cfbefebe3
|
@ -1507,6 +1507,14 @@ function declareTests({useJit, viewEngine}: {useJit: boolean, viewEngine: boolea
|
|||
.toContain('ng-reflect-dir-prop="hello"');
|
||||
});
|
||||
|
||||
it(`should work with prop names containing '$'`, () => {
|
||||
TestBed.configureTestingModule({declarations: [ParentCmp, SomeCmpWithInput]});
|
||||
const fixture = TestBed.createComponent(ParentCmp);
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(getDOM().getInnerHTML(fixture.nativeElement)).toContain('ng-reflect-test$="hello"');
|
||||
});
|
||||
|
||||
it('should reflect property values on template comments', () => {
|
||||
TestBed.configureTestingModule({declarations: [MyComp]});
|
||||
const template = '<template [ngIf]="ctxBoolProp"></template>';
|
||||
|
@ -2300,3 +2308,16 @@ class DirectiveWithPropDecorators {
|
|||
class SomeCmp {
|
||||
value: any;
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'parent-cmp',
|
||||
template: `<cmp [test$]="name"></cmp>`,
|
||||
})
|
||||
export class ParentCmp {
|
||||
name: string = 'hello';
|
||||
}
|
||||
|
||||
@Component({selector: 'cmp', template: ''})
|
||||
class SomeCmpWithInput {
|
||||
@Input() test$: any;
|
||||
}
|
||||
|
|
|
@ -230,7 +230,14 @@ export class DomRenderer implements Renderer {
|
|||
renderElement.nodeValue =
|
||||
TEMPLATE_COMMENT_TEXT.replace('{}', JSON.stringify(parsedBindings, null, 2));
|
||||
} else {
|
||||
this.setElementAttribute(renderElement, propertyName, propertyValue);
|
||||
// Attribute names with `$` (eg `x-y$`) are valid per spec, but unsupported by some browsers
|
||||
if (propertyName[propertyName.length - 1] === '$') {
|
||||
const attrNode: Attr = createAttrNode(propertyName).cloneNode(true) as Attr;
|
||||
attrNode.value = propertyValue;
|
||||
renderElement.setAttributeNode(attrNode);
|
||||
} else {
|
||||
this.setElementAttribute(renderElement, propertyName, propertyValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -341,3 +348,20 @@ export function splitNamespace(name: string): string[] {
|
|||
const match = name.match(NS_PREFIX_RE);
|
||||
return [match[1], match[2]];
|
||||
}
|
||||
|
||||
let attrCache: Map<string, Attr>;
|
||||
|
||||
function createAttrNode(name: string): Attr {
|
||||
if (!attrCache) {
|
||||
attrCache = new Map<string, Attr>();
|
||||
}
|
||||
if (attrCache.has(name)) {
|
||||
return attrCache.get(name);
|
||||
} else {
|
||||
const div = document.createElement('div');
|
||||
div.innerHTML = `<div ${name}>`;
|
||||
const attr: Attr = div.firstChild.attributes[0];
|
||||
attrCache.set(name, attr);
|
||||
return attr;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue