I am using angular slickgrid to display my data and also for inline editing data. In table inline edit working fine but some exceptional cases are present. For multiselect editor the cell change callback not called while i am pressing ok button without changing the multiselect value its fine. but the edit view still maintaining the focus state. Any solution to remove the focus in the editor.
Current Behavior
Multiselect editor maintaining the focus while pressing ok button without changing data.
Expected Behavior
Multiselect editor field needs to remove the focus while pressing ok button without changing data.
Here i shared my code snippet for your reference
Html
<angular-slickgrid gridId="{{gridId}}" [columnDefinitions]="columnDefinitions" [gridOptions]="gridOptions"
[dataset]="filteredResultList" (sgOnClick)="onGridItemClick($event)"
(onAngularGridCreated)="angularGridReady($event)"
(sgOnCellChange)="onCellChanged($event.detail.eventData, $event.detail.args)">
</angular-slickgrid>
Grid options
public gridOptions: GridOption = {
enableAutoResize: true,
autoEdit: false,
autoCommitEdit: true,
enableCellNavigation: true,
editable: true,
enableSorting: true,
enableFiltering: true,
i18n: this.translateService,
enableExcelExport: true,
enableExport: true,
gridMenu: {
hideExportExcelCommand: true,
hideExportCsvCommand: true,
customItems: [{
command: "cspfm-excel-export",
titleKey: "EXPORT_TO_EXCEL",
iconCssClass: "fa fa-file-excel-o",
action: (event, callbackArgs) => {
this.excelExport(event, callbackArgs)
}
},
{
command: "cspfm-csv-export",
titleKey: "EXPORT_TO_CSV",
iconCssClass: "fa fa-download",
action: (event, callbackArgs) => {
this.excelExport(event, callbackArgs)
}
}
],
},
enableAutoTooltip: true,
autoTooltipOptions: {
enableForCells: true,
enableForHeaderCells: true,
maxToolTipLength: 1000
},
autoResize: {
containerId: this.gridContainerId,
calculateAvailableSizeBy: 'container'
},
exportOptions: {
exportWithFormatter: true
},
excelExportOptions: {
exportWithFormatter: true,
},
headerMenu: {
hideColumnHideCommand: true
},
enableTranslate: true,
presets: {
sorters: [{
columnId: this.tableColumnInfo['pfm187413']['pfm187413_name']['prop'],
direction: 'ASC'
}],
}
};
Table column info
public tableColumnInfo = {
"pfm187413": {
"pfm187413_name": {
"label": "LTFieldTrackSingleGLISTVA_WEB_Grid_with_List.Element.fieldtracksinglejuy.name",
"fieldName": "name",
"prop": "name",
"fieldType": "TEXT",
"child": "",
"dateFormat": "",
"mappingDetails": "",
"currencyDetails": ""
},
"pfm187413_student": {
"label": "LTFieldTrackSingleGLISTVA_WEB_Grid_with_List.Element.fieldtracksinglejuy.student",
"fieldName": "student",
"prop": "student",
"fieldType": "TEXT",
"child": "",
"dateFormat": "",
"mappingDetails": "",
"currencyDetails": ""
},
"pfm187413_about": {
"label": "LTFieldTrackSingleGLISTVA_WEB_Grid_with_List.Element.fieldtracksinglejuy.about",
"fieldName": "about",
"prop": "about",
"fieldType": "TEXTAREA",
"child": "",
"dateFormat": "",
"mappingDetails": "",
"currencyDetails": ""
},
"pfm187413_qualification": {
"label": "LTFieldTrackSingleGLISTVA_WEB_Grid_with_List.Element.fieldtracksinglejuy.qualification",
"fieldName": "qualification",
"prop": "qualification",
"fieldType": "DROPDOWN",
"child": "",
"dateFormat": "",
"mappingDetails": {
"ma": "MA",
"ba": "BA",
"bt": "BTECH",
"mca": "MCA"
},
"currencyDetails": ""
},
"pfm187413_dateofbirth": {
"label": "LTFieldTrackSingleGLISTVA_WEB_Grid_with_List.Element.fieldtracksinglejuy.dateofbirth",
"fieldName": "dateofbirth",
"prop": "dateofbirth",
"fieldType": "DATE",
"child": "",
"dateFormat": this.appUtilityConfig.userDateFormat,
"mappingDetails": "",
"currencyDetails": ""
},
"pfm187413_starttime": {
"label": "LTFieldTrackSingleGLISTVA_WEB_Grid_with_List.Element.fieldtracksinglejuy.starttime",
"fieldName": "starttime",
"prop": "starttime",
"fieldType": "TIMESTAMP",
"child": "",
"dateFormat": this.appUtilityConfig.userDateTimeFormat,
"mappingDetails": "",
"currencyDetails": ""
},
"pfm187413_gender": {
"label": "LTFieldTrackSingleGLISTVA_WEB_Grid_with_List.Element.fieldtracksinglejuy.gender",
"fieldName": "gender",
"prop": "gender",
"fieldType": "RADIO",
"child": "",
"dateFormat": "",
"mappingDetails": {
"m": "Male",
"f": "Female"
},
"currencyDetails": ""
},
"pfm187413_favourites": {
"label": "LTFieldTrackSingleGLISTVA_WEB_Grid_with_List.Element.fieldtracksinglejuy.favourites",
"fieldName": "favourites",
"prop": "favourites",
"fieldType": "MULTISELECT",
"child": "",
"dateFormat": "",
"mappingDetails": {
"ds": "Dosa",
"idli": "Idly",
"ps": "Pasta",
"sl": "Salad"
},
"currencyDetails": ""
},
"pfm187413_sports": {
"label": "LTFieldTrackSingleGLISTVA_WEB_Grid_with_List.Element.fieldtracksinglejuy.sports",
"fieldName": "sports",
"prop": "sports",
"fieldType": "CHECKBOX",
"child": "",
"dateFormat": "",
"mappingDetails": {
"ck": "Cricket",
"ft": "Football",
"rg": "Rugby"
},
"currencyDetails": ""
},
"pfm187413_servicecost": {
"label": "LTFieldTrackSingleGLISTVA_WEB_Grid_with_List.Element.fieldtracksinglejuy.servicecost",
"fieldName": "servicecost",
"prop": "servicecost",
"fieldType": "CURRENCY",
"child": "",
"dateFormat": "",
"mappingDetails": "",
"currencyDetails": {
"currencyCode": "$",
"display": true,
"digitsInfo": "1.2-2",
"locale": "ms-BN"
}
},
"pfm187413_cgapercent": {
"label": "LTFieldTrackSingleGLISTVA_WEB_Grid_with_List.Element.fieldtracksinglejuy.cgapercent",
"fieldName": "cgapercent",
"prop": "cgapercent",
"fieldType": "DECIMAL",
"child": "",
"dateFormat": "",
"mappingDetails": "",
"currencyDetails": ""
},
"pfm187413_points": {
"label": "LTFieldTrackSingleGLISTVA_WEB_Grid_with_List.Element.fieldtracksinglejuy.points",
"fieldName": "points",
"prop": "points",
"fieldType": "NUMBER",
"child": "",
"dateFormat": "",
"mappingDetails": "",
"currencyDetails": ""
},
"pfm187413_url": {
"label": "LTFieldTrackSingleGLISTVA_WEB_Grid_with_List.Element.fieldtracksinglejuy.url",
"fieldName": "url",
"prop": "url",
"fieldType": "URL",
"child": "",
"dateFormat": "",
"mappingDetails": "",
"currencyDetails": ""
},
"pfm187413_isactive": {
"label": "LTFieldTrackSingleGLISTVA_WEB_Grid_with_List.Element.fieldtracksinglejuy.isactive",
"fieldName": "isactive",
"prop": "isactive",
"fieldType": "BOOLEAN",
"child": "",
"dateFormat": "",
"mappingDetails": "",
"currencyDetails": ""
}
}
};
Column definitions
public columnDefinitions: Array<Column> = [{
id: this.tableColumnInfo['pfm187413']['pfm187413_name']['prop'],
nameKey: this.tableColumnInfo['pfm187413']['pfm187413_name']['label'],
field: this.tableColumnInfo['pfm187413']['pfm187413_name']['prop'],
sortable: true,
type: FieldType.string,
exportCustomFormatter: CspfmDataFormatter,
minWidth: this.columnMinWidth,
formatter: CspfmDataFormatter,
filterable: true,
filter: {
model: Filters.compoundInput
},
editor: {
model: Editors.longText,
required: true
},
params: {
pipe: this.cspfmDataDisplay,
fieldInfo: this.tableColumnInfo['pfm187413']['pfm187413_name']
}
}, {
id: this.tableColumnInfo['pfm187413']['pfm187413_student']['prop'],
nameKey: this.tableColumnInfo['pfm187413']['pfm187413_student']['label'],
field: this.tableColumnInfo['pfm187413']['pfm187413_student']['prop'],
sortable: true,
type: FieldType.string,
exportCustomFormatter: CspfmDataFormatter,
minWidth: this.columnMinWidth,
formatter: CspfmDataFormatter,
filterable: true,
filter: {
model: Filters.compoundInput
},
editor: {
model: Editors.longText,
required: true
},
params: {
pipe: this.cspfmDataDisplay,
fieldInfo: this.tableColumnInfo['pfm187413']['pfm187413_student']
}
}, {
id: this.tableColumnInfo['pfm187413']['pfm187413_about']['prop'],
nameKey: this.tableColumnInfo['pfm187413']['pfm187413_about']['label'],
field: this.tableColumnInfo['pfm187413']['pfm187413_about']['prop'],
sortable: true,
type: FieldType.string,
exportCustomFormatter: CspfmDataFormatter,
minWidth: this.columnMinWidth,
formatter: CspfmDataFormatter,
filterable: true,
filter: {
model: Filters.compoundInput
},
params: {
pipe: this.cspfmDataDisplay,
fieldInfo: this.tableColumnInfo['pfm187413']['pfm187413_about']
}
}, {
id: this.tableColumnInfo['pfm187413']['pfm187413_qualification']['prop'],
nameKey: this.tableColumnInfo['pfm187413']['pfm187413_qualification']['label'],
field: this.tableColumnInfo['pfm187413']['pfm187413_qualification']['prop'],
sortable: true,
type: FieldType.string,
exportCustomFormatter: CspfmDataFormatter,
minWidth: this.columnMinWidth,
formatter: CspfmDataFormatter,
queryField: this.tableColumnInfo['pfm187413']['pfm187413_qualification']['prop'] + appConstant['customFieldSuffix']['slickgrid'],
filterable: true,
filter: {
collection: this.getLabelValue(this.qualification_371375),
model: Filters.multipleSelect
},
editor: {
model: Editors.singleSelect,
collection: this.getKeyValue(this.qualification_371375),
required: true
},
params: {
pipe: this.cspfmDataDisplay,
fieldInfo: this.tableColumnInfo['pfm187413']['pfm187413_qualification']
}
}, {
id: this.tableColumnInfo['pfm187413']['pfm187413_dateofbirth']['prop'],
nameKey: this.tableColumnInfo['pfm187413']['pfm187413_dateofbirth']['label'],
field: this.tableColumnInfo['pfm187413']['pfm187413_dateofbirth']['prop'],
sortable: true,
type: FieldType.date,
exportCustomFormatter: CspfmDataFormatter,
minWidth: this.columnMinWidth,
formatter: CspfmDataFormatter,
queryField: this.tableColumnInfo['pfm187413']['pfm187413_dateofbirth']['prop'] + appConstant['customFieldSuffix']['slickgrid'],
filterable: true,
filter: {
operator: OperatorType.rangeInclusive,
model: Filters.compoundDate
},
editor: {
model: Editors.date,
required: true,
editorOptions:
{
onReady: (selectedDates, dateStr, instance) => {
const flatpickrYearElement = instance.currentYearElement;
const children = flatpickrYearElement.parentElement.children;
for (let i in children) {
if (children.hasOwnProperty(i)) {
children[i].style.display = 'none';
}
}
const yearSelect = document.createElement('select');
var minDate = new Date();
minDate.setHours(0, 0, 0, 0);
minDate.setFullYear(minDate.getFullYear() - 100);
var maxDate = new Date();
maxDate.setHours(23, 59, 58, 999);
maxDate.setFullYear(maxDate.getFullYear() + 50);
instance.config._minDate = minDate;
instance.config._maxDate = maxDate;
const minYear = new Date(instance.config._minDate).getFullYear();
const maxYear = new Date(instance.config._maxDate).getFullYear();
for (let i = minYear; i <= maxYear; i++) {
const option = document.createElement('option');
option.value = '' + i;
option.text = '' + i;
yearSelect.appendChild(option);
}
yearSelect.addEventListener('change', (event) => {
flatpickrYearElement.value = event.target['value'];
instance.changeYear(parseInt(event.target['value']));
});
yearSelect.className = 'flatpickr-monthDropdown-months';
yearSelect.id = 'flatpickr-custom-year-select';
yearSelect.value = instance.currentYearElement.value;
flatpickrYearElement.parentElement.appendChild(yearSelect);
},
onMonthChange: (selectedDates, dateStr, instance) => {
document.getElementById('flatpickr-custom-year-select')['value'] = '' + instance.currentYear;
}
} as FlatpickrOption
},
params: {
pipe: this.cspfmDataDisplay,
fieldInfo: this.tableColumnInfo['pfm187413']['pfm187413_dateofbirth']
}
}, {
id: this.tableColumnInfo['pfm187413']['pfm187413_starttime']['prop'],
nameKey: this.tableColumnInfo['pfm187413']['pfm187413_starttime']['label'],
field: this.tableColumnInfo['pfm187413']['pfm187413_starttime']['prop'],
sortable: true,
type: FieldType.dateTime,
exportCustomFormatter: CspfmDataFormatter,
minWidth: this.columnMinWidth,
formatter: CspfmDataFormatter,
queryField: this.tableColumnInfo['pfm187413']['pfm187413_starttime']['prop'] + appConstant['customFieldSuffix']['slickgrid'],
filterable: true,
filter: {
operator: OperatorType.rangeInclusive,
model: Filters.compoundDate
},
params: {
pipe: this.cspfmDataDisplay,
fieldInfo: this.tableColumnInfo['pfm187413']['pfm187413_starttime']
},
editor: {
model: Editors.date,
required: true,
editorOptions:
{
onReady: (selectedDates, dateStr, instance) => {
const flatpickrYearElement = instance.currentYearElement;
const children = flatpickrYearElement.parentElement.children;
for (let i in children) {
if (children.hasOwnProperty(i)) {
children[i].style.display = 'none';
}
}
const yearSelect = document.createElement('select');
var minDate = new Date();
minDate.setHours(0, 0, 0, 0);
minDate.setFullYear(minDate.getFullYear() - 100);
var maxDate = new Date();
maxDate.setHours(23, 59, 58, 999);
maxDate.setFullYear(maxDate.getFullYear() + 50);
instance.config._minDate = minDate;
instance.config._maxDate = maxDate;
const minYear = new Date(instance.config._minDate).getFullYear();
const maxYear = new Date(instance.config._maxDate).getFullYear();
for (let i = minYear; i <= maxYear; i++) {
const option = document.createElement('option');
option.value = '' + i;
option.text = '' + i;
yearSelect.appendChild(option);
}
yearSelect.addEventListener('change', (event) => {
flatpickrYearElement.value = event.target['value'];
instance.changeYear(parseInt(event.target['value']));
});
yearSelect.className = 'flatpickr-monthDropdown-months';
yearSelect.id = 'flatpickr-custom-year-select';
yearSelect.value = instance.currentYearElement.value;
flatpickrYearElement.parentElement.appendChild(yearSelect);
},
onMonthChange: (selectedDates, dateStr, instance) => {
document.getElementById('flatpickr-custom-year-select')['value'] = '' + instance.currentYear;
}
} as FlatpickrOption
}
}, {
id: this.tableColumnInfo['pfm187413']['pfm187413_gender']['prop'],
nameKey: this.tableColumnInfo['pfm187413']['pfm187413_gender']['label'],
field: this.tableColumnInfo['pfm187413']['pfm187413_gender']['prop'],
sortable: true,
type: FieldType.string,
exportCustomFormatter: CspfmDataFormatter,
minWidth: this.columnMinWidth,
formatter: CspfmDataFormatter,
queryField: this.tableColumnInfo['pfm187413']['pfm187413_gender']['prop'] + appConstant['customFieldSuffix']['slickgrid'],
filterable: true,
filter: {
collection: this.getLabelValue(this.gender_371378),
model: Filters.multipleSelect
},
editor: {
model: Editors.singleSelect,
collection: this.getKeyValue(this.gender_371378),
required: true
},
params: {
pipe: this.cspfmDataDisplay,
fieldInfo: this.tableColumnInfo['pfm187413']['pfm187413_gender']
}
}, {
id: this.tableColumnInfo['pfm187413']['pfm187413_favourites']['prop'],
nameKey: this.tableColumnInfo['pfm187413']['pfm187413_favourites']['label'],
field: this.tableColumnInfo['pfm187413']['pfm187413_favourites']['prop'],
sortable: true,
type: FieldType.string,
exportCustomFormatter: CspfmDataFormatter,
minWidth: this.columnMinWidth,
formatter: CspfmDataFormatter,
queryField: this.tableColumnInfo['pfm187413']['pfm187413_favourites']['prop'] + appConstant['customFieldSuffix']['slickgrid'],
filterable: true,
filter: {
collection: this.getLabelValue(this.favourites_371379),
operator: OperatorType.inContains,
model: Filters.multipleSelect
},
editor: {
model: Editors.multipleSelect,
collection: this.getKeyValue(this.favourites_371379)
},
params: {
pipe: this.cspfmDataDisplay,
fieldInfo: this.tableColumnInfo['pfm187413']['pfm187413_favourites']
}
}, {
id: this.tableColumnInfo['pfm187413']['pfm187413_sports']['prop'],
nameKey: this.tableColumnInfo['pfm187413']['pfm187413_sports']['label'],
field: this.tableColumnInfo['pfm187413']['pfm187413_sports']['prop'],
sortable: true,
type: FieldType.string,
exportCustomFormatter: CspfmDataFormatter,
minWidth: this.columnMinWidth,
formatter: CspfmDataFormatter,
queryField: this.tableColumnInfo['pfm187413']['pfm187413_sports']['prop'] + appConstant['customFieldSuffix']['slickgrid'],
filterable: true,
filter: {
collection: this.getLabelValue(this.sports_371380),
operator: OperatorType.inContains,
model: Filters.multipleSelect
},
editor: {
model: Editors.multipleSelect,
collection: this.getKeyValue(this.sports_371380),
operator: OperatorType.inContains
},
params: {
pipe: this.cspfmDataDisplay,
fieldInfo: this.tableColumnInfo['pfm187413']['pfm187413_sports']
}
}, {
id: this.tableColumnInfo['pfm187413']['pfm187413_servicecost']['prop'],
nameKey: this.tableColumnInfo['pfm187413']['pfm187413_servicecost']['label'],
field: this.tableColumnInfo['pfm187413']['pfm187413_servicecost']['prop'],
sortable: true,
type: FieldType.number,
exportCustomFormatter: CspfmDataFormatter,
minWidth: this.columnMinWidth,
formatter: CspfmDataFormatter,
filterable: true,
filter: {
model: Filters.compoundInputNumber
},
editor: {
model: Editors.float,
params: {
decimalPlaces: 2
},
required: true
},
params: {
pipe: this.cspfmDataDisplay,
fieldInfo: this.tableColumnInfo['pfm187413']['pfm187413_servicecost']
}
}, {
id: this.tableColumnInfo['pfm187413']['pfm187413_cgapercent']['prop'],
nameKey: this.tableColumnInfo['pfm187413']['pfm187413_cgapercent']['label'],
field: this.tableColumnInfo['pfm187413']['pfm187413_cgapercent']['prop'],
sortable: true,
type: FieldType.number,
exportCustomFormatter: CspfmDataFormatter,
minWidth: this.columnMinWidth,
formatter: CspfmDataFormatter,
filterable: true,
filter: {
model: Filters.compoundInputNumber
},
params: {
pipe: this.cspfmDataDisplay,
fieldInfo: this.tableColumnInfo['pfm187413']['pfm187413_cgapercent']
}
}, {
id: this.tableColumnInfo['pfm187413']['pfm187413_points']['prop'],
nameKey: this.tableColumnInfo['pfm187413']['pfm187413_points']['label'],
field: this.tableColumnInfo['pfm187413']['pfm187413_points']['prop'],
sortable: true,
type: FieldType.number,
exportCustomFormatter: CspfmDataFormatter,
minWidth: this.columnMinWidth,
formatter: CspfmDataFormatter,
filterable: true,
filter: {
model: Filters.compoundInputNumber
},
editor: {
model: cspfmCustomEditor,
},
params: {
pipe: this.cspfmDataDisplay,
fieldInfo: this.tableColumnInfo['pfm187413']['pfm187413_points']
}
}, {
id: this.tableColumnInfo['pfm187413']['pfm187413_url']['prop'],
nameKey: this.tableColumnInfo['pfm187413']['pfm187413_url']['label'],
field: this.tableColumnInfo['pfm187413']['pfm187413_url']['prop'],
sortable: true,
type: FieldType.string,
exportCustomFormatter: CspfmDataFormatter,
minWidth: this.columnMinWidth,
formatter: CspfmDataFormatter,
filterable: true,
filter: {
model: Filters.compoundInput
},
editor: {
model: Editors.longText,
required: true
},
params: {
pipe: this.cspfmDataDisplay,
fieldInfo: this.tableColumnInfo['pfm187413']['pfm187413_url']
}
}, {
id: this.tableColumnInfo['pfm187413']['pfm187413_isactive']['prop'],
nameKey: this.tableColumnInfo['pfm187413']['pfm187413_isactive']['label'],
field: this.tableColumnInfo['pfm187413']['pfm187413_isactive']['prop'],
sortable: true,
type: FieldType.string,
exportCustomFormatter: CspfmDataFormatter,
minWidth: this.columnMinWidth,
formatter: CspfmDataFormatter,
filterable: true,
filter: {
collection: this.getLabelValue({
true: "true",
false: "false"
}),
model: Filters.multipleSelect
},
editor: {
model: Editors.checkbox,
collection: [{
value: true,
label: 'True'
},
{
valued: false,
label: 'False'
}
]
},
params: {
pipe: this.cspfmDataDisplay,
fieldInfo: this.tableColumnInfo['pfm187413']['pfm187413_isactive']
}
}];
Behavior of angular slickgrid sample project
Software Version
Angular : 7.3.5
Angular-Slickgrid : 2.19.0
TypeScript : 3.1.6
Operating System : Windows 10
Node : 10.16.3
NPM : 6.9.0