I’m trying to pass an object as an input to an Angular custom element created with @angular/elements, not via HTML attributes (since setAttribute only supports strings).
Here’s a minimal example:
import {
Component,
Input,
Injector,
inject,
NO_ERRORS_SCHEMA,
} from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';
import { createCustomElement } from '@angular/elements';
import { CommonModule } from '@angular/common';
@Component({
imports: [CommonModule],
selector: 'foo',
template: `foo works! {{ data.test() | json }}`,
})
export class Foo {
@Input() name = '';
@Input() data: any;
}
@Component({
selector: 'app-root',
template: `
<h1>Hello from {{ name }}!</h1>
<a target="_blank" href="https://angular.dev/overview">
Learn more about Angular
</a>
<app-foo></app-foo>
`,
schemas: [NO_ERRORS_SCHEMA],
})
export class App {
name = 'Angular';
injector = inject(Injector);
constructor() {
const el = createCustomElement(Foo, { injector: this.injector });
customElements.define('app-foo', el);
const e = document.querySelector('app-foo') as any;
queueMicrotask(() => {
e.data = {
test: () => {
console.log('in test');
return 'test';
},
};
});
}
}
bootstrapApplication(App);
I expect the <app-foo> element to print "foo works! test" in the template and log "in test" to the console.
However, the template doesn’t update — it looks like the @Input() isn’t detecting the object assignment.
Question: How can I pass a complex object (with functions or nested data) programmatically to an Angular Element so that the component receives it and the template updates?
Notes:
- Using
setAttribute()only allows passing strings, not objects. - I’m using Angular 20.0.0.
- Tested on StackBlitz.