8000 form.setForm disrupts editgrid component functionality · Issue #1797 · formio/formio · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

form.setForm disrupts editgrid component functionality #1797

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
jdancey-allview opened this issue Sep 10, 2024 · 1 comment
Open

form.setForm disrupts editgrid component functionality #1797

jdancey-allview opened this issue Sep 10, 2024 · 1 comment

Comments

@jdancey-allview
Copy link

Background

I have been working with dynamically rendering Tabs in Formio which has thrown up a lot of issues. Eventually I landed on a solution of amending the schema directly and using setForm.

This has worked smoothly however when adding in an 'editgrid' component. When the form.setForm() functionality is called it breaks the functionality of the Edit Grid component. None of the HTML gets injected into the Edit Grid component and the components are not rendered.

image

As you can see, it is still possible to add the new components however the HTML / JS templating that is in the templates appears to be broken and does not render the actual component. I have isolated this behaviour to specifically only break on form.setForm(newFormSchema) being called.

Code

Below is a stripped down version of my code that highlights the relevant parts. I have included the JSON for my Edit Grid Component. Some of the Templating has been deleted to avoid confusion.

import { cloneDeep } from 'lodash';

const editGrid = {
  "label": "some_sample_label",
  "labelPosition": "left-left",
  "labelWidth": 30,
  "openWhenEmpty": false,
  "tableView": false,
  "rowDrafts": false,
  "key": "some_sample_key",
  "type": "editgrid",
  "displayAsTable": false,
  "input": true,
  "templates": {
    "header": "<div class=\"row\">\n      {% util.eachComponent(components, function(component) { %}\n        {% if (displayValue(component)) { %}\n          <div class=\"col-sm-5\">{{ t(component.label) }}</div>\n        {% } %}\n      {% }) %}\n    </div>",
    "row": "<div class=\"row\">\n      {% util.eachComponent(components, function(component) { %}\n        {% if (displayValue(component)) { %}\n          <div class=\"col-sm-5\">\n            {{ isVisibleInRow(component) ? getView(component, row[component.key]) : ''}}\n          </div>\n    </div>"
  },
  "components": [
    {
      "label": "Code",
      "labelPosition": "left-left",
      "labelWidth": 30,
      "widget": "choicesjs",
      "tableView": true,
      "dataSrc": "url",
      "data": {
        "url": "somedataurl"
      },
      "dataType": "object",
      "validate": {
        "required": true
      },
      "key": "code",
      "template": "<span>{{ item.value }} - {{ item.label }}</span>",
      "type": "select",
      "input": true,
      "lazyLoad": false,
      "disableLimit": false
    },
    {
      "label": "Quantity",
      "labelPosition": "left-left",
      "labelWidth": 30,
      "mask": false,
      "tableView": true,
      "defaultValue": "1",
      "truncateMultipleSpaces": false,
      "validate": {
        "required": true
      },
      "key": "quantity",
      "calculateValue": "if (value) { value = value.replace(/[^0-9]/g, ''); }",
      "type": "textfield",
      "input": true
    }
  ]
}

// this is the callback function of the form.createForm()
const doCustomFormLogic = (form) => {
  //simplified version of what is happening
  form.on('initialized', () => handleInitialize(form));
};

// in this situation we are trying to dynamically add multiple tabs to a tabs component.
//I have tried many different ways and this is the only one that I could get working that also managed data and validation properly
const handleInitialize = (form) => {
//custom component to insert into our tabs component
  const customComponent = { someComponentJSON: 'substituting this for actual component' };
// avoid directly mutating our original schema
  const newFormSchema = cloneDeep(form.schema);
  // append the new JSON into the form schema
  newFormSchema.components[4].components[2].push(customComponent);
// setForm, this attaches listeners, enable validation etc.  This is the part that overwrite the editgrid component
  form.setForm(newFormSchema);
  //redraw the form to finalise everything
  form.redraw();
}

Avenues that I have explored

  • I am open to other ways of managing the Dynamic Tabs however I have tried many options so am not hopeful that there are many avenues
  • It doesn't seem possible to selectively setForm() and exclude certain components
  • I have attempted to extract the edit grid component and reinsert it following the rebuild
  • I have attempted to manually trigger the Edit Grid build process, editGrid.build(); editgrid.render(); editgrid.attach(); editgrid.redraw(); however this throws up the error involving querySelectorAll and loadRefs() so I don't know what is happening there.
  • I have tried to exclude different stages of the setForm() cycle eg. {noRebuild:true}

Thoughts

As far as I can guess, calling form.setForm() sets the form schema but in such a way that the Edit Grid templating is not called, so whatever part of the render cycle triggers the Edit Grid templating insertion does not get triggered.

Thanks in advance for the help!

@lane-formio
Copy link
Contributor

Could you possibly provide a jsfiddle or other code sandbox to illustrate the issue?
Also what version are you using?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants
0