6

I have an array:

const a = [apple,ball,cat]

I'm passing this to two components:

<app-header [appData]="data"  ></app-header>

<list-todo [appData]="data" [getData]="getData" [setData]="setData" ></list-todo>

In the appHeader component,

export class appHeader  {
  @Input('appData') data : any

  clear(){
    this.data = []
  }
}

performing the clear() function is not affecting the array in the listTodo component. Is there any way to solve that issue?

I also checked two way binding with attributes but nothing worked anymore!

2 Answers 2

7

Input binding sends data to child component in unidirectional way, so when we modify child component data it doesn't flow up. Since you're assigning new blank array to this.appData in child component(it doesn't flow up). In this case you could consider changing your appData property binding to be two way binding. So that anything updates in child component will update the relative property in parent component, but yes it doesn't happen magically. You have to update the data manually ;)

To make the same thing working, you have to emit changed copy of object to parent component via Output binding like [(appData)]="data" (it uses EventEmitter to emit data to parent compoent).

AppComponent Template

 <app-header [appData]="data"  ></app-header>
<list-todo [(appData)]="data"></list-todo>

ListTodoComponent

@Component({
  selector: 'list-todo',
  template: `
     <ul>
      <li *ngFor="let item of appData">{{item}}</li>
     </ul>
     <button (click)="clear()">Clear</button>
  `
})
export class ListTodoComponent { 
  @Input() appData;
  @Output() appDataChange: EventEmitter<any> = new EventEmitter<any>();

  clear(){
    this.appData = [];
    //this emit is important to send data back to parent.
    //make sure you should have `Change` prefix to bounded value, like `appData` + `Change` = `appDataChange`, 
    //which ultimately saves few lines of code.
    this.appDataChange.emit(this.appData); 
  }
}

Demo Here

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

1 Comment

Your comment here saved me some headache, I cannot believe that the name must be the same as the property and end with Change - no other name is allowed! Renaming this to appDataChanged (with a 'd' on the end) makes it not return a value to the parent!
6

By doing this.data = [], you're not emptying your array, but replacing it with a new instance. Your parent component and the other child component are still referring to the original instance, which results in the behavior you describe.

One solution is to empty the original array instead of replacing it:

clear() {
    this.data.length = 0;
}

In doing so, all components will keep referring to the same array instance, and its state will be correctly reflected.

1 Comment

Thanks Bro it's Working fine !!

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.