使用ng-template扩展角度分量

时间:2018-04-25 18:34:30

标签: angular angular2-directives kendo-ui-angular2

我使用Kendo Ui作为我最喜欢的Angular Ui Framework。

<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>

4 个答案:

答案 0 :(得分:1)

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

我创建了一个新的around指令,我可以访问

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

使用此解决方案,我可以访问原始multiselect中的所有自然属性,我只在ng-content

的帮助下扩展我“需要”的功能

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>

答案 1 :(得分:0)

是的,我认为这不是什么大问题。它只取决于你想要做什么,但创建一个自定义标题的指令似乎不太难。

我认为你可以使用ng-template注射和/或使用ngTemplateOutlet

但我建议你看一下kendoMultiSelectHeaderTemplate指令来检查它的作用。

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

答案 2 :(得分:0)

如果您打算重用多选输入,我建议将kendo元素包装到一个单独的组件中。这样,如果您需要将一些自定义选项传递给kendo元素,则可以在一个位置执行此操作,它将影响所有多选项。

答案 3 :(得分:0)

除了squadwuschel的回答外,这对我使用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来更新多选下拉列表中显示的复选框。

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

上找到演示。