title: How to subscribe to actual view changes in Angular?
body: <p>When working with Angular, the change detection runs and checks if some parts of the UI needs to be refresh/re-render.</p>
  
  <p>There's lifecycle hooks, but... I am not able to find an event/hook/observable to listen for view changes.</p>
  
  <p>What do I call view changes ? When Angular finds that there is changes in the model that need to be updated on the view. It can be because of a variable binding, or any expression. When relying on <code>ngOnChanges</code> lifecycle hook, we are only notified about <code>@Input</code> changes. But changes can come from various sources.</p>
  
  <p>See <a href="https://plnkr.co/edit/dJTB4B1S4pEKEKk6O9Z0?p=preview" rel="nofollow noreferrer">this plunker</a> for a basic implementation. You can open the console to see <code>console.log</code> in the <code>ngOnChanges</code>.</p>
  
  <p>The <strong>Input value</strong> input changes the value passed to the component with <code>@Input</code>. The <code>ngOnChanges</code> can detect this kind of changes.</p>
  
  <p>The <strong>Service value</strong> input changes a value stocked in some shared service, displayed inside our component. The <code>ngOnChanges</code> does not detect this and if we use <code>OnPush</code> detection strategy, our component won't see this changes.</p>
  
  <p>But in our case, we don't want to use <code>OnPush</code>, and we want to be able to listen to this view change.</p>
  
  <p>In this example, we use a simple input to perform some changes, but in the real world, this can be some async callback...</p>
  
  <p>I look for something generic, provided by the <code>ViewRef</code> or something like that, because it can be any <code>Component</code>s or <code>TemplateRef</code> that perform changes that need to be detected.</p>
  
  <h2>Real use case</h2>
  
  <p>I cannot rely on Component inner implementation or service, it has to be Component agnostic. My real use case is to detect changes in a <code>TemplateRef</code> attached to a <code>@angular/cdk</code> <a href="https://material.angular.io/cdk/overlay/overview" rel="nofollow noreferrer">Overlay</a>. I need to be notified about changes, so I can tell the overlay to update its positioning.</p>
  
  <p><strong>tooltip.directive.ts</strong></p>
  
  <pre><code>@Directive({
      selector: "[appTooltip]"
  })
  export class TooltipDirective implements OnInit, OnDestroy {
  
      @Input("appTooltip") templateRef: TemplateRef&lt;any&gt;;
  
      private _overlayRef: OverlayRef;
      private _portal: TemplatePortal&lt;any&gt;;
  
      constructor(private _viewContainerRef: ViewContainerRef, private _injector: Injector, private _overlay: Overlay) {}
  
      ngOnInit(): void {
          this._overlayRef = this._overlay.create();
          this._portal = new TemplatePortal(this.templateRef, this._viewContainerRef);
      }
  
      @HostListener("mouseenter")
      show() {
          this._overlayRef.attach(this._portal);
      }
  
      @HostListener("mouseleave")
      hide() {
          this._overlayRef.detach();
      }
  
      ngOnDestroy(): void {
          this._overlayRef.dispose();
      }
  
      /** I need to call this when changes are detected inside the templateRef. */
      onTemplateChange() {
          this._overlayRef.updatePosition();
      }
  }
  </code></pre>
  
  <p><strong>app.component.html</strong></p>
  
  <pre><code>&lt;ng-template #myTemplate&gt;
      &lt;h3&gt;Some {{ variable }} bindings&lt;/h3&gt;
      &lt;app-custom-component [withInput]="someVariable"&gt;&lt;/app-custom-component&gt;
      &lt;app-other-component&gt;&lt;/app-other-component&gt;
  &lt;/ng-template&gt;
  
  &lt;p&gt;Show tooltip when hover &lt;span [appTooltip]="myTemplate"&gt;this&lt;/span&gt;.&lt;/p&gt;
  </code></pre>
  
  <p>In this example, the <code>ng-template</code> element can contain anything the developer wants, and the <code>TooltipDirective</code> is not aware of what you can put inside the <code>ng-template</code>.</p>
  
  <p>The <code>CustomComponent</code> can update its view base on anything you want, and the <code>ngOnChanges</code> isn't necessarily called. But its view is updated, so Angular knows it needs to update the template.</p>