javascriptformioform.io

Formio.js get value of select component before and after change


I use formio javascript library to create my forms and I simply need for a dropdown to get its current value and its previous value on change event.
The challenge here is that the dropdown can be in a datagrid and more dropdowns are added when adding row. Like with this simple form configuration:

{ 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
} ] } ] } 

Solution

  • To handle fetching the present and past values of a dropdown in a DataGrid element with the formio, you need to use event listeners for monitoring value change.

    To achieve this :

    1. Attach the custom event listeners once the form is ready
    2. Monitor previous and current values by storing in key-value pairs
    3. As dropdowns are added dynamically in the DataGrid, you need to attach event listeners to every new dropdown that gets included

    STACKBLITZ LINK

    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 handleChange = (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.log(
              `For::${path} Previous Value: ${state.previousValue} , Current Value: ${state.currentValue}`
            );
          });
        };
    
        // Attach event listeners to existing dropdowns
        form.everyComponent((component) => {
          if (component.component.key === 'testDropDown') {
            handleChange(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.log('fired');
            const dataGridComponent = event.changed.instance;
            dataGridComponent.rows.forEach((row, rowIndex) => {
              if (row.testDropDown.component.key === 'testDropDown') {
                handleChange(row.testDropDown, rowIndex);
              }
            });
          }
        });
      }
    <script src="https://cdn.form.io/formiojs/formio.full.min.js"></script>
    
    
    <div id="formio"></div>