Search code examples
angularangular2-componentsangular2-databinding

Angular sub-component binding doesn't work


I'm trying to display message in sub-component using dependency injection.

Here is first.component.ts:

import { Component } from '@angular/core';
import { SecondComponent } from './second.component';

@Component({
  selector: 'app-first',
  template: `<button (click)="onClick()">Yes</button>
             <app-second></app-second>
             `,
  providers: [ SecondComponent ]
})

export class FirstComponent {
  constructor(private secondComponent: SecondComponent) {}
  onClick() {
    this.secondComponent.Show('Test message');
  }
}

Here is second.component.ts:

import { Component } from '@angular/core';

@Component({
  selector: 'app-second',
  template: '<p>{{ _message }}</p>'
})

export class SecondComponent {
  _message: string;

  Show(message: string) {
    this._message = message;
  }
}

Console show no errors, but {{ _message }} in browser is not updated.

Where am I wrong?


Solution

  • You can do this one of two ways; expose a public method in your SecondComponent or use @Input as yurzui mentioned

    Public method in child component

    Change your FirstComponent to

    @Component({
      selector: 'app-first',
      template: `<button (click)="onClick()">Yes</button>
                 <app-second #second></app-second>
                 `,
      providers: [ SecondComponent ]
    })
    
    export class FirstComponent {
      @ViewChild('second') second;
      constructor(private secondComponent: SecondComponent) {}
      onClick() {
        second.Show('Test message');
      }
    }
    

    and mark the Show method in your SecondComponent as public

    or Use @Input to pass data directly to your child component

    @Component({
      selector: 'app-first',
      template: `<button (click)="onClick()">Yes</button>
                 <app-second message="message"></app-second>
                 `,
      providers: [ SecondComponent ]
    })
    
    export class FirstComponent {
      public message: string;
      constructor(private secondComponent: SecondComponent) {}
      onClick() {
        this.message = 'Test message';
      }
    }
    
    import { Component } from '@angular/core';
    
    @Component({
      selector: 'app-second',
      template: '<p>{{ _message }}</p>'
    })
    
    export class SecondComponent {
      @Input() _message: string;
    }