2

I’m experimenting with Angular Elements and trying to update an input property programmatically, not by writing it in HTML like <app-foo name="...">.

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';

@Component({
  selector: 'foo',
  template: `foo works! {{ name }}`,
})
export class Foo {
  @Input() name = '';
}

@Component({
  selector: 'app-root',
  template: `
    <h1>Hello from {{ name }}!</h1>
    <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;
    e.name = 'bla'; // property
    e.setAttribute('name', 'bla'); // attribute
  }
}

bootstrapApplication(App);

I expect the <app-foo> element to display foo works! bla, but it still shows the default foo works!.

I’ve tried both:

e.name = 'bla';
e.setAttribute('name', 'bla');

but neither triggers Angular’s change detection.

Question: How can I properly set an @Input() property on an Angular custom element created with @angular/elements so the component updates its template when done programmatically?

Stackblitz Demo

1
  • I don't understand what you are trying to do. Normally with angular your tag would look like this: <app-foo [name]="'bla'"></app-foo>, to get you the same result, and no typescript or javascript needed. Commented Nov 1 at 1:56

1 Answer 1

3

Just define the element and then you should/could wait a microtask so angular upgrades it before setting the input like this: Hope this works!

export class App {
  name = 'Angular';
  injector = inject(Injector);

  constructor() {
    const el = createCustomElement(Foo, { injector: this.injector });
    customElements.define('app-foo', el);

    queueMicrotask(() => {
      const e = document.querySelector('app-foo') as HTMLElement;
      e.setAttribute('name', 'bla'); // trigger
    });
  }
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.