【问题标题】:extend a angular component with ng-template使用 ng-template 扩展一个角度分量
【发布时间】:2018-04-25 18:34:29
【问题描述】:

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

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

【问题讨论】:

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


    【解决方案1】:

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

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

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

    使用此解决方案,我可以访问原始多选中的所有自然属性,并且仅在 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>
    

    【讨论】:

      【解决方案2】:

      是的,我认为这没什么大不了的。这仅取决于您想要做什么,但是创建一个自定义标头的指令似乎并不难。

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

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

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

      【讨论】:

        【解决方案3】:

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

        【讨论】:

        • 问题来了,我必须封装所有 kendo 下拉功能,当我只需要一个特定功能时,我必须封装一个新组件,我最喜欢的解决方案是创建一些特定指令,哪个处理例如标题模板,....
        • 您可以将属性传递给具有所需功能名称的包装 kendo 组件,并在组件模板中执行 ngSwitch 来呈现模板。 &lt;my-kendo-dropdown [template]="feature1"&gt;&lt;/my-kendo-dropdown&gt;
        【解决方案4】:

        除了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 上找到演示

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-07-11
          • 2017-08-29
          • 2020-07-17
          • 1970-01-01
          • 2017-10-15
          • 1970-01-01
          • 1970-01-01
          • 2013-05-23
          相关资源
          最近更新 更多