使用 ng-template 扩展 angular 组件

extend a angular component with ng-template

我正在使用 Kendo Ui 作为我最喜欢的 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。所以我的问题是,我可以创建一个指令,我可以直接在主机 komponent 上使用它创建 ng-template 和我需要的所有其他东西,或者这里扩展现有组件子模板的最佳解决方案是什么。

示例结果:

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

是的,我认为这没什么大不了的。这只取决于你想做什么,但创建一个指令来自定义 header 似乎并不难。

我认为您可以使用 ng-template 注入和/或使用 ngTemplateOutlet

但我建议您查看 kendoMultiSelectHeaderTemplate 指令以检查它的确切作用。

如果您正在使用 let-dataItem 变量,请检查您是否可以在自定义 Directive.

上使用它

如果您打算重复使用多选输入,我建议将 kendo 元素包装到一个单独的组件中。这样,如果您需要将一些自定义选项传递给 kendo 元素,您可以在一个地方完成,它会影响所有多选。

解决方案似乎比我之前想象的要容易。

我创建了一个新的周围指令,我可以在其中访问

  • ContentChild => 是我们可以访问所有属性的多选组件
  • ViewChild => 是我要分配给多选的 Headertemplate

使用此解决方案,我可以访问原始多选中的所有自然属性,并且我仅在 ng-content

的帮助下扩展我 "need" 的功能

sq-多选-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-多选-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>

添加到 squadwuschel 的回答中,这对我使用 Angular 8

非常有用

我扩展了 Kendo MultiSelect 组件,具有 Select All 功能

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 来更新多选下拉列表中显示的复选框。

app.component.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

上找到演示