Angular 5 — EventEmitter отправляет данные только один раз

Я создаю панель управления для управления пользователями внутри компании. У этой компании разное количество отделов и куча филиалов внутри этих отделов, поэтому у меня есть пользовательское рекурсивное древовидное представление для отображения связи между ними.

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

Для этого я читал на форумах, что могу использовать декораторы @Input / @Output и EventEmitter. Это работает, но только один раз. метод, который получает cd (называемый receiveNode()), не обновляется, когда я нажимаю на другую ветку, и работает только в первой ветке. Что не является желаемым поведением.

Для тестирования тем же методом, который генерирует переменную CD, я вывожу в консоль CD ветки. Я вижу, что я могу регистрировать переменную CD каждый раз, когда я нажимаю на ветку, но отправляю только один раз через эмиттер событий.

tree.component.ts (дочерний элемент)

import { Component, OnInit, Output, EventEmitter } from '@angular/core';
import { Input } from '@angular/core';
import { TreeNode } from '../../interfaces/tree-node';

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

  @Input() treeData: TreeNode[];

  // Enviar CD do organigrama para o BuildOrganigComponent
  @Output() eventEmitter: EventEmitter<number> = new EventEmitter();
  nome: string;

  constructor() {  }

  ngOnInit() { }

  toggleChild(node) { node.showChildren = !node.showChildren; }

  sendNode(cd) {
    console.log(cd);
    this.eventEmitter.emit(cd);
  }
}

tree.component.html

<ul *ngIf="treeData">
  <li *ngFor="let node of treeData">
    <span *ngIf="node.children != 0">
      <i (click)="toggleChild(node)" id="seta-direita" class="fas fa-angle-right fa-fw"></i>
    </span>
    <span id="row" (click)="sendNode(node.cd)">{{ node.nome }}</span>
    <app-tree *ngIf="!node.showChildren" [treeData]="node.children"></app-tree>
  </li>  
</ul>

funcion.component.ts

  receiveNode(e) {
    console.log(e);
  }

funcion.component.html

 <div class="overflow" style="margin-left: -5% !important;">
        <app-tree [treeData]='nodes' (eventEmitter)='receiveNode($event)'></app-tree>
    </div>

funcion.html и funcion.ts довольно большие, поэтому там размещено только самое важное. Если нужно увидеть весь код, просто скажите мне.

Некоторые изображения Родительский компонент с деревом внутри

Подробности в консоли

На втором изображении мы видим, что журналы из компонентов дерева и функционального компонента, но после того, где бы я ни щелкнул, он никогда не вызывает метод в функциональных компонентах.

Что может быть не так? Любая помощь приветствуется


person LuisMorais    schedule 22.10.2018    source источник
comment
Вы пытаетесь использовать компонент в своем собственном шаблоне? я не думаю, что это хорошая идея или даже действительный?   -  person alokstar    schedule 22.10.2018
comment
Это рекурсивный способ сделать это... По крайней мере, как я понял. Я нашел в Интернете и работает до сих пор. Но кажется «неправильным», если подумать :/   -  person LuisMorais    schedule 22.10.2018
comment
Это может привести к зацикливанию вызовов ваших приложений! Я бы не советовал этого. Почему бы вам не создать отдельные родительские и дочерние компоненты и не попробовать? Сделав это, вам будет легко понять поток данных. Вы даже можете поставить точки останова на функции и посмотреть, какая функция или строка кода выполняется и когда, что рассеет все ваши сомнения!   -  person alokstar    schedule 22.10.2018
comment
Хм, хорошо, я проверю. Может быть, мне стоит подумать и перепроектировать все компоненты дерева. Спасибо   -  person LuisMorais    schedule 23.10.2018


Ответы (1)


Мне удалось заставить его работать, передавая данные через общий сервис, а не через декораторы @Input и @Output. Теперь это проще, чище и понятнее!

data.service.ts

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

@Injectable()
export class DataService {

  private cdSource = new BehaviorSubject<number>(1);
  currentCD = this.cdSource.asObservable();

  constructor() { }

  changeCD(m: number) {
    this.cdSource.next(m);
  }

}

child.component.ts

// Called everythime treeview is clicked
sendNode(cd: number) {
  this.dataService.changeCD(cd);
}

parent.component.ts

 // Update methods when dataService changes values
    this.dataService.currentCD.subscribe(message => {
      this.preencheGrafico(message);
      this.preencheDadosIniciais(message);
      this.preencheTabela(message);
  });
}

Работает как шарм и никаких недостатков!

Основано на этом руководстве.

person LuisMorais    schedule 23.10.2018