fix(elements): correctly handle getting/setting properties before connecting the element (#36114)
`createCustomElements()` creates some getters/setters for properties corresponding to component inputs that delegate to the `NgElementStrategy`. However, it is not guaranteed that the element's `NgElementStrategy` will have been created when these getters/setters are called, because some polyfills (e.g. `document-register-element`) do not call the constructor. Previously, trying to get/set input properties before connecting the element to the DOM (via `connectedCallback()`) would fail due to `NgElementStrategy` not being created. This commit ensures that the `NgElementStrategy` is always created before used inside the input property getters/setters (similar to how it is done for other methods of `NgElement`). Mentioned in https://github.com/angular/angular/pull/31416/files#r300326698. PR Close #36114
This commit is contained in:
parent
4c30aa8343
commit
327980bf49
|
@ -187,9 +187,15 @@ export function createCustomElement<P>(
|
|||
inputs.map(({propName}) => propName).forEach(property => {
|
||||
Object.defineProperty(NgElementImpl.prototype, property, {
|
||||
get: function() {
|
||||
if (!this.ngElementStrategy) {
|
||||
this.ngElementStrategy = strategyFactory.create(config.injector);
|
||||
}
|
||||
return this.ngElementStrategy.getInputValue(property);
|
||||
},
|
||||
set: function(newValue: any) {
|
||||
if (!this.ngElementStrategy) {
|
||||
this.ngElementStrategy = strategyFactory.create(config.injector);
|
||||
}
|
||||
this.ngElementStrategy.setInputValue(property, newValue);
|
||||
},
|
||||
configurable: true,
|
||||
|
|
|
@ -94,6 +94,22 @@ if (browserDetection.supportsCustomElements) {
|
|||
expect(strategy.inputs.get('fooFoo')).toBe('foo-foo-value');
|
||||
expect(strategy.inputs.get('barBar')).toBe('barBar-value');
|
||||
});
|
||||
|
||||
it('should properly handle getting/setting properties on the element even if the constructor is not called',
|
||||
() => {
|
||||
// Create a custom element while ensuring that the `NgElementStrategy` is not created
|
||||
// inside the constructor. This is done to emulate the behavior of some polyfills that do
|
||||
// not call the constructor.
|
||||
strategyFactory.create = () => undefined as unknown as NgElementStrategy;
|
||||
const element = new NgElementCtor(injector);
|
||||
strategyFactory.create = TestStrategyFactory.prototype.create;
|
||||
|
||||
element.fooFoo = 'foo-foo-value';
|
||||
element.barBar = 'barBar-value';
|
||||
|
||||
expect(strategy.inputs.get('fooFoo')).toBe('foo-foo-value');
|
||||
expect(strategy.inputs.get('barBar')).toBe('barBar-value');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue