Skip to content

Commit 363f14c

Browse files
gkalpakkara
authored andcommitted
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
1 parent a9edbc3 commit 363f14c

File tree

2 files changed

+22
-0
lines changed

2 files changed

+22
-0
lines changed

packages/elements/src/create-custom-element.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,9 +187,15 @@ export function createCustomElement<P>(
187187
inputs.map(({propName}) => propName).forEach(property => {
188188
Object.defineProperty(NgElementImpl.prototype, property, {
189189
get: function() {
190+
if (!this.ngElementStrategy) {
191+
this.ngElementStrategy = strategyFactory.create(config.injector);
192+
}
190193
return this.ngElementStrategy.getInputValue(property);
191194
},
192195
set: function(newValue: any) {
196+
if (!this.ngElementStrategy) {
197+
this.ngElementStrategy = strategyFactory.create(config.injector);
198+
}
193199
this.ngElementStrategy.setInputValue(property, newValue);
194200
},
195201
configurable: true,

packages/elements/test/create-custom-element_spec.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,22 @@ if (browserDetection.supportsCustomElements) {
9494
expect(strategy.inputs.get('fooFoo')).toBe('foo-foo-value');
9595
expect(strategy.inputs.get('barBar')).toBe('barBar-value');
9696
});
97+
98+
it('should properly handle getting/setting properties on the element even if the constructor is not called',
99+
() => {
100+
// Create a custom element while ensuring that the `NgElementStrategy` is not created
101+
// inside the constructor. This is done to emulate the behavior of some polyfills that do
102+
// not call the constructor.
103+
strategyFactory.create = () => undefined as unknown as NgElementStrategy;
104+
const element = new NgElementCtor(injector);
105+
strategyFactory.create = TestStrategyFactory.prototype.create;
106+
107+
element.fooFoo = 'foo-foo-value';
108+
element.barBar = 'barBar-value';
109+
110+
expect(strategy.inputs.get('fooFoo')).toBe('foo-foo-value');
111+
expect(strategy.inputs.get('barBar')).toBe('barBar-value');
112+
});
97113
});
98114
}
99115

0 commit comments

Comments
 (0)