簡體   English   中英

使用 ng-template 擴展角度組件

[英]extend a angular component with ng-template

我使用 Kendo Ui 作為我最喜歡的 Angular 用戶界面框架。

<kendo-multiselect [data]="listItems" [(ngModel)]="value">
       <ng-template kendoMultiSelectHeaderTemplate let-dataItem>
            <strong (click)="toggleSelection()">Alle Auswählen</strong>
         </ng-template>
</kendo-multiselect>

到目前為止一切順利,但我幾乎在我的每個多選下拉列表中都需要更多的 ng-template。 所以我的問題是,我可以創建一個指令,我可以直接在主機組件上使用它來創建 ng-template 和我需要的所有其他東西,或者這里是擴展現有組件子模板的最佳解決方案。

示例結果:

<kendo-multiselect my-multiselectHeader 
                   [data]="listItems" 
                   [(ngModel)]="value">
</kendo-multiselect>

解決方案似乎比我以前想象的要容易。

我創建了一個新的周圍指令,我可以在其中訪問

  • ContentChild => 是我們可以訪問所有屬性的多選組件
  • ViewChild => 是我想分配給多選的 Headertemplate

使用此解決方案,我可以訪問原始多選中的所有自然屬性,並且僅在 ng-content 的幫助下擴展我“需要”的功能

sq-multiselect-extension.html:

<ng-template kendoMultiSelectHeaderTemplate let-dataItem>
   <strong (click)="toggleSelection()" class="m-2 link-cursor">Alle Auswählen</strong>
</ng-template>
<ng-content></ng-content>

sq-multiselect-extension.ts:

import { Component, OnInit, ViewChild, ContentChild } from    '@angular/core';
import { HeaderTemplateDirective, MultiSelectComponent } from '@progress/kendo-angular-dropdowns'
@Component({
    selector: 'sq-multiselect-extension',
    templateUrl: './sq-multiselect-extension.html',
})
export class SxpMultiselectComponent implements OnInit {

    @ViewChild(HeaderTemplateDirective) headerTemplate: HeaderTemplateDirective;
    @ContentChild(MultiSelectComponent) multiselect: MultiSelectComponent;

public ngOnInit() {
  this.multiselect.headerTemplate = this.headerTemplate;
}

public toggleSelection(): void {
  if (this.multiselect.value.length > 0) {
    this.multiselect.reset();
  }
  else {
     this.multiselect.writeValue(this.multiselect.data)
     this.multiselect.value = this.multiselect.data.slice();
  } 
 }
}

並使用這個新組件

<sq-multiselect-extension>
    <kendo-multiselect [data]="listStringItems" [(ngModel)]="value" class="form-control">
    </kendo-multiselect>
</sq-multiselect-extension>

是的,我認為這沒什么大不了的。 這僅取決於您想要做什么,但創建一個自定義標題的指令似乎並不難。

我認為您可以使用ng-template注入和/或使用ngTemplateOutlet

但我建議您查看kendoMultiSelectHeaderTemplate指令以檢查它的准確功能。

如果您使用的是let-dataItem變量,請檢查您是否可以在自定義Directive上使用它。

如果您打算重用多選輸入,我建議將 kendo 元素包裝到一個單獨的組件中。 這樣,如果您需要將一些自定義選項傳遞給 kendo 元素,您可以在一個地方完成,它會影響所有多選。

添加到steamwuschel的答案中,這對使用Angular 8我來說是完美的

我已經使用Select All功能擴展了 Kendo MultiSelect 組件

ngOnInit ,組件尚未呈現,因此您將其視為未定義。 所以你必須使用AfterViewInit

multiselect-extended.component.ts

import {
  Component,
  OnInit,
  ViewChild,
  Output,
  ContentChild,
  AfterViewInit,
  EventEmitter
} from "@angular/core";
import {
  HeaderTemplateDirective,
  MultiSelectComponent
} from "@progress/kendo-angular-dropdowns";

@Component({
  selector: "app-custom-multselect",
  templateUrl: "./custom-multselect.component.html",
  styleUrls: ["./custom-multselect.component.css"]
})
export class CustomMultselectComponent implements OnInit, AfterViewInit {
  @ViewChild(HeaderTemplateDirective, { static: false })
  headerTemplate: HeaderTemplateDirective;
  @ContentChild(MultiSelectComponent, { static: false })
  multiselect: MultiSelectComponent;

  @Output() selectAllEvent: EventEmitter<boolean> = new EventEmitter();
  constructor() {}

  ngOnInit() {}
  ngAfterViewInit() {
    console.log(this.multiselect);
    this.multiselect.headerTemplate = this.headerTemplate;
  }

  public toggleSelection(): void {
    if (this.multiselect.value.length > 0) {
      this.multiselect.reset();
      this.selectAllEvent.emit(false);
    } else {
      this.multiselect.writeValue(this.multiselect.data);
      this.multiselect.value = this.multiselect.data.slice();
      this.selectAllEvent.emit(true);
    }
  }
}

請注意,我添加了一個selectAllEvent來更新多選下拉列表中顯示的復選框。

應用程序組件.html

<app-custom-multselect (selectAllEvent)=" selectAllItems($event)">
    <kendo-multiselect [data]="listItems" [(ngModel)]="value" [textField]="'text'" [valueField]="'value'"
        [autoClose]="false">
        <ng-template kendoMultiSelectItemTemplate let-dataItem>
            <input type="checkbox" class="k-checkbox"
          [checked]="isItemSelected(dataItem.text) || isAllSelected">
            <label class="k-checkbox-label">{{ dataItem.text }}</label>
        </ng-template>
    </kendo-multiselect>
</app-custom-multselect>

app.component.ts

export class AppComponent {
  public listItems: Array<{ text: string; value: number }> = [
    { text: "Small", value: 1 },
    { text: "Medium", value: 2 },
    { text: "Large", value: 3 },
    { text: "XL", value: 4 },
    { text: "XXL", value: 5 }
  ];
  public value: any = [];
  public isAllSelected: boolean = false;

  public isItemSelected(itemText: string): boolean {
    return this.value.some(item => item.text === itemText);
  }

  selectAllItems(isSelectAll) {
    if (isSelectAll) {
      this.isAllSelected = true;
    } else {
      this.isAllSelected = false;
    }
  }
}

你也可以在StackBlitz上找到演示

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM