Phil
Phil

Reputation: 758

Angular 2 - Component Inheritance - base class variable not propagated to base template

Is there something special to do when using Component Inheritance ?

edit : this concerns INHERITANCE, not parent/child view/components communication

as I try to hide a div defined in the base class template, it does not work

in the page, the variable is not even updated even if it gets modified in the code

1st, I tried with [hidden] and *ngIf

then I tried using changeDetectorRef but it does not do anything

it seems the value is not propagated to the template

base class:

@Component({
    selector: 'my-content',
    templateUrl: './content.component.html',
    styleUrls: ['./content.component.css'],
})    
export class ContentComponent implements OnInit {

    protected overlayVisible:boolean;

    constructor(....){...}

    ngOnInit() {
    }

    showOverlay()
    {
        this.overlayVisible=true; <<<<<<<<<<<<<< THESE GET CALLED
    }

    hideOverlay()
    {
        this.overlayVisible=false; <<<<<<<<<<<<<< THESE GET CALLED
    }
}

base template (content.component.html):

<div>
    <div class="contentMainDiv">
        <div class="contentBodyDiv"><ng-content select="[body]"></ng-content></div>
        <div [innerHTML]=" overlayVisible?'true':'false' "></div> /// DEBUG DIV
        <div [hidden]="!overlayVisible" class="contentOverlay" >
            <my-wait></my-wait>
        </div>

    </div>
</div>

child component :

export class CustomersComponent extends ContentComponent implements OnInit {

    private customers: any;

    constructor(
        private customersService: CustomersService,
        injector:Injector
        ) { super(injector); }

    getCustomers() {
        this.showOverlay();

        this.customersService.getCustomers().subscribe((customers: any) => {
            this.customers = customers;
            this.hideOverlay();
        });
    }

child template :

<my-content>
    <div body>
        <div *ngIf="customers">
            some table ...
        </div>
    </div>
</my-content>

what am I missing

is there something special to do when we use component inheritance ?

thanks

Upvotes: 2

Views: 4405

Answers (4)

Phil
Phil

Reputation: 758

the way I made it work is by removing the exportas

<my-base-frame #baseFrame>
...
</my-base-frame>

in the code

@ViewChildren('baseFrame') baseFrames; // finaly found how to get base class instance

...

this.baseFrames.changes.subscribe( (_comps: QueryList <any>)
    {
        if(this.baseFrames.first && !this.baseFrame)
        {
            this.baseFrame=this.baseFrames.first;
            ...
        }
    })

Upvotes: 0

Phil
Phil

Reputation: 758

the (partial) answer is this :

the overriding class is having its own template instance so one have to link the base template to it

detail : https://github.com/angular/angular/issues/18920

so in the base class you add to the component anotations:

 exportAs: 'myContentComponent', 

and the child class must have his template referencing it

 template: `<my-baseclass-component #myContentComponent>..
            <button (click)="myContentComponent.showOverlay()">toggle</button>

now I have no idea how to call that function from typescript child component to fit the question above

if anyone could answer, I'll update this answer

thanks

Upvotes: 2

Dmitry Shutov
Dmitry Shutov

Reputation: 96

Variables in your base class cannot be affected by executing method in child class. When you execute this.showOverlay() it modified this.overlayVisible in the scope of child component. Use component interactions https://angular.io/guide/component-interaction#parent-listens-for-child-event

Upvotes: 1

Julius Dzidzevičius
Julius Dzidzevičius

Reputation: 11000

You want to call a method that sits in parent component, right? Then EventEmitter can help you:

<child-component (showOverlay)="showOverlay()" (hideOverlay)="hideOverlay()"></child-component>

Child component:

import { EventEmitter, Output, OnDestroy } from '@angular/core';

 @Output showOverlay = new EventEmitter();
 @Output hideOverlay = new EventEmitter();


 getCustomers() {
    this.showOverlay.emit();
 <....rest of your code.....>

ngOnDestroy() {
   this.hideOverlay.emit();
}

I assume that you destroy child component and then want to hide overlay, so emitted hideOverlay in ngOnDestroy.

Upvotes: 1

Related Questions