Dynamically Generate 8.3 Forms

Hey all,

I’m experimenting with the new Form component in Ignition 8.3 and I’m wondering how dynamic it can be.

I’ve got a table in SQL that stores field metadata for custom forms. Each record has things like the field name, label, whether it’s required, and a data type (string, numeric, boolean, etc.).

Ideally, I’d like to pull that information at runtime and build the form dynamically by generating the JSON structure for props.columns (or whatever property the Form it expects..I may not be doing this correct).

From what I can tell, the hierarchy looks like this:

columns → items → rows → items → widgets

and each widget can be a "type": "text", "number", "checkbox", etc.

So in theory, I could return something like:

[
    {
        "align": "stretch",
        "justify": "start",
        "items": [
            {
                "visible": True,
                "rows": [
                    {
                        "align": "start",
                        "justify": "start",
                        "items": [
                            {
                                "visible": True,
                                "align": "start",
                                "enabled": True,
                                "justify": "start",
                                "items": [
                                    {
                                        "visible": True,
                                        "align": "start",
                                        "widgets": [
                                            {
                                                "visible": True,
                                                "defaultValue": "",
                                                "label": "test",
                                                "type": "text",
                                                "input": {
                                                    "suffix": "",
                                                    "placeholder": "test"
                                                },
                                                "style": {"marginBottom": "8px"},
                                                "id": "test",
                                                "validation": {
                                                    "constraints": {
                                                        "required": {"enabled": True}
                                                    }
                                                }
                                            }
                                        ]
                                    }
                                ]
                            },
                            {
                                "visible": True,
                                "align": "start",
                                "enabled": True,
                                "justify": "start",
                                "items": [
                                    {
                                        "visible": True,
                                        "align": "start",
                                        "widgets": [
                                            {
                                                "visible": True,
                                                "defaultValue": "",
                                                "label": "new one",
                                                "type": "number",
                                                "input": {
                                                    "suffix": "seconds",
                                                    "placeholder": ""
                                                },
                                                "style": {"marginBottom": "8px"},
                                                "id": "new one",
                                                "validation": {
                                                    "constraints": {
                                                        "required": {"enabled": True}
                                                    }
                                                }
                                            }
                                        ]
                                    }
                                ]
                            }
                        ]
                    }
                ]
            }
        ]
    }
]

Then assign that list to:

self.getChild("Form").props.columns = myJson

But when I try this, nothing renders yet…

Has anyone successfully generated a form dynamically like this in 8.3? If so, what’s the correct structure or method to inject widgets into the Form component programmatically?

Any insight or examples would be awesome. Thanks!

As long as you return appropriately formatted JSON to the component, it will work; there's no difference between the JSON emitted by a binding or the JSON created by clicking around in the designer.

That said:

That's Python, not JSON. Might be part of your issue?

1 Like

You will need to replace all True/False with lowercase true/false for json

1 Like

Thanks @paul-griffith and @Gaurav.Shitole !

The true/false values were part of the issue, but I also wanted to bind directly to props.columns, and that turned out to be pretty picky about the exact structure required.

For anyone else trying to do the same, here’s a working sample JSON that binds cleanly to a Form component in Ignition 8.3:

{
  "align": "stretch",
  "justify": "start",
  "items": [
    {
      "visible": true,
      "rows": {
        "align": "start",
        "justify": "start",
        "items": [
          {
            "align": "start",
            "justify": "start",
            "visible": true,
            "enabled": true,
            "widgets": [
              {
                "id": "header",
                "type": "none",
                "visible": true,
                "enabled": true,
                "label": {
                  "text": "Example Header"
                },
                "info": {
                  "text": "This is a form section header."
                },
                "style": {
                  "fontSize": "20px",
                  "fontWeight": "bold",
                  "marginBottom": "10px"
                }
              }
            ]
          },
          {
            "align": "start",
            "justify": "start",
            "visible": true,
            "enabled": true,
            "widgets": [
              {
                "id": "firstName",
                "type": "text",
                "text": {
                  "placeholder": "Type your name here...",
                  "validation": {
                    "constraints": {
                      "required": {
                        "enabled": true
                      }
                    }
                  }
                },
                "visible": true,
                "enabled": true,
                "label": {
                  "text": "First Name"
                },
                "info": {
                  "text": "Enter your first name."
                },
                "style": {
                  "marginBottom": "8px"
                }
              }
            ]
          }
        ]
      }
    }
  ]
}

This structure works perfectly when bound directly to the Form component’s props.columns

Just copy and paste it on columns in the designer to see how it should work.

2 Likes