Вызов метода общего интерфейса в Dynami c дочерних компонентов из родительского компонента в Angular 8 - PullRequest
1 голос
/ 14 марта 2020

Мне нужно вызвать общий метод из интерфейса, который реализован в динамических c дочерних компонентах из родительского компонента в Angular. Мой родительский компонент html будет выглядеть следующим образом:

parent.component. html:

<div *ngFor = "let config of childConfigs"> 

    <div *ngIf = " config.type == 'a' ">
        <child-a [config]="config"></child-a>
    </div>
    <div *ngIf = " config.type == 'b' ">
        <child-b [config]="config"></child-b>
    </div>
    .
    .
    <div *ngIf = " config.type == 'n' ">
        <child-n [config]="config"></child-n>
    </div>
</div>
<button (click)="resetComponent()"> Reset</button>

Предположим, что существует интерфейс 'ComponentActions', который содержит метод resetComponent () и все дочерние компоненты реализуют это. Пример структуры дочерних компонентов будет таким:

child-a.component.ts:

export class ChildAComponent implements ComponentActions {

@Input() config;

resetComponent(){
    // do something
}
}

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

1 Ответ

1 голос
/ 14 марта 2020

Да, это сложно. Все ваши дочерние компоненты наследуют базовый интерфейс. Есть способ реализовать это. Однако вам необходимо настроить все типы компонентов и изменить интерфейс на абстрактный класс. Не волнуйтесь, если это абстрактный класс без определенной логики c, он будет действовать так же, как интерфейс, и вы можете использовать implements, но таким образом вам не нужно создавать InjectionToken:

export abstract class ComponentActions {
  resetComponent(): void;
}

Если вы не можете или не хотите сделать его интерфейсом, сделайте следующее:

export const ComponentActionsToken = new InjectionToken<ComponentActions>('component actions');

С этим вы можете предоставить следующее всем своим дочерним компонентам: поэтому для каждого дочернего компонента, который вы указали в качестве useExisting соответствующего дочернего класса:

@Component({
  selector: 'child-x',
  providers: [{ provide: ComponentActions, useExisting: ChildXComponent }]
})
export class ChildXComponent implements ComponentActions {
  resetComponent(): void {
    // do something
  }
}

@Component({
  selector: 'child-y',
  providers: [{ provide: ComponentActions, useExisting: ChildYComponent }]
})
export class ChildYComponent implements ComponentActions {
  resetComponent(): void {
    // do something
  }
}

Если вы используете токен инъекции, вы должны изменить значение ComponentActions в свойстве обеспечить на ComponentActionsToken

Теперь, согласно вашему шаблону, вы можете иметь несколько экземпляров ComponentActions в родительском шаблоне. Таким образом, вам нужен лог c, чтобы определить, над кем вы хотите выполнить действие. Но я полагаю, что у вас это есть.

Кроме того, похоже, что вы хотите выполнить это действие одновременно для всех компонентов. Итак, вот где появляется декоратор ViewChildren:

@Component({
  selector: 'parent'
})
export class ParentComponent {
  @ViewChildren(ComponentActions)
  children?: QueryList<ComponentActions>

  resetComponent(): void {
    this.children?.forEach((child) => child.resetComponent());
  }
}

Если вы используете токен впрыска, вы должны изменить значение ComponentActions в ViewChildren на ComponentActionsToken

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

...