Я использую библиотеку javascript formio для создания своих форм, и мне просто нужен раскрывающийся список, чтобы получить его текущее значение и предыдущее значение при событии изменения.
Проблема здесь в том, что раскрывающийся список может находиться в сетке данных, и при добавлении строки добавляются дополнительные раскрывающиеся списки. Как в этой простой конфигурации формы:
{ display : 'form'
, components:
[ { label : 'Data Grid'
, reorder : false
, addAnotherPosition : 'bottom'
, layoutFixed : false
, enableRowGroups : false
, initEmpty : false
, tableView : false
, defaultValue : [ { } ]
, key : 'dataGrid'
, type : 'datagrid'
, input : true
, components:
[ { label : 'Test drop down'
, widget : 'choicesjs'
, tableView : true
, data:
{ values:
[ { label: 'Test 1', value: 'test1' }
, { label: 'Test 2', value: 'test2' }
, { label: 'Test 3', value: 'test3' }
]
}
, key : 'testDropDown'
, type : 'select'
, input : true
} ] } ] }
Исходя из ваших требований, я примерно добавил несколько слушателей и кнопок для имитации процесса добавления параметров формы.
change
, где значение получается через index. (form-renderer#log-change-events)triggerRedraw
для принудительного повторного рендеринга для обновления формы. (Component-Settings#redraw-on )демо:
<!DOCTYPE html>
<html>
<head>
<title>Form.io Dropdown Tracking</title>
<script src = "https://cdn.form.io/formiojs/formio.full.min.js"></script>
</head>
<body>
<div id = "formio"></div>
<script>
const formDefinition = {
display: "form",
components: [
{
label: "Data Grid",
reorder: false,
addAnotherPosition: "bottom",
layoutFixed: false,
enableRowGroups: false,
initEmpty: false,
tableView: false,
defaultValue: [{}],
key: "dataGrid",
type: "datagrid",
input: true,
components: [
{
label: "Test drop down",
widget: "choicesjs",
tableView: true,
data: {
values: [
{ label: "Test 1", value: "test1" },
{ label: "Test 2", value: "test2" },
{ label: "Test 3", value: "test3" },
],
},
key: "testDropDown",
type: "select",
input: true,
},
],
},
],
};
const previousValues = {};
Formio.createForm(document.getElementById("formio"), formDefinition).then(
(form) => {
function addValuesToDropdown(newValues) {
const dataGrid = form.getComponent("dataGrid");
dataGrid.components.forEach((row) => {
const dropdown = row.getComponent("testDropDown");
dropdown.component.data.values.push(...newValues);
dropdown.triggerRedraw();
});
}
const newDropdownValues = [
{ label: "Test 4", value: "test4" },
{ label: "Test 5", value: "test5" },
];
addValuesToDropdown(newDropdownValues);
form.on("change", (event) => {
if (
event.changed &&
event.changed.component &&
event.changed.component.key === "testDropDown"
) {
const dataGridIndex = event.instance.component.id;
const currentValue = event.changed.value;
const previousValue = previousValues[dataGridIndex] || null;
console.info(
`Previous value: ${previousValue}, Current value: ${currentValue}`
);
previousValues[dataGridIndex] = currentValue;
}
});
}
);
</script>
<style>
.choices__list.choices__list--dropdown{
position: static !important;
}
</style>
</body>
</html>
Чтобы обрабатывать выборку текущих и прошлых значений раскрывающегося списка в элементе DataGrid с помощью formio, вам необходимо использовать прослушиватели событий для мониторинга изменения значений.
Для достижения этой цели :
const formConfig = {
display: 'form',
components: [{
label: 'Data Grid',
reorder: false,
addAnotherPosition: 'bottom',
layoutFixed: false,
enableRowGroups: false,
initEmpty: false,
tableView: false,
defaultValue: [{}],
key: 'dataGrid',
type: 'datagrid',
input: true,
components: [{
label: 'Test drop down',
widget: 'choicesjs',
tableView: true,
data: {
values: [{
label: 'Test 1',
value: 'test1'
},
{
label: 'Test 2',
value: 'test2'
},
{
label: 'Test 3',
value: 'test3'
},
],
},
key: 'testDropDown',
type: 'select',
input: true,
}, ],
}, ],
};
Formio.createForm(document.getElementById('formio'), formConfig).then(
(form) => {
attachEventListeners(form);
}
);
function attachEventListeners(form) {
// Store previous and current values for each component
const componentStates = new Map();
// Function to handle the change event for dropdowns
const handleChangeEvent = (component, rowIndex) => {
const path = `${component.path}[${rowIndex}]`;
let state = componentStates.get(path);
if (!state) {
state = {
previousValue: null,
currentValue: ''
};
componentStates.set(path, state);
}
component.on('change', () => {
state.previousValue = state.currentValue;
state.currentValue = component.getValue();
// if (rowIndex)
console.info(
`For::${path} Previous Value: ${state.previousValue} , Current Value: ${state.currentValue}`
);
});
};
// Attach event listeners to existing dropdowns
form.everyComponent((component) => {
if (component.component.key === 'testDropDown') {
handleChangeEvent(component, 0);
}
});
// Attach event listeners to new rows in the DataGrid
form.on('change', (event) => {
if (
event.changed &&
event.changed.component &&
event.changed.component.key === 'dataGrid'
) {
console.info('fired');
const dataGridComponent = event.changed.instance;
dataGridComponent.rows.forEach((row, rowIndex) => {
if (row.testDropDown.component.key === 'testDropDown') {
handleChangeEvent(row.testDropDown, rowIndex);
}
});
}
});
}
<script src = "https://cdn.form.io/formiojs/formio.full.min.js"></script>
<div id = "formio"></div>