fix(ivy): do not inject attributes with namespace (#29257)
When injecting with `@Attribute`, namespaced attributes should not match (in order to have feature parity with View Engine). This PR resolves FW-1137 PR Close #29257
This commit is contained in:
parent
1f0eadfab6
commit
018477e2c4
|
@ -279,7 +279,14 @@ export function injectAttributeImpl(tNode: TNode, attrNameToInject: string): str
|
||||||
// If we hit a `Bindings` or `Template` marker then we are done.
|
// If we hit a `Bindings` or `Template` marker then we are done.
|
||||||
if (isNameOnlyAttributeMarker(value)) break;
|
if (isNameOnlyAttributeMarker(value)) break;
|
||||||
|
|
||||||
if (typeof value === 'number') {
|
// Skip namespaced attributes
|
||||||
|
if (value === AttributeMarker.NamespaceURI) {
|
||||||
|
// we skip the next two values
|
||||||
|
// as namespaced attributes looks like
|
||||||
|
// [..., AttributeMarker.NamespaceURI, 'http://someuri.com/test', 'test:exist',
|
||||||
|
// 'existValue', ...]
|
||||||
|
i = i + 2;
|
||||||
|
} else if (typeof value === 'number') {
|
||||||
// Skip to the first value of the marked attribute.
|
// Skip to the first value of the marked attribute.
|
||||||
i++;
|
i++;
|
||||||
if (value === AttributeMarker.Classes && attrNameToInject === 'class') {
|
if (value === AttributeMarker.Classes && attrNameToInject === 'class') {
|
||||||
|
@ -300,7 +307,6 @@ export function injectAttributeImpl(tNode: TNode, attrNameToInject: string): str
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (value === attrNameToInject) {
|
} else if (value === attrNameToInject) {
|
||||||
// TODO(FW-1137): Skip namespaced attributes
|
|
||||||
return attrs[i + 1] as string;
|
return attrs[i + 1] as string;
|
||||||
} else {
|
} else {
|
||||||
i = i + 2;
|
i = i + 2;
|
||||||
|
|
|
@ -131,30 +131,62 @@ describe('di', () => {
|
||||||
expect(fixture.componentInstance.myDir.localeId).toBe('en-GB');
|
expect(fixture.componentInstance.myDir.localeId).toBe('en-GB');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should be able to inject different kinds of attributes', () => {
|
describe('@Attribute', () => {
|
||||||
@Directive({selector: '[dir]'})
|
|
||||||
class MyDir {
|
|
||||||
constructor(
|
|
||||||
@Attribute('class') public className: string,
|
|
||||||
@Attribute('style') public inlineStyles: string,
|
|
||||||
@Attribute('other-attr') public otherAttr: string) {}
|
|
||||||
}
|
|
||||||
@Component({
|
|
||||||
template:
|
|
||||||
'<div dir style="margin: 1px; color: red;" class="hello there" other-attr="value"></div>'
|
|
||||||
})
|
|
||||||
class MyComp {
|
|
||||||
@ViewChild(MyDir) directiveInstance !: MyDir;
|
|
||||||
}
|
|
||||||
|
|
||||||
TestBed.configureTestingModule({declarations: [MyDir, MyComp, MyComp]});
|
it('should be able to inject different kinds of attributes', () => {
|
||||||
const fixture = TestBed.createComponent(MyComp);
|
@Directive({selector: '[dir]'})
|
||||||
fixture.detectChanges();
|
class MyDir {
|
||||||
|
constructor(
|
||||||
|
@Attribute('class') public className: string,
|
||||||
|
@Attribute('style') public inlineStyles: string,
|
||||||
|
@Attribute('other-attr') public otherAttr: string) {}
|
||||||
|
}
|
||||||
|
|
||||||
const directive = fixture.componentInstance.directiveInstance;
|
@Component({
|
||||||
|
template:
|
||||||
|
'<div dir style="margin: 1px; color: red;" class="hello there" other-attr="value"></div>'
|
||||||
|
})
|
||||||
|
class MyComp {
|
||||||
|
@ViewChild(MyDir) directiveInstance !: MyDir;
|
||||||
|
}
|
||||||
|
|
||||||
expect(directive.otherAttr).toBe('value');
|
TestBed.configureTestingModule({declarations: [MyDir, MyComp]});
|
||||||
expect(directive.className).toBe('hello there');
|
const fixture = TestBed.createComponent(MyComp);
|
||||||
expect(directive.inlineStyles).toBe('margin: 1px; color: red;');
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
const directive = fixture.componentInstance.directiveInstance;
|
||||||
|
|
||||||
|
expect(directive.otherAttr).toBe('value');
|
||||||
|
expect(directive.className).toBe('hello there');
|
||||||
|
expect(directive.inlineStyles).toBe('margin: 1px; color: red;');
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not inject attributes with namespace', () => {
|
||||||
|
@Directive({selector: '[dir]'})
|
||||||
|
class MyDir {
|
||||||
|
constructor(
|
||||||
|
@Attribute('exist') public exist: string,
|
||||||
|
@Attribute('svg:exist') public namespacedExist: string,
|
||||||
|
@Attribute('other') public other: string) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
template: '<div dir exist="existValue" svg:exist="testExistValue" other="otherValue"></div>'
|
||||||
|
})
|
||||||
|
class MyComp {
|
||||||
|
@ViewChild(MyDir) directiveInstance !: MyDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
TestBed.configureTestingModule({declarations: [MyDir, MyComp]});
|
||||||
|
const fixture = TestBed.createComponent(MyComp);
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
const directive = fixture.componentInstance.directiveInstance;
|
||||||
|
|
||||||
|
expect(directive.exist).toBe('existValue');
|
||||||
|
expect(directive.namespacedExist).toBeNull();
|
||||||
|
expect(directive.other).toBe('otherValue');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue