Reputation: 604
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
Reputation: 3149
I have done this before with Angular Material's mat-select
element, using @ContentChildren and ng-template.
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