1

I have written a custom dropdown component and I want to use inside it a template tag to style the output. For example:

<cstm-dropdown [model]="incident.sensor" [options]="sensors" [id]="'id'">            
      <template>
         {{option.name | localName}}
      </template>  
</cstm-dropdown>

this should display the name property of the options with some pipe transformation on it.

My component is :

import { Component, Input, OnChanges } from '@angular/core';

@Component({
  selector: 'cstm-dropdown',
  template: `
      <select [ngModel]="selectedOption"  (ngModelChange)="onModelChange($event)" >
        <option *ngFor="let option of options" [ngValue]="option">
          <!-- The template should be rendered here -->
        </option>
      </select>
    `
})
export class CustomDropdownComponent implements OnChanges {

  @Input() model: any;

  selectedOption: any;

  @Input() options: any[];

  @Input() id: any;

  @Input() idProperties: any[];

  ngOnChanges() {
    if (!this.identifyByProperty()) {
      this.identifyByProperties();
    }
  }

  onModelChange(event) {
    for (const key of Object.keys(event)) {
      this.model[key] = event[key];
    }
  }

  identifyByProperty(): boolean {
    if (!this.id) {
      return false;
    }

    for (const option of this.options) {
      if (this.model[this.id] === option[this.id]) {
        this.selectedOption = option;
        return true;
      }
    }

    return false;
  }

  identifyByProperties(): boolean {
    // if the array isn't passed
    if (!this.idProperties) {
      return false;
    }
    // if the passed array is empty
    if (!this.idProperties.length) {
      return false;
    }

    for (const option of this.options) {
      if (this.arePropertiesIdentical(option)) {
        this.selectedOption = option;
        return true;
      }
    }

    return false;
  }

  arePropertiesIdentical(option: any): boolean {
    for (const prop of this.idProperties) {
      if (this.model[prop] !== option[prop]) {
        return false;
      }
    }
    return true;
  }

}

I read that I should use TemplateRef, but couldn't fimd any tutorials on how to do the templating with it. Any help is welcomed :)

Alexander Abakumov
  • 13,617
  • 16
  • 88
  • 129
user3719857
  • 1,083
  • 4
  • 16
  • 45
  • 1
    http://stackoverflow.com/questions/39974126/how-to-pass-an-expression-to-a-component-as-an-input-in-angular2 http://stackoverflow.com/questions/39561688/nested-templates-in-angular-2 – yurzui Feb 26 '17 at 18:44
  • @yurzui Thank you :). You can close this question. – user3719857 Feb 26 '17 at 18:56

1 Answers1

0

You can use Content Projection as below

@Component({
  selector: 'cstm-dropdown',
  template: `
      <select [ngModel]="selectedOption"  (ngModelChange)="onModelChange($event)" >
        <option *ngFor="let option of options" [ngValue]="option">
        <ng-content select=".custom-template"> </ng-content>
          <!-- The template should be rendered here -->
        </option>
      </select>
    `
})

You have to use the selector in your HTML so that your content template is filled with the relevant template

<cstm-dropdown [model]="incident.sensor" [options]="sensors" [id]="'id'">            
     <div class="custom-template">
      <template>
         {{option.name | localName}}
      </template>  
     <div>
</cstm-dropdown>
Aravind
  • 40,391
  • 16
  • 91
  • 110