FairSite2C
FairSite2C

Reputation: 155

Why does angular base component html elements not recognize changes to data?

what am i missing here? This is a simplified example of creating an Angular 18 base component and a heir component extending it. Both are standalone. All seems fine in that the heir component sees the base components properties and methods in this. override is required on base methods and properties. Changes to the variables done in either base or heir show up. My problem is the html in base doesn't seem to recognize any changes in the variables. Change the variables in either base or heir and the heir html responds. Not what I expected.

I create a base component QueryBaseComponent

name:string='nancy;

changeName(newName:string){
    this.name = newName;
    console.log(this.name);//shows liberace
}

onClick(event:any){
//always fires even if it is override in heir component
    console.log('base');
}

html

<label>{{name}}</label>  //always shows initial value of nancy, doesn't change
<button (click)="onClick($event)">hit me</button>
<ng-content select="[position=bottom]"></ng-content>

i extend the base component

export class QueryTextComponent extends QueryBaseComponent implements AfterViewInit

ngAfterViewInit(){
    this.changeName('liberace');
}

override onClick(event:any){
//never gets hit
    console.log('heir');
}

html

<app-query-base>
    <div position="bottom">
        <label>{{name}}</label> //shows nancy and then liberace
    </div>
</app-query-base>
    
 

Upvotes: 1

Views: 63

Answers (1)

Naren Murali
Naren Murali

Reputation: 57986

You need to notice, that when you use content projection. The methods inside the content actually still have the original scope that it was declared on. So the HTML inside base component will always call the base component methods.

Since you declared the HTML content(stuff inside app-query-base on QueryTextComponent, it will always have access to the methods of QueryTextComponent.

The best solution is to simply move the button inside the QueryTextComponent so that the chick will call the override method instead of the base method.

<app-query-base>
  <div position="bottom">
    <button (click)="onClick($event)">hit me</button>
    <div><label>{{name}}</label> </div>
  </div>
</app-query-base>

Full Code:

import { Component, AfterViewInit } from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';

@Component({
  selector: 'app-query-base',
  standalone: true,
  template: `
    <label>{{name}}</label>  
    <ng-content select="[position=bottom]"></ng-content>
  `,
})
export class QueryBaseComponent {
  name: string = 'nancy';

  changeName(newName: string) {
    this.name = newName;
    console.log(this.name);
  }

  onClick(event: any) {
    console.log('base');
  }
}

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [QueryBaseComponent],
  template: `
    <app-query-base>
      <div position="bottom">
        <button (click)="onClick($event)">hit me</button>
        <div><label>{{name}}</label> </div>
      </div>
    </app-query-base>
  `,
})
export class App extends QueryBaseComponent implements AfterViewInit {
  ngAfterViewInit() {
    this.changeName('liberace');
  }

  override onClick(event: any) {
    console.log('heir');
  }
}

bootstrapApplication(App);

Stackblitz Demo

Upvotes: 0

Related Questions