Skip to content

Instantly share code, notes, and snippets.

@tomastrajan
Last active April 21, 2022 11:36
Show Gist options
  • Save tomastrajan/20367ff13da49d6124d87415222e1308 to your computer and use it in GitHub Desktop.
Save tomastrajan/20367ff13da49d6124d87415222e1308 to your computer and use it in GitHub Desktop.
Angular elements change detection problem
/*
This is then built as Angualr element
with
ngDoBootstrap() {
const ElementExample = createCustomElement(ElementExampleComponent, { injector: this.injector });
customElements.define('element-example', ElementExample);
}
and used with
<element-example value="abc"></element-example> WORKS = triggers ngOnChanges + triggers backend request + displays data
<element-example [value]="someProp"></element-example> DOES NOT WORK = triggers ngOnChanges + triggers backend request + DOES NOT display data
( only works with "tap( () => setTimeout(() => this.cdr.detectChanges()))" )
*/
import { Component, OnInit, OnChanges, Input, ChangeDetectorRef } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { BehaviorSubject, Observable } from 'rxjs';
import { switchMap, filter, tap } from 'rxjs/operators';
@Component({
selector: 'element-example',
template: `
<p>test value: {{ test }} (zone.js sanity check)</p>
<p>sync value: {{ value }} works</p>
<p>async value: {{ value$ | async | json }} does NOT work without manual CD</p>
`
})
export class ElementExampleComponent implements OnInit, OnChanges {
@Input() value: string;
trigger: BehaviorSubject<string> = new BehaviorSubject(undefined);
value$: Observable<any>;
test = 1;
constructor(private httpClient: HttpClient, private cdr: ChangeDetectorRef) {}
ngOnInit() {
console.log('INIT', this.value);
this.value$ = this.trigger.asObservable().pipe(
filter(Boolean),
switchMap(() => this.httpClient.get('https://api.github.com/users/tomastrajan/repos')),
// tap( () => this.cdr.detectChanges()), DOESNT WORK
// tap( () => Promise.resolve()), DOESNT WORK
// tap( () => setTimeout(() => {})), DOESNT WORK
tap( () => setTimeout(() => this.cdr.detectChanges())), // WORKS
tap(a => console.log('LAST OPERATOR', a))
/*
setTimeout(() => {
this.test = 2; WORKS
}, 5000);
*/
);
}
ngOnChanges() {
this.trigger.next(this.value);
}
}
@h4de5
Copy link

h4de5 commented Apr 21, 2022

I know this is pretty old - but is there a solution to this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment