I have a main component in which there are two components: headerTable, rowTable.
In headerTable, my table column naming is the checkbox, which, when checked, selects all the rows in rowTable (and vice versa). In rowTable there is also a checkbox (it is this checkbox that will stand out to select a row). I want to do the following script:

  1. Click on the selection of all lines (in the headerTable click on the checkbox), and remove from the selection any of the lines.
  2. After I remove the checkbox in any line, the headerTable should remove the checkbox.

I tried to do this through the decorator Input, but apparently, because of different contexts, then the input does not work.

@Component({ selector: 'headerTable', template: '<input type="checkbox" [ngModel]="allItems" (ngModelChange)=onChange($event)>' }) export class HeaderComponent { @Input() allItems: boolean; onChange(flag: boolean) { this.allItems = flag; } } ... @Component({ selector: 'row', template: '<input type="checkbox" (change)="onChange($event)">' }) export class RowComponent { @Output() checkedItem = new EventEmitter<number>(); onChange(flag: boolean) { this.checkedItem.emit(5); } } ... 

page.html:

 <headerTable [allItems]="allItems"></headerTable> <row (checkedItem)="checkedItem($event)"></row> 

page.ts:

  checkedItem(id: number) { this.allItems = false; } 

    1 answer 1

    It is a bit hard for me to understand the question, having limited information. But I understand from the question that you are trying to force to communicate 2 components that are at level 1 through the parent:

    enter image description here

    It is precisely at such moments that the state services come to the rescue, because the usual communication is much harder to break. At your place I would create such a service:

     @Injectable() export class TableService implements OnDestroy { public allItemsSelected$ = new BehaviorSubject(false); public ngOnDestroy(): void { this.allItemsSelected$.complete(); } public setAllItemsSelectedTo(selected: boolean): void { this.allItemsSelected$.next(selected); } } 

    Then I would add the service to the providers of the parent component, which is on top of app-table-row and app-table-header :

     @Component({ selector: 'app-parent', viewProviders: [TableService] }) export class ParentComponent { constructor(private tableService: TableService) {} public get allItemsSelected$(): Observable<boolean> { return this.tableService.allItemsSelected$.asObservable(); } } 

    In the component template, we already exclude communication through ordinary variables:

     <app-table-header [allItems]="allItemsSelected$ | async"></app-table-header> 

    In the method that listens for the ngModelChange event ngModelChange we also replace the variable with the event generation:

     constructor(private tableService: TableService) {} public onChange(selected: boolean): void { this.tableService.setAllItemsSelectedTo(selected); } 

    Similarly, inject this service into the app-table-row component and when clicking on the checkbox — if the event value is false , then we generate an event for the app-table-header , this is the solution to your second question:

    After I remove the checkbox in any line, the headerTable should remove the checkbox.

     @Component({ selector: 'app-table-row' }) export class TableRowComponent { constructor(private tableService: TableService) {} public onChange(selected: boolean): void { if (selected) { return; } this.tableService.setAllItemsSelectedTo(selected); } } 

    PS - checkedItem no longer necessary to generate a checkedItem event.

    • Thanks, there was an idea about the service, but is it all redundant for one small logic - to remove the checkbox? - bruce 2:38 pm
    • and in what redundancy? instead of spaggeti with one variable and output, you get total control over business logic, besides Mishko did not come up with services (they are not for fools)? :) - overthesanity pm