Posted 20 April 2020, 12:17 pm EST
I am using wijmo 5 flexgrid with Angular 8 and trying to create an inline editable grid with Edit button at every row. Each row has a checkbox column(isWorking) and a dropdown column (Asset Type) which looks like a plain grid cell when Edit button is not clicked. The checkbox should be editable when the Edit button of that specific row is clicked. The dropdown field should be editable when the Edit button is clicked and the checkbox is checked. If the checkbox is unchecked, the dropdown field reverts to the readonly grid cell and the value should show “–Select Asset Type–”. If again checked, existing Asset Type value, if any, should be selected. The user also can change Asset Type value by changing selection.
The issues I am facing :
- When in Edit mode, the checkbox is added, it always shows checked in the UI, irrespective of the actual value (true/false). How to display the correct checked value in the checkbox?
- When in Edit mode, the checkbox is clicked to check/uncheck, how to toggle the Asset Type field between editable dropdown and readonly grid cell, and change the value accordingly?
The Code is in the link
https://stackblitz.com/edit/angular-zx3qvc
app.component.ts
import { Component, ViewChild } from '@angular/core';
import { CollectionView, ObservableArray } from 'wijmo/wijmo';
import * as wjCore from 'wijmo/wijmo';
import * as wjInput from 'wijmo/wijmo.input';
import * as wjGrid from 'wijmo/wijmo.grid';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
private _currentEditItem: any = null;
public data : any;
public deptList: any = [
{'deptId':'D1', 'deptName':'Accounts'},
{'deptId':'D2', 'deptName':'Development'},
{'deptId':'D3', 'deptName':'HR'}
];
public assetTypeList: any = [
{'assetTypeId':'', 'assetTypeName':'-- Select Asset Type --'},
{'assetTypeId':'A1', 'assetTypeName':'Desktop'},
{'assetTypeId':'A2', 'assetTypeName':'Laptop'}
];
public empList: any = [
{'empId':'E1', 'empName':'AA', 'deptId':'D3', 'isWorking':true, 'assetTypeId':'A2'},
{'empId':'E2', 'empName':'BB', 'deptId':'D2', 'isWorking':false, 'assetTypeId':''},
{'empId':'E3', 'empName':'CC', 'deptId':'D1', 'isWorking':false, 'assetTypeId':''},
{'empId':'E4', 'empName':'DD', 'deptId':'D2', 'isWorking':true, 'assetTypeId':'A1'}
];
@ViewChild('flex') flex:wjGrid.FlexGrid;
// we can still use DataMap to display different key and value while in read mode
public deptMap = new wjGrid.DataMap(this.deptList, 'deptId', 'deptName');
public assetTypeMap = new wjGrid.DataMap(this.assetTypeList, 'assetTypeId', 'assetTypeName');
constructor() {
this.data = new wjCore.CollectionView(this.empList);
}
initializeGrid(flex: wjGrid.FlexGrid) {
flex.rows.defaultSize = 40;
// custom formatter to paint buttons and editors
flex.formatItem.addHandler((s: wjGrid.FlexGrid, e: wjGrid.FormatItemEventArgs) => {
if (e.panel == s.cells) {
let col = s.columns[e.col],
item = s.rows[e.row].dataItem;
if (item == this._currentEditItem) {
// create editors and buttons for the item being edited
switch (col.binding) {
case 'buttons':
e.cell.innerHTML = document.getElementById('tplBtnEditMode').innerHTML;
e.cell['dataItem'] = item;
break;
case 'empName':
e.cell.innerHTML = '<input class="form-control" ' +
'id="' + col.binding + '" ' +
'value="' + s.getCellData(e.row, e.col, true) + '"/>';
break;
case 'deptId':
// create a ComboBox
e.cell.innerHTML = '';
var cb = new wjInput.ComboBox(wjCore.createElement('<div></div>', e.cell), {
itemsSource: this.deptList,
displayMemberPath: 'deptName',
selectedValuePath: 'deptId'
});
var dt = e.panel.getCellData(e.row, e.col, false);
cb.selectedValue = dt;
cb.inputElement.id = col.binding;
break;
case 'assetTypeId':
// if isWorking is true, create a ComboBox
if (item.isWorking){
e.cell.innerHTML = '';
var cb = new wjInput.ComboBox(wjCore.createElement('<div></div>', e.cell), {
itemsSource: this.assetTypeList,
displayMemberPath: 'assetTypeName',
selectedValuePath: 'assetTypeId'
});
var dt = e.panel.getCellData(e.row, e.col, false);
cb.selectedValue = dt;
cb.inputElement.id = col.binding;
}
break;
case 'isWorking':
e.cell.innerHTML = '<input type="checkbox" class="wj-cell-check" ' +
'id="' + col.binding + '" ' +
// 'value="' + s.getCellData(e.row, e.col, true) + '"/>';
'value=' + col.collectionView.currentItem.isWorking + ' ' +
// 'binding=' + col.collectionView.currentItem.isWorking + ' ' +
'checked=' + col.collectionView.currentItem.isWorking + ' />';
const chk = <HTMLInputElement>e.cell.firstChild;
chk.addEventListener('click', () => {
const row = flex.rows[e.row];
//console.log(row);
if (chk.checked)
console.log('yes');
else
console.log('no');
})
break;
}
} else {
// create buttons for items not being edited
switch (col.binding) {
case 'buttons':
e.cell.innerHTML = document.getElementById('tplBtnViewMode').innerHTML;
e.cell['dataItem'] = item;
break;
}
}
}
});
// handle button clicks
flex.addEventListener(flex.hostElement, 'click', (e: MouseEvent) => {
let targetBtn: HTMLButtonElement;
if (e.target instanceof HTMLButtonElement) {
targetBtn = e.target;
}
// else if (e.target instanceof HTMLSpanElement && e.target.classList.contains('glyphicon')) {
// targetBtn = e.target.parentElement as HTMLButtonElement;
// }
if (targetBtn) {
// get button's data item
let item = wjCore.closest(targetBtn, '.wj-cell')['dataItem'];
// handle buttons
switch (targetBtn.id) {
// start editing this item
case 'btnEdit':
this._editItem(item);
break;
// remove this item from the collection
// case 'btnDelete':
// (<wjCore.CollectionView>flex.collectionView).remove(item);
// break;
// commit edits
case 'btnOK':
this._commitEdit();
break;
// cancel edits
case 'btnCancel':
this._cancelEdit();
break;
}
}
e.preventDefault();
});
// exit edit mode when scrolling the grid or losing focus
flex.scrollPositionChanged.addHandler(this._cancelEdit.bind(this));
flex.lostFocus.addHandler(this._cancelEdit.bind(this));
}
private _editItem(item: any) {
this._cancelEdit();
this._currentEditItem = item;
this.flex.invalidate();
}
private _commitEdit() {
if (this._currentEditItem) {
this.flex.columns.forEach((col: any) => {
let input = <HTMLInputElement>this.flex.hostElement.querySelector('#' + col.binding);
if (input) {
let value = wjCore.changeType(input.value, col.dataType, col.format);
// get the key value to update in CollectionView
if(col.binding === 'deptId') {
value = this.deptMap.getKeyValue(value);
}
if (col.binding === 'isWorking') {
value = wjCore.changeType(input.checked, col.dataType, col.format);
}
if (wjCore.getType(value) == col.dataType) {
this._currentEditItem[col.binding] = value;
}
}
});
}
console.log(this._currentEditItem);
this._currentEditItem = null;
this.flex.invalidate();
}
private _cancelEdit() {
if (this._currentEditItem) {
this._currentEditItem = null;
this.flex.invalidate();
}
}
}
app.component.html
<div class="header">
<div class="container">
<h1>
</h1>
</div>
</div>
<!-- content -->
<div class="container">
<div>
<wj-flex-grid #flex [itemsSource]="data"
[headersVisibility]="'Column'" (initialized)="initializeGrid(flex)">
<wj-flex-grid-column [header]="'Employee Name'" [binding]="'empName'" [isReadOnly]="true" [width]="'4*'">
</wj-flex-grid-column>
<wj-flex-grid-column [header]="'Department'" [binding]="'deptId'" [isReadOnly]="true" [width]="'4*'" [dataMap]="deptMap">
</wj-flex-grid-column>
<wj-flex-grid-column [header]="'isWorking'" [binding]="'isWorking'" [isReadOnly]="true" [width]="'4*'">
</wj-flex-grid-column>
<wj-flex-grid-column [header]="'Asset Type'" [binding]="'assetTypeId'" [isReadOnly]="true" [width]="'4*'" [dataMap]="assetTypeMap">
</wj-flex-grid-column>
<wj-flex-grid-column [header]="'Actions'" [binding]="'buttons'" [isReadOnly]="true" [width]="'3*'"></wj-flex-grid-column>
</wj-flex-grid>
<!-- template for buttons on items in view mode -->
<div id="tplBtnViewMode" style="display:none">
<button id="btnEdit" class="btn btn-default btn-sm">
Edit
</button>
</div>
<!-- template for buttons on items in edit mode -->
<div id="tplBtnEditMode" style="display:none">
<button id="btnOK" class="btn btn-primary btn-sm">
OK
</button>
<button id="btnCancel" class="btn btn-warning btn-sm">
Cancel
</button>
</div>
</div>
</div>