21

I want to implement Skrollr as an Angular2 attribute directive.

So, the format may be:

<body my-skrollr>
</body>

However, in order to implement this, I need to be able to detect changes in the DOM in child elements below the containing tag (in this case, <body>), so that I can call skrollr.init().refresh(); and update the library to work with the new content.

Is there a straightforward way of doing this that I'm not aware of, or am I approaching this incorrectly?

Tom Mettam
  • 2,454
  • 1
  • 23
  • 30

1 Answers1

34

Angular does not provide something built-in for that purpose. You can use MutationObserver to detect DOM changes.

@Directive({
  selector: '[my-skrollr]',
  ...
})
class MyComponent {
  constructor(private elRef:ElementRef) {}

  ngAfterViewInit() {
    this.observer = new MutationObserver(mutations => {
      mutations.forEach(function(mutation) {
        console.log(mutation.type);
      });   
    });
    var config = { attributes: true, childList: true, characterData: true };

    this.observer.observe(this.elRef.nativeElement, config);
  }
}
Günter Zöchbauer
  • 490,478
  • 163
  • 1,733
  • 1,404
  • In MutationObserver constructor it should be "mutations" instead of "mutation" – Anton Nikiforov Mar 28 '17 at 20:47
  • thank you for this... Can someone tell me wha th opposite of what this would be... i.e. detecting nothing changed? if that makes sense. lol I need something to turn off the variable. – Christian Matthew Aug 11 '17 at 01:28
  • Perhaps you can check that no mutation event was emitted for a specific amount of time? – Günter Zöchbauer Aug 11 '17 at 09:43
  • @ChristianMatthew - Surely you would simply set a state to "false" and then just change to true when something changes? – Tom Mettam Sep 06 '17 at 20:20
  • 2
    Don't forget to call `this.observer.disconnect();` inside the `ngOnDestroy()` method – Carlo Bos Feb 12 '20 at 00:33
  • Is it safe to use ElementRef.nativeElement? I thought that posed XSS risk for the application. – coder101 Mar 19 '20 at 11:41
  • Using nativeElement is not related to XSS as long as you do not use it to append user-generated content (directly or indirectly) to the DOM. Access to `nativeElement` was frowned upon at the beginning of Angular 2 development because it would be incompatible with server-side rendering and web-worker but they are not used widely anyway and only the few that do need to take care. The current status is as far as I remember, that passing around `nativeElement` is now compatible with SSR/WW, but accessing methods or properties is not. – Günter Zöchbauer Mar 19 '20 at 12:32