Nicolas
Nicolas

Reputation: 604

How to display customized dropdown in angular 5

I am trying to display items in dropdown using ng-select in Angular 5. But the dropdown component that I am designing should be more generic in nature meaning people who are calling my dropdown should be able to pass customized template for displaying items in dropdown. i.e. the items list in dropdown should be build with specific template and a call to my generic dropdown should display the customized list of items. Is this something that can be achieved in transclusion? Currently I am using "dropdownVal" which is of String[] datatype but instead I need to have array of template/component.

My code is below

dropdown.component.ts

@Component({
  selector: 'wdsk-dropdown',
  templateUrl: './dropdown.component.html',
  styleUrls: ['./dropdown.component.scss']
})
export class DropdownComponent implements OnInit {


  @Input() dropdownVal: string[];
  @Input() placeholder: string;

  @Output() selectedItem = new EventEmitter();

  constructor() { }

  ngOnInit() {
  }

  onSelect(value: any) {
    this.selectedItem.emit(value);
  }
}

Template - dropdown.component.html

<div class="col-md-12 account-dropdown">
  <div class="form-group row">

    <div class="col-md-12">

      <ngx-select tabindex="0" placeholder={{placeholder}} [items]="dropdownVal" (selected)="onSelect($event)">
      </ngx-select>
    </div>
  </div>
</div>

Upvotes: 1

Views: 4168

Answers (1)

JBoothUA
JBoothUA

Reputation: 3149

I have done this before with Angular Material's mat-select element, using @ContentChildren and ng-template.

Working Example Here

dropdown.ts

import { Component, OnInit, Input, ViewEncapsulation, Output, EventEmitter, ViewChild, ContentChildren, QueryList , TemplateRef} from '@angular/core';
import { MatSelectChange, MatSelect } from '@angular/material/select';

// Template Sections
@Component({
  selector: 'custom-dropdown-item',
  template: '<ng-template #content><ng-content></ng-content></ng-template>'
})
export class CustomDropdownItemsComponent {
  @ViewChild('content') content: any;
  @Input() value: any;
  @Input() width: string;
  @Input() height: string;
  @Output() click: EventEmitter<any> = new EventEmitter();

  onClick() {
    this.click.emit(this.value);
  }
}

@Component({
  selector: 'custom-dropdown',
  templateUrl: './custom-dropdown.component.html',
  styleUrls: ['./custom-dropdown.component.scss']
})
export class CustomDropdownComponent implements OnInit {
  @ViewChild('matSelect') matSelect: MatSelect;
  @Output() valueChange: EventEmitter<MatSelectChange> = new EventEmitter<MatSelectChange>();
  @Output() openedChange: EventEmitter<boolean> = new EventEmitter<boolean>();
  @Input() value: any;
  @Input() items: string[];
  @Input() placeholder: string;
  @Input() dropdownTitle: string;
  @Input() addDynamicContent: boolean = false;
  @Input() compareWith: Function;
  defaultCompareWithFn: Function = function () { };
  selectedIndex = -1;

  @ContentChildren(CustomDropdownItemsComponent)
  ddItems:QueryList<CustomDropdownItemsComponent>;

  constructor() { }

  ngOnInit() {
  }

  valueChanged(event: MatSelectChange) {
    this.valueChange.emit(event.value);
  }
}

dropdown.html

<mat-select #matSelect [(value)]="value" (selectionChange)="valueChanged($event)">
  <mat-option style="width:100px" [value]="0">
    <h1 style="color:red">I'm content = 0</h1>
  </mat-option>
  <mat-option [style.width]="ddlItem.width" [value]="i+1" *ngFor="let ddlItem of ddItems; let i = index">
    <ng-container [ngTemplateOutlet]="ddlItem.content"></ng-container>
  </mat-option>
</mat-select>

Passing in custom items:

<div class="mat-app-background basic-container" style="width:200px; padding:0; margin:0">
    <custom-dropdown [addDynamicContent]="true" [(value)]="selected">
        <custom-dropdown-item width="100px">
                <span style="color:green">I'm dynamic content = 1</span>
        </custom-dropdown-item>
        <custom-dropdown-item width="100px">
                <p style="color:blue">I'm dynamic content = 2</p>
        </custom-dropdown-item>
    </custom-dropdown>
</div>
<div>
  Selected: {{ selected }}
</div>

Upvotes: 1

Related Questions