0

I want to set the child component property from parent component

parent.component.html

<div>
<child-detail #myCarousel [childList]="detail.List" ></child-detail>
</div>  

parent.component.ts

@Component({
  selector: "parent",
  templateUrl: "./parent.component.html",
 })  
export class AppComponent { 
  public detail; // it is of JSON type
}

child.component.ts

@component({
 selector:'child-detail',
 templateUrl: './child.component.html'
})
export class ChildDetailComponent{
  @Input() public childList;   // that list of array type
}

child.component.html

<div *ngFor = "let list of childList">
 <li>{{list}} </li>
</div>

I know i can set this property by @Input() binding , but this will set only at the time of initializing of the component , I want to set it programmaticaly in intermediate at some point .

I know I can access this child property in parent using

@ViewChild(ChildDetailComponent) childDetailComponent: ChildDetailComponent;
console.log(this.childDetailComponent.childList);

But I want to set it programatically at any event of parent.

12
  • 2
    So why can't you use input properties and populate that input property on an event on parent? Commented Dec 4, 2018 at 7:05
  • *but this will set only at the time of initializing of the component *?? This is not true. It will be set whenever you change the prop in parent. Read about ngOnChanges() hook Commented Dec 4, 2018 at 7:07
  • @xyz can you please elaborate this. Commented Dec 4, 2018 at 7:07
  • when ever the value of childList change in the parent component the value of the childList in the childComponent will also be updated but if you went to change the value of childList in the parent component when the value of childList change in the child component you can use set method for the childList Input Commented Dec 4, 2018 at 7:10
  • Just a note. You're using TypeScript. TypeScript has types. So why, instead of using // that list of array type, don't you properly declare the type of the variable? Commented Dec 4, 2018 at 7:27

3 Answers 3

1

You can use service for the sharing data pragmatically.

Step 1: Create data share service.

import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';

@Injectable()
export class DataService {

  private messageSource = new BehaviorSubject('default message');
  currentMessage = this.messageSource.asObservable();

  constructor() { }

  changeMessage(message: string) {
    this.messageSource.next(message)
  }

} 

Step 2: Change message

export class ParentComponent implements OnInit {

  message:string;

  constructor(private data: DataService) { }

  ngOnInit() {
   this.data.changeMessage("Hello from Sibling")
  }

Step 3: Get message

export class ChildComponent implements OnInit {

  message:string;

  constructor(private data: DataService) { }

  ngOnInit() {
    this.data.currentMessage.subscribe(message => this.message = message)
  }

}
Sign up to request clarification or add additional context in comments.

1 Comment

You should add DataService at providers: [DataService] in app.module.ts otherwise following error NullInjectorError: No provider for DataService! will come.
1

I'm not sure how you're doing it without using the @Input property.

Whenever the input you've passed to it changes, it will also reflect in the Child Component. You can track it in ngOnChanges in the Child Component. Just try logging to the console

Give this a try:

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

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  detail: any = {
    childList: []
  };

  setChildList() {
    this.detail.childList = [
      { id: 1, name: 'John' },
      ...
    ];
  }

}

And in the template:

<button (click)="setChildList()">Set Child List</button>
<hello [childList]="detail.childList"></hello>

Here the @Input property is changing on the Click of the Button. But in your case, you can simply call the setChildList method your event.


Here's a Working Sample StackBlitz for your ref.

5 Comments

But ngOnChanges() detect only primary type change so this life cycle hook will run , but in case of object property changes it will not run .
Judging from what you're saying, looks like you have a ChangeDetectionStrategy of OnPush on your Component. In that case it will run only if there's a change in the reference of the @Input Object.
What you're saying doesn't make any sense in that case. I'm passing the input to the child component just like you want to. And if you have a look at my StackBlitz Sample, it's passing the value as expected and updating it in the Child Component.
you can check the following URL concretepage.com/angular-2/… . ( in case of object property change this technique will not work)
Did you even check the Sample StackBlitz? Passing Objects as @Input is exactly what I'm doing there. And it's detecting the changes and updating the Child Component as well as the view.
0

use @input in child component. can listen to the changes in child component using ngOnChanges.

@Input() name: string;

ngOnChanges(changes: SimpleChanges) {
  const name: SimpleChange = changes.name;
  console.log('prev value: ', name.previousValue);
  console.log('got name: ', name.currentValue);
}

working stackblitz

Comments

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.