使用 ng-select 插入动态模板

Eri*_*yke 1 string-interpolation angular2-template angular

我想创建一个组件,其中包含一个ng-select组件,我向该组件传递一组复杂对象以及要在下拉列表中显示的字段和所选值的定义。您可以ng-select指定要显示的字段 ( bindLabel) 并定义一个模板来显示所选值(您可以显示对象中的一个或多个字段或其他 HTML 标记)。我能够传递 的值bindLabel,但无法弄清楚如何插入模板。

例如,这就是我通常使用的方式ng-select。在本例中,我显示对象的两个字段和一些 HTML(将缩写字段加粗),并在下拉列表中列出缩写字段:

子组件

  items = [
    { name: 'United States', abbreviation: 'US' }, 
    { name: 'United Kingdom', abbreviation: 'UK' }, 
    { name: 'Canada', abbreviation: 'CA' }
  ];
  displayField = 'abbreviation';
Run Code Online (Sandbox Code Playgroud)

子模板

  <ng-select [items]="items" 
           bindLabel="displayField"
           [(ngModel)]="model"
           name="ngselect" 
           (change)=emitModelChanged()>
      <ng-template ng-label-tmp let-item="item">
          <b>{{item.abbreviation}}</b> - {{item.name}}
      </ng-template>
  </ng-select>
Run Code Online (Sandbox Code Playgroud)

要从父组件动态配置它,我传递items,displayFieldtemplate作为输入:

父组件

  selectedTemplate = '<b>{{item.name}}</b> - {{item.abbreviation}}';
Run Code Online (Sandbox Code Playgroud)

父模板

  <child-component [model]=model 
                   [items]=items
                   [displayField]="'abbreviation'"
                   [template]=selectedTemplate
                   (update)=updateModel($event)></child-component>
Run Code Online (Sandbox Code Playgroud)

子组件

  @Input() items;
  @Input() displayField; //what field shows in dropdown options
  @Input() template; // what shows for selected value in combobox
  @Input() model;
  @Output() update: EventEmitter<any> = new EventEmitter(); //emit back to parent
Run Code Online (Sandbox Code Playgroud)

子组件模板

  <ng-select [items]="items" 
           bindLabel="{{displayField}}"
           [(ngModel)]="model"
           name="ngselect" 
           (change)=modelChanged()>
      <ng-template let-item="item">
          <label [innerHTML]="template"></label>
      </ng-template>
</ng-select>
Run Code Online (Sandbox Code Playgroud)

虽然“模板”的粗体标记被解释,但数据字段不会被插值,该值按字面显示为

{{item.name}} - {{item.abbreviation}}

它是否失去了范围,因此没有将 {{item.name}} 插入到适当的值?当我不使用innerHTML标签而只使用{{template}}时,也会发生同样的情况。如何防止将其呈现为字符串?

我同样对标准 <select> 进行了相同的插值失败,它将选项呈现为文字字符串:

selectField = 'item.'+this.displayField;   // (equivalent to item.abbreviation)

<select #standardSelect [(ngModel)]="model" (change)=modelChanged() >

  <!-- Also getting interpolating error here. Below renders as a string "item.abbreviation" -->
  <option *ngFor="let item of items" [ngValue]="item">{{selectField}}</option>

  <!-- This also renders as a string -->
  <!-- <option *ngFor="let item of items" [ngValue]="item" [innerHTML]="selectField"></option> -->

  <!-- Hardcoded value below works -->
  <!-- <option *ngFor="let item of items" [ngValue]="item">{{item.abbreviation}}</option> -->
</select>
Run Code Online (Sandbox Code Playgroud)

斯塔克闪电战

Rad*_*dik 7

您可以将模板路径放入组件中并使用 来渲染它ng-container,但是您需要使用ContentChild来处理模板引用。对于多个模板,使用#命名将它们与引用相匹配ContentChild。你可以尝试如下示例

使用 TemplateRef 引用外部模板

    import { TemplateRef } from '@angular/core';
    
    @Component({
      selector: 'ng-select-accessible[displayField]',
      templateUrl: './ng-select-accessible.component.html',
      styleUrls: [ './ng-select-accessible.component.scss' ]
    })
    export class NgSelectAccessibleComponent  {
    
      @ContentChild('labelTemplate') labelTemplate: TemplateRef<any>;;
      @ContentChild('optionTemplate') optionTemplate: TemplateRef<any>;;

    }
Run Code Online (Sandbox Code Playgroud)

使用 ng-container 将外部模板放置在项目模板内

    <div class='styled-select' aria-hidden=true>
      <ng-select [items]="items"
                 [placeholder]=placeholder 
                 [(ngModel)]="model"
                 name="ngselect" 
                 (change)=modelChanged()
                 attr.aria-label={{ariaLabel}}>

          <ng-template ng-label-tmp let-item="item">
            <ng-container 
              *ngTemplateOutlet="labelTemplate; context: { $implicit: item }">
            </ng-container>
          </ng-template>
    
          <ng-template ng-option-tmp let-item="item">
            <ng-container 
              *ngTemplateOutlet="optionTemplate; context: { $implicit: item }">
            </ng-container>
          </ng-template>
      </ng-select>
    </div>
Run Code Online (Sandbox Code Playgroud)

在 ng-template 中定义项目视图如下

    <ng-select-accessible 
                      [model]=model 
                      [items]=items
                      [displayField]="'abbreviation'"
                      [placeholder]="'custom placeholder'" 
                      (update)=updateModel($event)
                      [ariaLabel]="'Select a number'">
      <ng-template #labelTemplate let-item>               
        <label>
          <b>{{item.name}}</b> - {{item.abbreviation}}
        </label>
      </ng-template>
      <ng-template #optionTemplate let-item>               
        <label>
          <b>{{item.name}}</b>
        </label>
      </ng-template>

    </ng-select-accessible>
Run Code Online (Sandbox Code Playgroud)

我认为这是一篇关于 ng-template 的好文章