[VUE] Gantt multi field filter error with gridfieldfilterpickergroup: Uncaught (in promise) TypeError: Cannot read props
We have use the example from: https://www.bryntum.com/products/gantt/examples/fieldfilters/ to implement the gridfieldfilterpickergroup on our tradeDiscipline column in the Gantt's grid.
We are using v5.2.9 of the Bryntum Gantt package.
In our class that extends TaskModel, we have applied our relations:
static relations = {
tradeDiscipline : {
foreignKey : 'tradeDisciplineId',
foreignStore : tradeDisciplineStore
}
}
We have implemented our Grid feature:
get filterFeature() {
const filterPickerFields = {
tradeDisciplineId: {
relatedDisplayField: 'description'
}
};
return {
isMulti: {
allowedFieldNames: ['activityName', 'startDate', 'endDate', 'duration', 'responsible', 'tradeDisciplineId', 'progress'],
fields: filterPickerFields
}
}
}
Our columns are defined as follows:
get columns() {
const data = this.data;
return [
{ id: "id", field : "id", text : 'ID', hidden: true },
{ id: "activityName", type: "name", field: 'activityName', text: 'Activity Name' },
{ id: "issueConstraints", type: "issue-column", width: "50px", text: "Issues/Constraints" },
{ id: "comment", type: "comment-column", width: "50px", text: "Comment"},
{ id: "startDate", type: "startdate", field : 'startDate', text : 'Start Date', format: bryntumDateFormat },
{ id: "endDate", type: "enddate", field : 'endDate', text : 'End Date', format: bryntumDateFormat },
{ id: "duration", type: "duration", field : "duration", text : "Duration", width: "50px"},
{
id: "discipline",
field : 'tradeDisciplineId',
type: 'number',
text : 'Discipline',
renderer : ({ record }) => record.tradeDiscipline?.description
},
{
id: 'responsible',
field: 'responsible',
text: 'Responsible'
},
{ id: "progress", type: "percentdone", field:'progress', showCircle: true, width: 70, text: "Progress" }
];
}
Our new store:
import {Model, Store} from "@bryntum/gantt";
class TradeDiscipline extends Model {
static $name = 'TradeDiscipline';
static fields = [
'id', 'description'
];
}
// Define a separate store holding additional data that we can attach to the main TaskModel, to
// demonstrate setting up relations between models and filtering on them
const tradeDisciplineStore = new Store({
modelClass : TradeDiscipline,
data:
window.clientModel.tradeDisciplines.map(x => {
return {id: x.tradeDisciplineId, description: x.description}
})
});
export default tradeDisciplineStore;
From our project-component.vue which wraps the Bryntum Project:
computed: {
projectConfig() {
return {
...this.$attrs
};
},
taskStore() {
const vm = this;
return {
modelClass: ActivityModel,
tradeDisciplineStore: tradeDisciplineStore,
listeners: {
.....
};
},
Steps to reproduce:
- When clicking the filter button on the tradeDiscipline column
- Selecting "is one of"
- Selecting a value from the dropdown
We get the following error in the console:
Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'sort')
at eval (gantt.module.js?3374:99129:1)
at Array.map (<anonymous>)
at eval (gantt.module.js?3374:99107:1)
at Array.forEach (<anonymous>)
at Filter.refreshHeaders (gantt.module.js?3374:99092:1)
at Filter.onStoreFilter (gantt.module.js?3374:99875:1)
at TaskStore.trigger (gantt.module.js?3374:6056:1)
at TaskStore.trigger (gantt.module.js?3374:127400:1)
at TaskStore.triggerFilterEvent (gantt.module.js?3374:29113:1)
at TaskStore.afterPerformFilter (gantt.module.js?3374:29105:1)
gantt.module.js?3374:99129:1
if (isColumnFiltered) {
const bullet = '• ';
filterText = `${me.L('L{filter}')}: ` + (columnFilters.length > 1 ? '<br/><br/>' : '') + columnFilters.map(columnFilter => {
var _columnFilter$value, _me$store, _me$store$modelRelati;
let value = (_columnFilter$value = columnFilter.value) !== null && _columnFilter$value !== void 0 ? _columnFilter$value : '';
const isArray = Array.isArray(value),
relation = (_me$store = me.store) === null || _me$store === void 0 ? void 0 : (_me$store$modelRelati = _me$store.modelRelations) === null || _me$store$modelRelati === void 0 ? void 0 : _me$store$modelRelati.find(({
foreignKey
}) => foreignKey === columnFilter.property);
if (columnFilter.displayValue) {
value = columnFilter.displayValue;
} else {
if (me.isMulti && relation) {
var _me$isMulti$fields;
// Look up remote display value per filterable-field config (FieldFilterPicker.js#FieldOption)
const {
relatedDisplayField
} = (_me$isMulti$fields = me.isMulti.fields) === null || _me$isMulti$fields === void 0 ? void 0 : _me$isMulti$fields[columnFilter.property];
if (relatedDisplayField) {
const getDisplayValue = foreignId => {
var _relation$foreignStor;
return (_relation$foreignStor = relation.foreignStore.getById(foreignId)) === null || _relation$foreignStor === void 0 ? void 0 : _relation$foreignStor[relatedDisplayField];
};
if (isArray) {
//relatedDisplayField is "description"
[EXCEPTION LINE] value = value[relatedDisplayField].sort((a, b) => (a !== null && a !== void 0 ? a : '').localeCompare(b !== null && b !== void 0 ? b : ''));
} else {
value = getDisplayValue(value);
}
}
} else if (column.formatValue && value) {
value = isArray ? value.map(val => column.formatValue(val)) : column.formatValue(value);
}
if (isArray) {
value = `[ ${value.join(', ')} ]`;
}
}
return (columnFilters.length > 1 ? bullet : '') + (typeof columnFilter === 'string' ? columnFilter : `${columnFilter.operator} ${value}`);
}).join('<br/><br/>');
}
However the filter dialog does appear and items can be selected to filter by, but the filter is not actually applied to the data in the grid:
(There is data in the Trade Discipline columns, behind the filter pop-up)