12
votes

I am trying to pass a function to a child component. Passing the function works fine. Problem is, if I want to change property values of the parent component, this wont work since 'this' is not referencing to the parent component, but to the child component (DatagridComponent in my case)

The context of this seems to be the problem. See comments in code below.

Parent component:

@Component({
  selector: 'app-user-management',
  templateUrl: './user-management.component.html',
  styleUrls: ['./user-management.component.css'],
})
export class UserManagementComponent implements OnInit {
  showUserDetails: boolean: false;
  showUsergroupDetails = false;

  onSelectUser() {
    this.showUsergroupDetails = false;
    this.showUserDetails = true;
    console.log(this.showUsergroupDetails); // prints false, as expected
    console.log(this.showUserDetails); // prints true, as expected
    console.log(this); // prints DatagridComponent :(
}

HTML, passing onSelectUser as function:

<app-datagrid [onSelection]="onSelectUser"></app-datagrid>

Child component:

@Component({
  selector: 'app-datagrid',
  templateUrl: './datagrid.component.html',
  styleUrls: ['./datagrid.component.css']
})
export class DatagridComponent implements OnInit {
  @Input() onSelection: () => {};

  onSelectListItem(item: any) {

    // some code

    if (this.onSelection) {
      this.onSelection(); // is executed, results see comments in parent component
    }
  }
}

HTML of child component:

<div *ngFor="let item of items" (click)="onSelectListItem(item)">
   ....
</div>

How can I accomplish this?

2
You might want to look at the Component Interaction docs, there are a bunch of different ways to implement interactions between parent-child components - Andrei Matracaru

2 Answers

22
votes

The question is more about this context, which you can fix it this way :

onSelectUser = ()=>{ // note this part 
    this.showUsergroupDetails = false;
    this.showUserDetails = true;
    console.log(this.showUsergroupDetails); // prints false, as expected
    console.log(this.showUserDetails); // prints true, as expected
    console.log(this); // prints DatagridComponent :(
}

We're using fat arrow to keep the context of the current component inside the function

13
votes

Use Output event to communicate from child component to parent component. Use Input property binding to pass data from parent to child

Html

<app-datagrid (onSelection)="onSelectUser($event)"></app-datagrid>

Component

@Component({
  selector: 'app-datagrid',
  templateUrl: './datagrid.component.html',
  styleUrls: ['./datagrid.component.css']
})
export class DatagridComponent implements OnInit {
  @Output() onSelection: EventEmitter<any> = new EventEmitter();

  onSelectListItem(item: any) {
     this.onSelection.emit(item);
  }
}

//app-user-management method will receive item object
onSelectUser(item: any) {
   //here you would have item object.
}

See Also Component Interaction