question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

External angular elements don't detect changes of deferred data after first instantiation

See original GitHub issue

I’m submitting a…


[ ] Regression (a behavior that used to work and stopped working in a new release)
[x] Bug report  
[ ] Performance issue
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead see https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question
[ ] Other... Please describe:

Current behavior

When dynamically loading an angular elements custom element from an external source (i.e. not a custom element that is defined in the same angular app, but say from assets or some url), the first time it’s rendered, everything works as usual. The second etc. time it’s rendered, all data that is set in the component is rendered fine as well, but change detection does not work anymore, so if data is changed by an http request or a timeout, the changes are not displayed.

To work around this issue, ChangeDetectorRef has to be injected into the external custom element component and detectChanges has to be called once all data is available.

Expected behavior

The change detection should work on subsequent instances just as in the first one without manually calling ChangeDetectorRef.detectChanges().

Minimal reproduction of the problem with instructions

i don’t know how to create a multi-project demo on stackblitz, so here’s here are the steps to reproduce:

ng new custom-element-one --prefix ce1
cd custom-element-one
ng add @angular/elements
npm install @webcomponents/custom-elements --save
  • modify app.module.ts to register custom element
const element = createCustomElement(AppComponent, { injector: this.injector });
customElements.define('custom-element-one', element);
  • in the component, set some data deferred with http request or setTimeout and make sure it’s bound in the template:
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'ce1-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  title = 'custom-element-one';

  ngOnInit(): void {
    setTimeout(() => this.title = 'custom-element-one updated', 1000);
  }
}
  • build/concat etc.
  • create a new standard angular project and put the output of custom-element-one into assets
  • load the custom element using script tag(s), createElement and appendChild similar to this:
  appendCustomElementWithUrls(name: string, urls: string[], target: HTMLElement) {
    if (!customElements.get(name)) {
      for (const url of urls) {
        const script = document.createElement('script');
        script.src = url;
        document.head.appendChild(script);
      }
    }

    const component = document.createElement(name);
    target.appendChild(component);
  }

What is the motivation / use case for changing the behavior?

External custom elements should behave the same if they are added to the DOM once or twice.

This works:

import { Component, OnInit, ChangeDetectorRef, Input } from '@angular/core';

@Component({
  selector: 'ce1-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  @Input()
  title = 'custom-element-one';

  constructor(private cd: ChangeDetectorRef) {} // <-- inject ChangeDetectorRef

  ngOnInit(): void {
    setTimeout(() => {
      this.title = 'custom-element-one updated';
      this.cd.detectChanges(); // <-- call detectChanges to update UI
    }, 1000);
  }
}

Environment


Angular version: 6.2.3


Browser:
- [x] Chrome (desktop) version 69.0.3497.100
- [ ] Chrome (Android) version XX
- [ ] Chrome (iOS) version XX
- [x] Firefox version 61.0.1
- [ ] Safari (desktop) version XX
- [ ] Safari (iOS) version XX
- [ ] IE version XX
- [x] Edge version 40.15063.674.0
 
For Tooling issues:
- Node version: v10.4.1
- Platform: Windows 10 

Others:

i’ll continue looking into this, but since i’m not familiar with the angular code base, any hint on where to start looking would be helpful.

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Comments:5 (1 by maintainers)

github_iconTop GitHub Comments

8reactions
remackgeekcommented, Oct 16, 2018

This is most likely the same as #24181.

A fix has been committed to zone.js, but not released yet: #1133.

You can verify this by building your element with this library, elements-zone-strategy, which also implements a version of the fix.

2reactions
Hackman-Sanchezcommented, Dec 12, 2018

Same problem! @remackgeek I f*****g love you! I’ve spent days trying to get this sucker to work. Just dropped this in and it works like a charm. Thank you so much!

Read more comments on GitHub >

github_iconTop Results From Across the Web

Angular Element Component doesn't update when I add ...
Therefore, inject ChangeDetectorRef into your custom element and call detectChanges() when mutating your images array, like so:
Read more >
Top 18 Most Common AngularJS Developer Mistakes - Toptal
In this article you will learn about most common AngularJS developer mistakes ... But if the change is to a property of a...
Read more >
Using IntersectionObserver And NgSwitch To Defer Template ...
It just observes the host element using the IntersectionObserver API and then updates an isIntersecting property. And, since we're changing the ...
Read more >
Lazy load Angular Components | juri.dev
As a result, we want to defer the loading of the corresponding JavaScript for that area as much as possible. Maybe we don't...
Read more >
Developer Preview of Standalone Support in Angular Elements
Angular Elements are shipped in a single JavaScript file and behave just as regular HTML elements. They instantiate automatically when they are ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found