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

У меня есть 2 разных компонента, в которых я использую Angular - панель расширения для расширяемого сводного представления.

Я могу интегрировать <mat-expansion-panel> к отдельным компонентам успешно.

Мне нужна помощь, чтобы сделать Component2.html как родитель Component1.html (Развернуть внутри развернуть - см. Изображение ниже)

  • Компонент 1 должен иметь возможность разворачиваться и сворачиваться независимо, чтобы отображать данные.

  • Компонент 2 должен встраивать Компонент 1 в себя, поэтому, когда Component 1 is expanded it can show its data and display remaining Child components

ПРИМЕЧАНИЕ. - Оба компонента имеют отношение Sibling , no parent child

Component1.html

        <div class="row">
    <div class>
      <dl class="row property_set" data-property-set-name="data">
        <mat-accordion>
          <mat-expansion-panel (opened)="doExpand = true"
                             (closed)="doExpand = false">
          <mat-expansion-panel-header>
            <mat-panel-title>
        <dt class="col-sm-4 record_property">data</dt>
      </mat-panel-title>
      <mat-panel-description>
        <dd class="col-sm-8 record_property_value data_name" id="{{genId(data.name)}}">
          <inline-misal-edit 
                        [(field)]="data.name" [elementType]="a.bName" (fieldChange)="dataModified(data)"
                        cols="30" rows="1"></inline-misal-edit>
          </dd>
      </mat-panel-description>
    </mat-expansion-panel-header>

        <dt class="col-sm-4 record_property">news</dt>
        <dd class="col-sm-8 record_property_value">{{data.news?.created | news}}</dd>
      </mat-expansion-panel>
    </mat-accordion>
      </dl>
    </div>

Component2.html

      
  <dl class="row property_set" data-property-set-name="misal">
    <mat-accordion>
        <mat-expansion-panel (opened)="doExpand = true"
                             (closed)="doExpand = false">
          <mat-expansion-panel-header>
            <mat-panel-title>
              misal Id
            </mat-panel-title>
            <mat-panel-description>
              <dd class="col-sm-10 record_property_value" data-property-type="select">{{misal.id || 'new'}}</dd>
            </mat-panel-description>
          </mat-expansion-panel-header>
          <dd class="col-sm-10 record_property_value misal_name">{{misal.data[0].name}}</dd>
          <dt class="col-sm-2 record_property">Country Pass</dt>
          <dt class="col-sm-2 record_property">Plugins Program</dt>
          <dd class="col-sm-10 record_property_value">
            <north-dhamma[(misal)]="misal" [editMode]="editMode" (misalChange)="recordModified.emit()"></registry-number>
          </dd>
          <dt *ngIf="misal.value === 'hovered'" class="col-sm-2 record_property">Related Plugins Program</dt>
          <dd *ngIf="misal.value === 'hovered'" class="col-sm-10 record_property_value">
            <land-hole></land-hole>
          </dd>
                </mat-expansion-panel>
      </mat-accordion>
  </dl>

.ts файл

        panelOpenState = true;

4 ответа

Один из способов сделать это - использовать общий сервис - https://angular.io/guide/component-interaction#parent-and-children-communicate-via-a-service.

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

app-sibling2.component.ts

      import { AppSibling1Component } from '../app-sibling1/app-sibling1.component';

export class AppSibling2Component {
   @Input() data: AppSibling1Component;
   ...
}

В шаблоне родительского компонента:

      <!-- Assigns "AppSibling1Component" instance to variable "data" -->
<app-sibling1 #data></app-sibling1>
<!-- Passes the variable "data" to AppSibling2Component instance -->
<app-sibling2 [data]="data"></app-sibling2> 

Я считаю, что это то, что вы ищете. Дайте знать, если у вас появятся вопросы

Вы должны иметь возможность добавить свой дочерний компонент сразу после закрывающего тега mat-expansion-panel-header

      <mat-accordion>
  <mat-expansion-panel>
    <mat-expansion-panel-header>
      <mat-panel-title>
        Parent Expansion
      </mat-panel-title>
    </mat-expansion-panel-header>
    <p>Content of parent</p>
    <!-- add child here -->
    <app-child></app-child>
  </mat-expansion-panel>
</mat-accordion>

https://stackblitz.com/edit/angular-5euuwx?file=src%2Fapp%2Fexpansion-overview-example.html

Я не понимаю, что вам нужно.

Компонент 2 должен включать Компонент 1 в себя.

Вам нужно что-то вроде этого

      // component2.component.ts
@Component({
  selector: "component2",
  template: `
    <component1></component1>
  `,
  styles: []
})
export class Component2 {
}

Оба компонента имеют отношение Sibling, ни родительский ребенок, ни дочерний элемент - родитель

Но здесь ты этого хочешь.

      // app.component.ts
@Component({
  selector: "app",
  template: `
    <component2></component2>
    <component1></component1>
  `,
  styles: []
})
export class AppComponent {
}

Думаю, вам нужно что-то вроде этого, демо . 2 родных брата <mat-expansion-panel> как дисплей.

Я немного запутался, ты хочешь Component2.html как родитель Component1.html и вы упомянули, что оба компонента имеют отношение Sibling, no parent child or child - parent.

Помня об этом, как насчет того, чтобы ExpansionWrapperComponentкоторый объединяет и и включает в себя поведение - если включено, должно переключаться одновременно, можно переключать и отдельно .

extension-wrapper.component.html

      <div class="expansion-wrapper">
  <div class="parent">
    <ng-content select="app-component2"></ng-content>
  </div>
  <div class="child">
    <ng-content select="app-component1"></ng-content>
  </div>
</div>

extension-wrapper.component.ts

      import { AfterContentInit, Component, ContentChild, OnInit } from '@angular/core';
import { Component1Component } from '../component1/component1.component';
import { Component2Component } from '../component2/component2.component';

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

  @ContentChild(Component2Component, { static: false }) component2: Component2Component;
  
  @ContentChild(Component1Component, { static: false }) component1: Component1Component;

  constructor() { }

  ngOnInit() {
  }

  ngAfterContentInit() {
    this.component2.panelStateChanged.subscribe(res => {
      this.component1.togglePanelState(res);
    });
  }

}

Где и содержит отдельную панель расширения. С этим Component1 является родным братом и чувствует себя втянутым в Component2.

Проверить приложение через stackblitz

Другие вопросы по тегам