a suite of UI Components for development of web apps
If you have any questions, don't hesitate to contact us at support@lidorsystems.com
Advanced User Interface Controls and Components
Created: 18 August 2017
By default, all cells in TreeGrid component displays a simple text. To display custom content in grid cell, you need to add custom HTML elements or other Angular component to the cell template. In this article, you will learn how to add a dropdown checked list to the grid cells and change their value based on selected option.
If you have any questions, don't hesitate to contact us at support@lidorsystems.com
As this demo shows, all cells in Genre column display an arrow on the right side. When cell is clicked a dropdown list will popup, showing items that you can check. To confirm selection, click on any item in the list. Once the dropdown window closes, the cell value is updated.
The dropdown list is sorted in a way that at first shows all checked items for that specific cell, following by all other items in ascending order. If you click outside of the dropdown window or press the ESCAPE key, the selection is cancelled, and the cell value will remain the same.
At first, you need to create a checked list of items. For this purpose we are using the <ul>, <li> HTML elements where each item has a checkbox and a label. The template looks like this:
<ng-template let-obj [iuiTemplate]="{ type: 'dropdown' }">
<ul class="dropdown-list" [ngStyle]="{ width: dropDownWidth + 'px'}" (mousedown)="listMouseDown($event)">
<li *ngFor="let item of dropdownItems" (mousedown)="itemSelected(cell, item)">
<span class="cell-checkbox" [ngStyle]="{ 'background-image': getItemValue(item) }" style="margin-top:-1px" (mousedown)="itemChecked($event, cell, item)"></span>
<span>{{item.text}}</span>
</li>
</ul>
</ng-template>
/* DropDown Cell */
.dropdown-list
{
cursor: default;
margin: 0;
overflow: auto;
padding: 0;
list-style-type: none;
white-space: nowrap;
width: 150px;
height: 140px;
}
.dropdown-list li
{
padding: 5px;
}
.dropdown-list li:hover
{
background: #e5e5e5;
}
.cell-checkbox
{
background: url('') no-repeat 0 0;
display: inline-block;
padding: 0;
margin: 5px 7px 0 7px;
width: 16px;
height: 16px;
vertical-align: middle;
}
Checkbox is represented by a <span> element, where for its background a checkbox icon is used. Depending on item value, checkbox is checked or unchecked.
When item label is clicked, the selection is confirmed and the dropdown list is closed.
To show a popup window, you can use IntegralUIDropDown directive or any other Angular component. In case of the DropDown directive, to show a dropdown list you need to apply the previous template as content to the directive.
<div [iuiDropDown]="cell.dropdown" (dropDownOpen)="onDropDownOpen($event, cell)" #dropdown>
<div class="treegrid-ccmb-adv-item-drop-mark"><span></span></div>
<span class="treegrid-ccmb-adv-item-label">{{cell.text}}</span>
<ng-template let-obj [iuiTemplate]="{ type: 'dropdown' }">
<ul class="dropdown-list" [ngStyle]="{ width: dropDownWidth + 'px'}" (mousedown)="listMouseDown($event)">
<li *ngFor="let item of dropdownItems" (mousedown)="itemSelected(cell, item)">
<span class="cell-checkbox" [ngStyle]="{ 'background-image': getItemValue(item) }" style="margin-top:-1px" (mousedown)="itemChecked($event, cell, item)"></span>
<span>{{item.text}}</span>
</li>
</ul>
</ng-template>
</div>
Because dropdown is applied to many grid cells, you need to make sure each cell display its value and a dropdown icon. In this way, the user will know that when cell is clicked, it will open a dropdown window.
<div [iuiDropDown]="cell.dropdown" (dropDownOpen)="onDropDownOpen($event, cell)" #dropdown>
<div class="treegrid-ccmb-adv-item-drop-mark"><span></span></div>
<span class="treegrid-ccmb-adv-item-label">{{cell.text}}</span>
<ng-template let-obj [iuiTemplate]="{ type: 'dropdown' }">
<ul class="dropdown-list" [ngStyle]="{ width: dropDownWidth + 'px'}" (mousedown)="listMouseDown($event)">
<li *ngFor="let item of dropdownItems" (mousedown)="itemSelected(cell, item)">
<span class="cell-checkbox" [ngStyle]="{ 'background-image': getItemValue(item) }" style="margin-top:-1px" (mousedown)="itemChecked($event, cell, item)"></span>
<span>{{item.text}}</span>
</li>
</ul>
</ng-template>
</div>
.treegrid-ccmb-adv-item-drop-mark
{
float: right;
}
.treegrid-ccmb-adv-item-drop-mark span
{
background: url(app/integralui/resources/icons.png) -144px -80px no-repeat;
display: inline-block;
opacity: 0.5;
overflow: hidden;
padding: 0 !important;
margin: 4px 2px 0 0;
width: 16px;
height: 16px;
vertical-align: middle;
}
Each cell that has a dropdown directive applied, need to have a object field with the following settings:
When Grid is created, you can cycle through all rows and apply this object to all cells that have a DropDown directive attached. In this example, because multiple items can be checked from the dropdown list, the cell value is represented by a set of string values separated by commas. The code looks like this:
ngAfterViewInit(){
// Set a dropdown for row cells
let list = this.treegrid.getFullList();
for (let i = 0; i < list.length; i++)
for (let j = 0; j < list[i].cells.length; j++){
let cell: any = list[i].cells[j];
if (cell.cid == 4){
cell.dropdown = {
appRef: this.applicationRef,
adjustment: { top: 0, left: -3 },
data: cell
}
cell.value = [];
let selGenres = cell.text.split(', ');
for (let j = 0; j < selGenres.length; j++){
let foundItem = this.findGenre(selGenres[j]);
if (foundItem)
cell.value.push(foundItem);
}
}
}
}
findGenre(text: string){
let found: any = null;
for (var i = 0; i < this.dropdownItems.length; i++){
if (this.dropdownItems[i].text == text){
found = this.dropdownItems[i];
break;
}
}
return found;
}
Now you can apply the cell object with settings to the DropDown directive, using the directive name as a property.
<div [iuiDropDown]="cell.dropdown" (dropDownOpen)="onDropDownOpen($event, cell)" #dropdown>
<div class="treegrid-ccmb-adv-item-drop-mark"><span></span></div>
<span class="treegrid-ccmb-adv-item-label">{{cell.text}}</span>
<ng-template let-obj [iuiTemplate]="{ type: 'dropdown' }">
<ul class="dropdown-list" [ngStyle]="{ width: dropDownWidth + 'px'}" (mousedown)="listMouseDown($event)">
<li *ngFor="let item of dropdownItems" (mousedown)="itemSelected(cell, item)">
<span class="cell-checkbox" [ngStyle]="{ 'background-image': getItemValue(item) }" style="margin-top:-1px" (mousedown)="itemChecked($event, cell, item)"></span>
<span>{{item.text}}</span>
</li>
</ul>
</ng-template>
</div>
When cell is clicked, the dropdown window will popup, however the list will appear the same for all cells. In order to show checked items first, based on cell value that is previously selected options, you need to handle the dropDownOpen event for the DropDown directive. This allows you to modify how the dropdown list will appear based on which cell is clicked.
onDropDownOpen(e: any, cell: any){
this.isItemSelected = false;
if (cell){
this.dropDownWidth = this.getCellWidth(cell);
let cellItems = cell.value;
if (cellItems){
this.resetList();
for (let i = 0; i < cellItems.length; i++)
cellItems[i].checked = true;
}
this.showCheckedFirst();
}
}
// Calculates the width of tree grid cell
getCellWidth(cell: any){
let cellWidth: number = 100;
for (let j = 0; j < this.columns.length; j++){
if (this.columns[j].id == cell.cid){
cellWidth = this.getColumnWidth(this.columns[j]) + 3;
break;
}
}
return cellWidth;
}
protected getColumnWidth(column: any): number {
return column && column.width != undefined ? column.width : 100;
}
<div [iuiDropDown]="cell.dropdown" (dropDownOpen)="onDropDownOpen($event, cell)" #dropdown>
<div class="treegrid-ccmb-adv-item-drop-mark"><span></span></div>
<span class="treegrid-ccmb-adv-item-label">{{cell.text}}</span>
<ng-template let-obj [iuiTemplate]="{ type: 'dropdown' }">
<ul class="dropdown-list" [ngStyle]="{ width: dropDownWidth + 'px'}" (mousedown)="listMouseDown($event)">
<li *ngFor="let item of dropdownItems" (mousedown)="itemSelected(cell, item)">
<span class="cell-checkbox" [ngStyle]="{ 'background-image': getItemValue(item) }" style="margin-top:-1px" (mousedown)="itemChecked($event, cell, item)"></span>
<span>{{item.text}}</span>
</li>
</ul>
</ng-template>
</div>
In this case, the checked items appear first followed by a sorted list of unchecked items.
// Show checked items first and apply sorting
showCheckedFirst(){
let checkedList: Array = [];
let uncheckedList: Array = [];
for (let i = 0; i < this.dropdownItems.length; i++){
if (this.dropdownItems[i].checked)
checkedList.push(this.dropdownItems[i]);
else
uncheckedList.push(this.dropdownItems[i]);
}
checkedList.sort(this.sortComparer);
uncheckedList.sort(this.sortComparer);
this.dropdownItems.length = 0;
for (let i = 0; i < checkedList.length; i++)
this.dropdownItems.push(checkedList[i]);
for (let i = 0; i < uncheckedList.length; i++)
this.dropdownItems.push(uncheckedList[i]);
}
sortComparer(firstItem: any, secondItem: any){
let x = firstItem.text != undefined ? firstItem.text : null;
let y = secondItem.text != undefined ? secondItem.text : null;
if (x < y)
return -1;
else if (x > y)
return 1;
return 0;
}
Finally, the complete code that adds a drodown checked list to the cells in TreeGrid component is available here:
//
// app.module.ts
//
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { BrowserModule } from '@angular/platform-browser';
import { IntegralUIModule } from './integralui/integralui.module';
import { AppComponent } from './app.component';
@NgModule({
imports: [
BrowserModule,
FormsModule,
IntegralUIModule
],
declarations: [
AppComponent,
],
bootstrap: [ AppComponent ]
})
export class AppModule { }
//
// app.component.ts
//
import { Component, ViewContainerRef, ViewChild, ViewEncapsulation } from '@angular/core';
import { IntegralUITreeGrid } from './integralui/components/integralui.treegrid';
@Component({
selector: 'iui-app',
templateUrl: 'app.template.html',
styleUrls: ['sample-styles.css'],
encapsulation: ViewEncapsulation.None
})
export class AppComponent {
// Get a reference to the application root component
@ViewChild('application', {read: ViewContainerRef}) applicationRef: ViewContainerRef;
// Get a reference to the TreeGrid component
@ViewChild('treegrid') treegrid: IntegralUITreeGrid;
// An array that holds all options in the comboo box
public dropdownItems: Array;
public dropDownWidth: number = 150;
// TreeGrid settings
public columns: Array;
public rows: Array;
// Control Style
public treegridStyle: any = {
general: {
normal : 'treegrid-ccmb-adv-normal'
}
}
private imageChecked: string = 'url(app/integralui/resources/checkbox/checkbox-checked-1.png)';
private imageUnchecked: string = 'url(app/integralui/resources/checkbox/checkbox-unchecked-1.png)';
constructor(){
// Options to choose from
this.dropdownItems = [
{ text: "Action", checked: false },
{ text: "Adventure", checked: false },
{ text: "Animation", checked: false },
{ text: "Biography", checked: false },
{ text: "Comedy", checked: false },
{ text: "Crime", checked: false },
{ text: "Drama", checked: false },
{ text: "Fantasy", checked: false },
{ text: "Horror", checked: false },
{ text: "Mystery", checked: false },
{ text: "Sci-Fi", checked: false },
{ text: "Thriller", checked: false },
{ text: "Western", checked: false }
];
// Add columns and rows for the TreeGrid
this.columns = [
{ id: 1, headerText: "Title", width: 280 },
{ id: 4, headerText: "Genre", headerAlignment: "center", contentAlignment: "center", width: 270 },
{ id: 5, headerText: "Ratings", headerAlignment: "center", contentAlignment: "center", width: 70 },
{ id: 6, headerText: "Released", headerAlignment: "center", contentAlignment: "center", width: 120 }
];
this.rows = [
{
id: 1,
text: "2010",
cells: [{ cid: 1, text: "2010" }],
rows: [
{ id: 11, pid: 1, text: "Inception", cells: [{ cid: 1, text: "Inception" }, { cid: 2, value: true }, { cid: 3, text: "2010" }, { cid: 4, text: "Action, Mystery, Sci-Fi" }, { cid: 5, text: "8.8" }, { cid: 6, text: "16 Jul 2010" }] },
{ id: 12, pid: 1, text: "Toy Story 3", cells: [{ cid: 1, text: "Toy Story 3" }, { cid: 2, value: true }, { cid: 3, text: "2010" }, { cid: 4, text: "Animation, Adventure, Comedy" }, { cid: 5, text: "8.4" }, { cid: 6, text: "18 Jun 2010" } ] },
{ id: 13, pid: 1, text: "The Town", cells: [{ cid: 1, text: "The Town" }, { cid: 2 }, { cid: 3, text: "2010" }, { cid: 4, text: "Crime, Drama, Thriller" }, { cid: 5, text: "7.6" }, { cid: 6, text: "17 Sep 2010" }] },
{ id: 14, pid: 1, text: "The Social Network", cells: [{ cid: 1, text: "The Social Network" }, { cid: 2, value: true }, { cid: 3, text: "2010" }, { cid: 4, text: "Biography, Drama" }, { cid: 5, text: "7.8" }, { cid: 6, text: "01 Oct 2010" }] },
{ id: 15, pid: 1, text: "Black Swan", cells: [{ cid: 1, text: "Black Swan" }, { cid: 2 }, { cid: 3, text: "2010" }, { cid: 4, text: "Drama, Mystery, Thriller" }, { cid: 5, text: "8.0" }, { cid: 6, text: "17 Dec 2010" }] },
{ id: 16, pid: 1, text: "Shutter Island", cells: [{ cid: 1, text: "Shutter Island" }, { cid: 2, value: true }, { cid: 3, text: "2010" }, { cid: 4, text: "Mystery, Thriller" }, { cid: 5, text: "8.1" }, { cid: 6, text: "19 Feb 2010" }] }
]
},
{
id: 2,
text: "2012",
cells: [{ cid: 1, text: "2012" }],
rows: [
{ id: 21, pid: 2, text: "Django Unchained", cells: [{ cid: 1, text: "Django Unchained" }, { cid: 2, value: true }, { cid: 3, text: "2012" }, { cid: 4, text: "Western" }, { cid: 5, text: "8.5" }, { cid: 6, text: "25 Dec 2012" }] },
{ id: 22, pid: 2, text: "Prometheus", cells: [{ cid: 1, text: "Prometheus" }, { cid: 2, value: true }, { cid: 3, text: "2012" }, { cid: 4, text: "Adventure, Mystery, Sci-Fi" }, { cid: 5, text: "7.0" }, { cid: 6, text: "08 Jun 2012" } ] },
{ id: 23, pid: 2, text: "The Avengers", cells: [{ cid: 1, text: "The Avengers" }, { cid: 2 }, { cid: 3, text: "2012" }, { cid: 4, text: "Action, Adventure, Sci-Fi" }, { cid: 5, text: "8.2" }, { cid: 6, text: "04 May 2012" }] },
{ id: 24, pid: 2, text: "The Dark Knight Rises", cells: [{ cid: 1, text: "The Dark Knight Rises" }, { cid: 2, value: true }, { cid: 3, text: "2012" }, { cid: 4, text: "Action, Thriller" }, { cid: 5, text: "8.5" }, { cid: 6, text: "20 Jul 2012" }] }
]
},
{
id: 3,
text: "2013",
cells: [{ cid: 1, text: "2013" }],
rows: [
{ id: 31, pid: 3, text: "Gravity", cells: [{ cid: 1, text: "Gravity" }, { cid: 2 }, { cid: 3, text: "2013" }, { cid: 4, text: "Sci-Fi, Thriller" }, { cid: 5, text: "7.9" }, { cid: 6, text: "04 Oct 2013" }] },
{ id: 32, pid: 3, text: "The Wolf of Wall Street", cells: [{ cid: 1, text: "The Wolf of Wall Street" }, { cid: 2, value: true }, { cid: 3, text: "2013" }, { cid: 4, text: "Biography, Comedy, Crime" }, { cid: 5, text: "8.2" }, { cid: 6, text: "25 Dec 2013" } ] },
{ id: 33, pid: 3, text: "The Conjuring", cells: [{ cid: 1, text: "The Conjuring" }, { cid: 2 }, { cid: 3, text: "2013" }, { cid: 4, text: "Horror" }, { cid: 5, text: "7.5" }, { cid: 6, text: "19 Jul 2013" }] },
{ id: 34, pid: 3, text: "Blue Jasmine", cells: [{ cid: 1, text: "Blue Jasmine" }, { cid: 2, value: true }, { cid: 3, text: "2013" }, { cid: 4, text: "Drama" }, { cid: 5, text: "7.3" }, { cid: 6, text: "23 Aug 2013" }] },
{ id: 35, pid: 3, text: "Prisoners", cells: [{ cid: 1, text: "Prisoners" }, { cid: 2 }, { cid: 3, text: "2013" }, { cid: 4, text: "Crime, Drama, Mystery" }, { cid: 5, text: "8.1" }, { cid: 6, text: "20 Sep 2013" }] },
{ id: 36, pid: 3, text: "American Hustle", cells: [{ cid: 1, text: "American Hustle" }, { cid: 2 }, { cid: 3, text: "2013" }, { cid: 4, text: "Crime, Drama" }, { cid: 5, text: "7.3" }, { cid: 6, text: "20 Dec 2013" }] },
{ id: 37, pid: 3, text: "Frozen", cells: [{ cid: 1, text: "Frozen" }, { cid: 2 }, { cid: 3, text: "2013" }, { cid: 4, text: "Animation, Adventure, Comedy" }, { cid: 5, text: "7.7" }, { cid: 6, text: "27 Nov 2013" }] },
{ id: 38, pid: 3, text: "Rush", cells: [{ cid: 1, text: "Rush" }, { cid: 2 }, { cid: 3, text: "2013" }, { cid: 4, text: "Action, Biography, Drama" }, { cid: 5, text: "8.2" }, { cid: 6, text: "27 Sep 2013" }] },
{ id: 39, pid: 3, text: "This Is the End", cells: [{ cid: 1, text: "This Is the End" }, { cid: 2 }, { cid: 3, text: "2013" }, { cid: 4, text: "Comedy, Fantasy" }, { cid: 5, text: "6.7" }, { cid: 6, text: "12 Jun 2013" }] }
]
},
{
id: 4,
text: "2014",
cells: [{ cid: 1, text: "2014" }],
rows: [
{ id: 41, pid: 4, text: "Nightcrawler", cells: [{ cid: 1, text: "Nightcrawler" }, { cid: 2, value: true }, { cid: 3, text: "2014" }, { cid: 4, text: "Crime, Thriller" }, { cid: 5, text: "7.9" }, { cid: 6, text: "31 Oct 2014" }] },
{ id: 42, pid: 4, text: "Locke", cells: [{ cid: 1, text: "Locke" }, { cid: 2 }, { cid: 3, text: "2014" }, { cid: 4, text: "Drama" }, { cid: 5, text: "7.1" }, { cid: 6, text: "29 May 2014" }] },
{ id: 43, pid: 4, text: "Snowpiercer", cells: [{ cid: 1, text: "Snowpiercer" }, { cid: 2 }, { cid: 3, text: "2014" }, { cid: 4, text: "Action, Mystery, Sci-Fi" }, { cid: 5, text: "7.0" }, { cid: 6, text: "11 Jul 2014" }] },
{ id: 44, pid: 4, text: "Edge of Tomorrow", cells: [{ cid: 1, text: "Edge of Tomorrow" }, { cid: 2, value: true }, { cid: 3, text: "2014" }, { cid: 4, text: "Action, Adventure, Mystery" }, { cid: 5, text: "7.9" }, { cid: 6, text: "06 Jun 2014" }] },
{ id: 45, pid: 4, text: "Interstellar", cells: [{ cid: 1, text: "Interstellar" }, { cid: 2 }, { cid: 3, text: "2014" }, { cid: 4, text: "Adventure, Drama, Sci-Fi" }, { cid: 5, text: "8.7" }, { cid: 6, text: "07 Nov 2014" }] },
{ id: 46, pid: 4, text: "Interstellar", cells: [{ cid: 1, text: "Dawn of the Planet of the Apes" }, { cid: 2, value: true }, { cid: 3, text: "2014" }, { cid: 4, text: "Action, Drama, Sci-Fi" }, { cid: 5, text: "7.7" }, { cid: 6, text: "11 Jul 2014" }] }
]
},
];
}
ngAfterViewInit(){
// Set a dropdown for row cells
let list = this.treegrid.getFullList();
for (let i = 0; i < list.length; i++)
for (let j = 0; j < list[i].cells.length; j++){
let cell: any = list[i].cells[j];
if (cell.cid == 4){
cell.dropdown = {
appRef: this.applicationRef,
adjustment: { top: 0, left: -3 },
data: cell
}
cell.value = [];
let selGenres = cell.text.split(', ');
for (let j = 0; j < selGenres.length; j++){
let foundItem = this.findGenre(selGenres[j]);
if (foundItem)
cell.value.push(foundItem);
}
}
}
}
findGenre(text: string){
let found: any = null;
for (var i = 0; i < this.dropdownItems.length; i++){
if (this.dropdownItems[i].text == text){
found = this.dropdownItems[i];
break;
}
}
return found;
}
// DropDown Cell ---------------------------------------------------------------------
private isItemSelected: boolean = false;
// Prevent clicks in the list scrollbar area to close the dropdown window
listMouseDown(e: any){
if (!this.isItemSelected)
e.stopPropagation();
}
private getItemValue(item: any){
return item && item.checked == true ? this.imageChecked : this.imageUnchecked;
}
itemChecked(e: any, cell: any, item: any){
let currentValue = item.checked == true ? true : false;
item.checked = !currentValue;
e.stopPropagation();
}
itemSelected(cell: any, item: any){
if (cell){
let list: Array = [];
for (let i = 0; i < this.dropdownItems.length; i++){
if (this.dropdownItems[i].checked)
list.push(this.dropdownItems[i]);
}
cell.text = '';
for (let i = 0; i < list.length; i++)
cell.text += list[i].text + ", ";
if (cell.text != '')
cell.text = cell.text.substring(0, cell.text.length - 2);
cell.value = list;
this.isItemSelected = true;
}
}
// Calculates the width of treegrid cell
protected getColumnWidth(column: any): number {
return column && column.width != undefined ? column.width : 100;
}
getCellWidth(cell: any){
let cellWidth: number = 100;
for (let j = 0; j < this.columns.length; j++){
if (this.columns[j].id == cell.cid){
cellWidth = this.getColumnWidth(this.columns[j]) + 3;
break;
}
}
return cellWidth;
}
onDropDownOpen(e: any, cell: any){
this.isItemSelected = false;
if (cell){
this.dropDownWidth = this.getCellWidth(cell);
let cellItems = cell.value;
if (cellItems){
this.resetList();
for (let i = 0; i < cellItems.length; i++)
cellItems[i].checked = true;
}
this.showCheckedFirst();
}
}
resetList(){
for (let i = 0; i < this.dropdownItems.length; i++)
this.dropdownItems[i].checked = false;
}
// Show checked items first and apply sorting
showCheckedFirst(){
let checkedList: Array = [];
let uncheckedList: Array = [];
for (let i = 0; i < this.dropdownItems.length; i++){
if (this.dropdownItems[i].checked)
checkedList.push(this.dropdownItems[i]);
else
uncheckedList.push(this.dropdownItems[i]);
}
checkedList.sort(this.sortComparer);
uncheckedList.sort(this.sortComparer);
this.dropdownItems.length = 0;
for (let i = 0; i < checkedList.length; i++)
this.dropdownItems.push(checkedList[i]);
for (let i = 0; i < uncheckedList.length; i++)
this.dropdownItems.push(uncheckedList[i]);
}
sortComparer(firstItem: any, secondItem: any){
let x = firstItem.text != undefined ? firstItem.text : null;
let y = secondItem.text != undefined ? secondItem.text : null;
if (x < y)
return -1;
else if (x > y)
return 1;
return 0;
}
}
<div #application>
<iui-treegrid [appRef]="applicationRef" [controlStyle]="treegridStyle" [columns]="columns" [rows]="rows" [showFooter]="false" [rowHeight]="25" #treegrid>
<ng-template let-column [iuiTemplate]="{ type: 'header' }">
{{column.headerText}}
</ng-template>
<ng-template let-cell [iuiTemplate]="{ type: 'cell' }">
<span [ngSwitch]="cell.cid">
<div *ngSwitchCase="4">
<div [iuiDropDown]="cell.dropdown" (dropDownOpen)="onDropDownOpen($event, cell)" #dropdown>
<div class="treegrid-ccmb-adv-item-drop-mark"><span></span></div>
<span class="treegrid-ccmb-adv-item-label">{{cell.text}}</span>
<ng-template let-obj [iuiTemplate]="{ type: 'dropdown' }">
<ul class="dropdown-list" [ngStyle]="{ width: dropDownWidth + 'px'}" (mousedown)="listMouseDown($event)">
<li *ngFor="let item of dropdownItems" (mousedown)="itemSelected(cell, item)">
<span class="cell-checkbox" [ngStyle]="{ 'background-image': getItemValue(item) }" style="margin-top:-1px" (mousedown)="itemChecked($event, cell, item)"></span>
<span>{{item.text}}</span>
</li>
</ul>
</ng-template>
</div>
</div>
<div *ngSwitchDefault style="display:inline-block">
<span class="treegrid-ccmb-adv-item-label">{{cell.text}}</span>
</div>
</span>
</ng-template>
</iui-treegrid>
</div>
/* TreeGrid settings */
.treegrid-ccmb-adv-normal
{
width: 800px;
height: 375px;
}
.treegrid-ccmb-adv-normal .iui-treegrid-expand-box
{
margin-top: -3px;
}
.treegrid-ccmb-adv-item-label
{
display: inline-block;
margin-top: 3px;
padding: 2px 0;
}
/* DropDown Cell */
.dropdown-list
{
cursor: default;
margin: 0;
overflow: auto;
padding: 0;
list-style-type: none;
white-space: nowrap;
width: 150px;
height: 140px;
}
.dropdown-list li
{
padding: 5px;
}
.dropdown-list li:hover
{
background: #e5e5e5;
}
.cell-checkbox
{
background: url('') no-repeat 0 0;
display: inline-block;
padding: 0;
margin: 5px 7px 0 7px;
width: 16px;
height: 16px;
vertical-align: middle;
}
.treegrid-ccmb-adv-item-drop-mark
{
float: right;
}
.treegrid-ccmb-adv-item-drop-mark span
{
background: url(app/integralui/resources/icons.png) -144px -80px no-repeat;
display: inline-block;
opacity: 0.5;
overflow: hidden;
padding: 0 !important;
margin: 4px 2px 0 0;
width: 16px;
height: 16px;
vertical-align: middle;
}
By modifying the cell template in TreeGrid component for Angular, you can add a custom DropDown editor that will display checked item list. For this purpose, you can use the IntegralUIDropDown directive or any other Angular component with ability to show a popup window.
Based on settings in each individual cell, you can change how the dropdown list will appear. You can have a list of checked items first, followed by a list of sorted items. This helps in quickly navigating to specific option, if the list contains many items.
This example, only presents a DropDown editor. The TreeGrid component is fully customizable, and you can add any custom editor to any cell, or even use different editors for specific cell based on different conditions. There are no limitations, based on your application requirements; you can use any editor you need.
The TreeGrid component is part of IntegralUI Web.