3

I have a parent component which has a title field. This field is passed to the child component using the @input decorator. In my child component i have added some logic to manipulate the title value before showing it in my HTML.

Because my logic is in ngInit hook of the child component, only the first time the title field is reflected correctly. Changes that happen from then onwards do not reflect. Now i know this is because ngInit is called once but how do i trigger a change from my parent to child telling it to recheck the value?

EDIT Added code snippet

Header (child) component

export class HeaderComponent implements OnInit {
@Input() title: string | Array<any>;

titleType = 'string';
tabletTitle: string | Array<any>;


constructor() { }

ngOnInit() {

    if ( typeof this.title == 'object' ) {
        this.titleType = 'array';

        // For tablet - only send the last most array item
        this.tabletTitle = [this.title[this.title.length - 1]];     // Has to be in the form of array (to be consistent with other orange header data type)
    } else {
        // Title is string - same for tablet
        this.tabletTitle = this.title;
    }

    // Temporary to show filter button on catalog page
    if ( this.page == 'catalog' ) {
        this.showFilterButton = true;
    }
}
}

Header template

    <h1 *ngIf="titleType=='string'">{{title}}</h1>
    <h1 *ngIf="titleType=='array'">
        <ul class="header-breadcrumb">
            <template ngFor let-item [ngForOf]="title | keyValueObject">
                <li title="{{item.value['title']}}">
                    <a *ngIf="item.value['link']" [routerLink]="item.value['link']">{{item.value['title']}}</a>
                    <span *ngIf="!item.value['link']">{{item.value['title']}}</span>
                </li>
                <li *ngIf="!last" class="separator"></li>
            </template>
        </ul>
        <ul class="header-breadcrumb tablet">
            <li *ngFor="let item of tabletTitle | keyValueObject">
                <a *ngIf="item.value['link']" [routerLink]="item.value['link']">{{item.value['title']}}</a>
                <span *ngIf="!item.value['link']">{{item.value['title']}}</span>
            </li>
        </ul>
    </h1>

Parent component

if ( this.parentCatId ) {
    // Push Parent Category name in header title
    this.headerTitle.push({title: 'Parent'});
}

if ( this.subCatId ) {          
    // Push Sub Category name in header title
    this.headerTitle.push({title: 'Child'});
}

Parent component HTML

<app-header [title]="headerTitle"></app-header>
1
  • Provide some code snippet or create a plunker/ jsfiddle. Commented Sep 29, 2016 at 11:44

1 Answer 1

10

You can either make @Input() title: string | Array<any> a setter or use ngOnChanges() instead of ngOnInit(). ngOnChanges() is called every time an @Input() is updated.

@Input() set title(value: string | Array<any>) {
  ...
}

or

ngOnChanges() {

    if ( typeof this.title == 'object' ) {
        this.titleType = 'array';

        // For tablet - only send the last most array item
        this.tabletTitle = [this.title[this.title.length - 1]];     // Has to be in the form of array (to be consistent with other orange header data type)
    } else {
        // Title is string - same for tablet
        this.tabletTitle = this.title;
    }

    // Temporary to show filter button on catalog page
    if ( this.page == 'catalog' ) {
        this.showFilterButton = true;
    }
}
Sign up to request clarification or add additional context in comments.

20 Comments

Thanks for your quick reply. Does setting the @Input as set have any performance impacts or both methods work the same way? :)
Not, having it as setter doesn't have any performance impact. The setter is just called once every time change detection recognized a change on the parents headerTitle property.
For some crazy reason my IDE (Sublime text 3) is not recognizing the @Input set syntax. Marks it in red :(
Sorry, no idea about TS with Sublime 3
Well i have used the ngOnChanges method and its detecting the changes. However for some bizarre reason its not re-rendering it in the View layer (DOM), any clues why that might be?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.