Angular 2 - Passing data to Child component after Parent initialisation

后端 未结 5 2010
花落未央
花落未央 2020-12-23 16:58

I have a parent component which is getting data from a server through a service. I need some of this data to be passed to the Child component.

I\'ve been trying to p

相关标签:
5条回答
  • 2020-12-23 17:20
    @Component({
        selector: 'test-child',
        template: `
            <!-- Content for child.... -->
        `
    })
    
    export class ChildComponent implements OnChanges {
        @Input() childData: any;
    
        ngOnChanges() {
            console.log(childData); // logs undefined
        }
    }
    

    This is supposed to be like this, no? I hope this might be the problem.

        ngOnChanges() {
            console.log(this.childData); // reference with this
        }
    
    0 讨论(0)
  • 2020-12-23 17:25

    I'm assuming that the child is getting a subset of the parents data, potentially from a user action (like loading a form when a user clicks on a grid row). In this case I would use an event.

    Have the parent fire an event, maybe dataSelected, and the contents of the event would be the data that was selected.

    Then have the child listen for those events and when fired load the data from the event into the model.

    This will help decouple your components, which always a good idea.

    0 讨论(0)
  • Since data is undefined at start, you can postpone it with *ngIf='data'

    <div *ngIf='data'>
       <test-child [childData]="data"></test-child>
    </div>
    

    Or you can implement ControlValueAccessor on your component and pass it by ngModel with ngModelChange

    <test-child [ngModel]="data?" (ngModelChange)="data? ? data= $event : null"></test-child>
    
    0 讨论(0)
  • 2020-12-23 17:38

    you can use ngOnChanges to get data like below,

     ngOnChanges() {
       if(!!childData){         
            console.log(childData);         
       }
     }
    

    OnChanges

    Angular calls its ngOnChanges method whenever it detects changes to input properties of the component (or directive).

    Read more about it here.

    Update

    ngOnChanges will only fire if you change entire object, if you want to just update property of the bound object not entire object you have two options,

    1. either bind the property directly in the template, make sure to use ? like {{childData?.propertyname}}

    2. or you can create a get property depending upon childdata object,

      get prop2(){
        return this.childData.prop2;
      }
      

    Copmlete Example,

    import { Component, Input } from '@angular/core';
    
    @Component({
      selector: 'my-app',
      template: `<h1>Hello {{name}}</h1>
      <child-component [childData]='childData' ></child-component>
      `
    })
    export class AppComponent { 
      name = 'Angular'; 
      childData = {};
      constructor(){
        // set childdata after 2 second
        setTimeout(() => {
          this.childData = {
            prop1 : 'value of prop1',
            prop2 : 'value of prop2'
          }
        }, 2000)
      }
    }
    
    @Component({
      selector: 'child-component',
      template: `
        prop1 : {{childData?.prop1}}
        <br />
        prop2 : {{prop2}}
      `
    })
    export class ChildComponent { 
      @Input() childData: {prop1: string, prop2: string};
    
      get prop2(){
        return this.childData.prop2;
      }
    }
    

    Here is the Plunker!

    Hope this helps!!

    0 讨论(0)
  • 2020-12-23 17:38

    At the time your ChildComponent (you called it also ParentComponent, but i guess it's a typo) gets initialized and executes its ngOnInit, there is no data in your parent avaible since your service will still be out getting your data. Once your data is there it will be pushed to the child.

    What you can do depends on your usecase..

    If you just want to display the data in your ChildComponent template, you could use the elvis operator (?). Something like: {{ childData?}} or {{ childData?.myKeyName }}...

    If you want to do some other stuff, you may use a setter in your ChildComponent. It will intercept the input change and give you the opportunity to alter/test/"do what ever you want" with it before you do other things with it in your ChildComponent.. eg.:

    @Component({
        selector: 'test-child',
        template: `
            <!-- Content for child.... -->
        `
    })
    
    export class ChildComponent implements OnInit {
        private _childData: any;
        @Input()
        set childData(parentData: any) {
            // every time the data from the parent changes this will run
            console.log(parnetData);
            this._childData = parentData; // ...or do some other crazy stuff
        }
        get childData(): any { return this._childData; }
    
        ngOnInit() {
          // We don't need it for that...
        }
    }
    

    or use ngOnChanges as Madhu mentioned.

    You also might want to take a look at the cookbook entry for Component Communication in the official docs.

    0 讨论(0)
提交回复
热议问题