Formio.js

Formio.js is an open source formbuilder and form renderer library.

Formio Utilities

Utilities to easily fetch components or submission data and modify them. Also loop through all components or flatten the component tree.

https://github.com/formio/formio.js/wiki/Form-Utilities

Custom Action on Formio Button

To add a custom action on a button in the formbuilder you would use their component dialog and the custom action is stringified in json. But if you write your component definition directly in Javascript, you can do it just this way:

{
  "display": "form",
  "components": [
     {
        "label": "Custom Button",
        "action": "custom",
        "key": "customButton",
        "type": "button",
        "custom": (form) => {
            console.log(form);
        },
        // Pure JSON Example
        //"custom": "FormioUtils.eachComponent(form.components, function(component) {\n  console.log(component);\n})\n\nconsole.log(data,form);",
    }
  ]
}

Validate Form Externaly (Vue)

Get all methods via this.$refs.formioForm.formio.* like this.$refs.formioForm.formio.submit()

methods: {
    validate() {
        this.$refs.formioForm.formio.checkValidity();
    }
}

Validate Form Externaly more Complex (Vue)

<!-- scope radio buttons with same name to current form. Since form is disabled this has no effect like accidental submission or so -->
<form>
    <formio
        ref="formioMainForm"
        id="formio-main-form"
        class="created-form"
        :form="form"
        :submission="submission"
        :options="options"
        v-on:submit="submitHandler"
        v-on:error="errorHandler"
        v-on:change="formioChange"
        v-on:render="formioRender"
        v-on:customEvent="formioCustomEvent"
        language="de"></formio>
</form>

<button @click="saveChecklist()" type="button">Save</button>
var app = new Vue({

    data: {

    },
    methods: {
        /**
         * contains information about the errornous elements
         * @param  {object} params
         */
        errorHandler: function(params) {
            console.log('ErrorHandler', params);
        },
        /**
         * Contains submission data - post it somewhere or whatever
         * @param  {object} params submission.data.*
         */
        submitHandler: function(params) {
            console.log('SubmitHandler', params);
        },
        saveChecklist: function () {

            // grab formio instance
            let formio = this.$refs.formioMainForm.formio;

            // trigger submit() and utilize validation check.
            formio
                .submit()
                // the following is not needed if you use the handler function 
                .then(function(params){
                    // this is the same as `submitHandler()`
                })
                .catch(function(params){
                    // this is the same as errorHandler().
                });

            if (!formio.checkValidity()) {
                //formio.submit();
                notify.danger("Fehler im Formular!");
                return;
            }

            // in my app, I just proceed here with posting data and fill the field again...
        }
    }

});

Inline SVG in Dropdown

const config = {
    // https://github.com/formio/formio.js/wiki/Form-Sanitize-Config
    sanitizeConfig: {
        allowedTags: ['svg', 'title', 'path'],
        addTags: ['svg', 'title', 'path'],
        allowedAttr: [ 'd', 'transform', 'fill', 'viewBox', 'xmlns'],
        addAttr: [ 'd', 'transform', 'fill', 'viewBox', 'xmlns'],
    }
};

const components = {
    "components": [
    {
          "label": "Select",
          "tableView": true,
          "data": {
            "values": [
              {
                "label": "SVG",
                "value": "svg"
              }
            ]
          },
          "template": "<span>\n  <svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" aria-hidden=\"true\" focusable=\"false\" width=\"1em\" height=\"1em\" style=\"-ms-transform: rotate(360deg); -webkit-transform: rotate(360deg); transform: rotate(360deg);\" preserveAspectRatio=\"xMidYMid meet\" viewBox=\"0 0 15 15\"><g fill=\"none\"><path d=\"M13.5 3.5h.5v-.207l-.146-.147l-.354.354zm-3-3l.354-.354L10.707 0H10.5v.5zm-8 6V6H2v.5h.5zm0 2H2V9h.5v-.5zm2 0H5V8h-.5v.5zm0 2v.5H5v-.5h-.5zm2-1H6v.207l.146.147L6.5 9.5zm1 1l-.354.354l.354.353l.354-.353L7.5 10.5zm1-1l.354.354L9 9.707V9.5h-.5zm2-3V6H10v.5h.5zm0 4H10v.5h.5v-.5zm2 0v.5h.5v-.5h-.5zM2 5V1.5H1V5h1zm11-1.5V5h1V3.5h-1zM2.5 1h8V0h-8v1zm7.646-.146l3 3l.708-.708l-3-3l-.708.708zM2 1.5a.5.5 0 0 1 .5-.5V0A1.5 1.5 0 0 0 1 1.5h1zM1 12v1.5h1V12H1zm1.5 3h10v-1h-10v1zM14 13.5V12h-1v1.5h1zM12.5 15a1.5 1.5 0 0 0 1.5-1.5h-1a.5.5 0 0 1-.5.5v1zM1 13.5A1.5 1.5 0 0 0 2.5 15v-1a.5.5 0 0 1-.5-.5H1zM5 6H2.5v1H5V6zm-3 .5v2h1v-2H2zM2.5 9h2V8h-2v1zM4 8.5v2h1v-2H4zm.5 1.5H2v1h2.5v-1zM6 6v3.5h1V6H6zm.146 3.854l1 1l.708-.708l-1-1l-.708.708zm1.708 1l1-1l-.708-.708l-1 1l.708.708zM9 9.5V6H8v3.5h1zM13 6h-2.5v1H13V6zm-3 .5v4h1v-4h-1zm.5 4.5h2v-1h-2v1zm2.5-.5v-2h-1v2h1z\" fill=\"#626262\"/></g></svg>\n  \n</span>",
          "selectThreshold": 0.3,
          "key": "select",
          "type": "select",
          "input": true,
          "defaultValue": "svg"
        }
    ]
};

Formio.createForm(document.getElementById('formio'), components, config);