Как я могу правильно передать значение из подкомпонента второго уровня в родительский компонент в этой ситуации?

Я не очень люблю Angular и TypeScript (я пришел с Java), и мне нужно решить следующую проблему. Я не знаю, правильное ли решение, которое я думаю использовать, или есть лучшие решения.

В основном у меня есть компонент с именем order-manager.component, который является родительским компонентом, отображающим эти таблицы:

введите описание изображения здесь

Этот родительский компонент содержит список объектов, представляющих одну строку:

orders: any[];

и в ngOnInit () получить список с помощью службы.

Как вы можете видеть на предыдущем экране, каждая строка моей таблицы может быть расширена, чтобы показать \ отредактировать детали конкретного объекта.

Для этого я использовал подкомпонент сведения о заказе. Итак, в основном в моем родительском компоненте HTML у меня есть что-то вроде этого:

DETTAGLIO ORDINE

Этот подкомпонент сведения о заказе имеет два подкомпонента: один для режима просмотра, а второй для режима редактирования (выделено на предыдущем снимке экрана. ).

Итак, в моем коде этого компонента сведения о заказе у меня просто есть:

<p-selectButton [options]="editOrderOption"
                [(ngModel)]="editOrderSelectedOption"
                (onChange)="editOrderOptionOnChange($event, orderDetail.id)"></p-selectButton>


<div *ngIf="editOrderSelectedOption=='view';then view_content else edit_content">here is ignored</div>

<ng-template #view_content>
  <app-view-order [orderDetail]="orderDetail"></app-view-order>
</ng-template>

<ng-template #edit_content>
  <app-update-order [orderDetail]="orderDetail"></app-update-order>
</ng-template>

Обычно пользователь выбирает режим просмотра или редактирования с помощью кнопки выбора, и на странице отображается подкомпонент.

В конкретном случае мы находимся в режиме редактирования, используя этот компонент update-order.

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

И вот моя проблема. Список объектов, представляющих строки таблицы, определяется в первом родительском компоненте order-manager.component, а кнопка - во вложенном компоненте update-order второго уровня, this это иерархия:

order-manager component
          |
          |
          |---------> order-details component
                                |
                                |
                                |----------------> update-order component

                 

Чтобы решить эту проблему, я подумал, что могу сделать что-то вроде этого:

  1. Пользователь нажимает кнопку Удалить, определенную в подкомпоненте update-order. Это обрабатывается методом, который генерирует событие, содержащее идентификатор текущей строки (это уникальное значение поля объекта.

  2. Я прослушиваю это событие в родительском компоненте order-manager. Когда событие получено, оно удаляется из списка заказов, представляющего список строк моей таблицы.

Как вы думаете, это довольно приличное и изящное решение для достижения этой задачи, или я чего-то упускаю, и есть решения получше?


person AndreaNobili    schedule 05.09.2020    source источник
comment
да, вот как вы это делаете. просто испустите событие, прослушайте его в родительском и удалите строку.   -  person fastAsTortoise    schedule 05.09.2020
comment
вероятно, лучше просто использовать общий сервис, чем двухуровневый эмиттер событий   -  person bryan60    schedule 06.09.2020


Ответы (3)


Выдача значения будет работать.

Более простым решением будет создание службы, которая может отслеживать действия пользователя. Создайте Сервис, скажите OrderChangeService и введите это как в order-manager component, так и в update-order component

export class OrderChangeService {
  deleteIdSubject$ = new Subject<number>(); // import { Subject } from rxjs
  deleteIdAction$ = deleteIdSubject$.asObservable()
}

Теперь в update-order component, когда пользователь щелкает, чтобы удалить определенный заказ, вы вызываете функцию next () для этой темы.

  deleteOrder(id: number) {
    deleteIdSubject$.next(id);
  }

В компоненте менеджера заказов теперь вы можете подписаться на deleteIdAction$ в своей функции ngOnInit()

deleteIdAction$ = this.orderChangeService.deleteIdAction$ // make sure you inject service in the constructor
  ngOnInit() {
    this.deleteIdAction$.subscribe({
      next: (id) => {
        // Do Delete action for item with id
      }
    })
  }

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

Лучшим подходом было бы использовать NgRx для управления состоянием. Может быть немного сложно использовать, но дает лучший результат. Вы можете ознакомиться с официальной документацией NgRx.

person Owen Kelvin    schedule 05.09.2020

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

import { Injectable } from '@angular/core';
import { Subject, Observable } from 'rxjs';
@Injectable()
export class MessageService {
  private siblingMsg = new Subject<string>();
  constructor() { }
  /*
   * @return {Observable<string>} : siblingMsg
   */
  public getMessage(): Observable<string> {
    return this.siblingMsg.asObservable();
  }
  /*
   * @param {string} message : siblingMsg
   */
  public updateMessage(message: string): void {
    this.siblingMsg.next(message);
  }
}

а из компонента вы можете установить значение с помощью подписки

import { Component, OnInit, OnDestroy } from '@angular/core';
import { MessageService } from './message.service';
...
export class AppComponent implements OnInit{
  public messageForSibling: string;
  public subscription: Subscription;
  constructor(
    private msgservice: MessageService // inject service
  ) {}

  public ngOnDestroy(): void {
    this.subscription.unsubscribe(); // onDestroy cancels the subscribe request
  }

  public ngOnInit(): void {
    // set subscribe to message service
    this.subscription = this.messageService.getMessage().subscribe(msg => this.messageForSibling = msg);
  }
}
person Geeks Trick    schedule 06.09.2020

Сначала вы должны создать свойство вывода в своем дочернем компоненте.

  @Output() 
  updated = new EventEmitter<boolean>();
  
  saveButtonClicked() {
    
    //do update
    
    this.updated.emit(true); //update success
    
  }

Определите это в своем HTML:

<ng-template #edit_content>
  <app-update-order [orderDetail]="orderDetail" (updated)="orderUpdated($event)"></app-update-order>
</ng-template>

Теперь вы можете прослушивать события обновления в родительском компоненте.

orderUpdated(updated:boolean){
    if(updated){
    
    }
}

Дополнительную информацию о взаимодействии компонентов можно найти здесь

person Muhammed Yusuf    schedule 06.09.2020