Angular 8 компонентов, вложенных в один эмиттер событий компонента - PullRequest
4 голосов
/ 29 мая 2020

Я использовал компонент, вложенный в тот же компонент. когда я меняю флажок в прикрепленной функции родительского компонента, которая вызывается правильно, и эмиттер событий работает нормально, но когда я меняю дочерний флажок, прикрепленная функция была запущена, но эмиттер событий недоступен (насколько мне известно, когда-либо значение не привязано к дочернему). Я хочу выдавать данные, когда меняю флажок в дочернем элементе.

Если кто знает ответ, помогите пожалуйста решить эту проблему. И какова терминология для использования компонента, вложенного в один и тот же компонент?

Благодарю

Это ссылка stackblitz https://stackblitz.com/edit/angular-material-normal-tree (проверьте консоль)

tree.component.ts

import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';

@Component({
  selector: 'app-tree',
  templateUrl: './tree.component.html',
  styleUrls: ['./tree.component.css'],
})

export class TreeComponent {
  @Input() treeData: any;
  @Output() toggleEmitter: EventEmitter<any> = new EventEmitter();

  constructor() {}

  toggleChild(node) {
    console.log('from tree start');
    console.log(node);
    console.log('from tree end');
    this.toggleEmitter.emit(node);
    // if ('children' in node && node.children.length) {
    //   node.isExpand = !node.isExpand;
    // }
  }

  test(node, i) {
    node.parentIndex = i;
    console.log(node);
    // this.toggleEmitter.emit(node);
  }

  CBchangeEvent(node) {
    console.log(node);
    this.toggleEmitter.emit(node);
  }

}

tree.component. html

<ul *ngIf="treeData">
    <li *ngFor="let node of treeData;let i = index;">
        <button mat-icon-button="" mattreenodetoggle="" class="mat-icon-button" (click)="toggleChild(node)">
        <span class="mat-button-wrapper">
          <mat-icon class="mat-icon material-icons" role="img" aria-hidden="true"> 
            {{node.isExpand != 0 ? 'expand_more' : 'chevron_right'}} 
          </mat-icon>
        </span>
      </button>
        <mat-checkbox class="checklist-leaf-node" (change)="CBchangeEvent(node)">{{node.name}}</mat-checkbox>
        <app-tree *ngIf="node.isExpand" [treeData]="node.children" (toggleEmitter)="test(node,i)"></app-tree>
    </li>
</ul>

tree.component. css

ul {
    list-style-type: none !important;
}

tree.module.ts

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { TreeComponent } from './tree.component';
import {
  MatIconModule, MatCheckboxModule, MatFormFieldModule, MatButtonModule
} from '@angular/material';


@NgModule({
  imports: [
    CommonModule,
    MatIconModule, 
    MatCheckboxModule, 
    MatFormFieldModule, 
    MatButtonModule
  ],
  declarations: [TreeComponent],
  exports: [TreeComponent]
})
export class TreeModule {
  static forRoot() {
    return {
      ngModule: TreeModule
    }
  }
}

app.component.ts

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

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  myData = [
    {'id':1, 'name':'Main 1','isExpand':false,
     'children':[
       {'id':1, 'name':'Child 1', 'isExpand':false,
       'children':[
         {'id':2, 'name':'Test2','isExpand':false}
       ]
       }
     ] 
    },
    {
      'id':2, 'name':'Main 2','isExpand':false
    }
  ]

  test(node) {
    console.log('from app start');
    console.log(node);
    console.log('from app end');
    if ('children' in node && node.children.length) {
      node.isExpand = !node.isExpand;
    }
  }
}

app.component. html

<app-tree [treeData]='myData' (toggleEmitter)="test($event)"></app-tree>

app.module.ts

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { TreeModule } from './tree/tree.module';
import {
  MdToolbarModule,
  MdTabsModule,
  MdButtonModule,
  MdInputModule,
  MdDatepickerModule,
  MdNativeDateModule,
  MdCheckboxModule,
  MdRadioModule,
  NoConflictStyleCompatibilityMode
} from '@angular/material';

import { AppComponent } from './app.component';

@NgModule({
  imports:      [ BrowserModule, FormsModule, BrowserAnimationsModule, MdToolbarModule, MdTabsModule, MdButtonModule, MdInputModule, MdDatepickerModule, MdNativeDateModule, MdCheckboxModule, MdRadioModule, TreeModule, NoConflictStyleCompatibilityMode ],
  declarations: [ AppComponent ],
  bootstrap:    [ AppComponent ]
})
export class AppModule { }

Ответы [ 2 ]

0 голосов
/ 02 июня 2020

вместо использования «test» вы должны привязать «toggleChild» в дочернем компоненте.

изменить

<app-tree *ngIf="node.isExpand" [treeData]="node.children" (toggleEmitter)="test(node,i)"></app-tree>

на

<app-tree *ngIf="node.isExpand" [treeData]="node.children" (toggleEmitter)="toggleChild(node,i)"></app-tree>
0 голосов
/ 02 июня 2020

Генератор событий работает таким образом

Родитель передает данные дочернему элементу

и

Ребенок Излучает, когда сообщить родителю, что Данные были - так что родитель может вызвать свою функцию обратного вызова

Для дочернего элемента Знание родителя изменилось Дата

Здесь происходит привязка данных, точно так же, как * ngif работает, когда дочерние проверочные данные всегда будут последними.

Переменная Input () дочернего компонента будет в том же состоянии, что и переменная, которая передается при привязке. Связывание заботится об обновлении дочернего пользовательского интерфейса - при изменении состояния связанных переменных

...