No More Posting New Topics!

If you have a question or an issue, please start a thread in our Github Discussions Forum.
This forum is closed for new threads/ topics.

Navigation

    Quasar Framework

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search

    QForm - Form Fields Generator

    Show & Tell
    9
    19
    9663
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • D
      dgk last edited by dgk

      just working on a new component, essentially a form generator. You pass in the object that you want to ‘model’ and a schema for the object’s fields. Just a work in progress but looking for feedback and input. It currently only does q-input but eventually any of the quasar form components could be supported (the best way to do that is still unclear).

      seems like once this supports all the form compoenents it could be added to quasar. It’s really just a way to avoid hard coding a form template especially when a subform of a form might be dependent on a form field as in my use case where choosing a “type” requires a different set of input fields for that type…And too when one is using schemas (like json schemas) for their nosql database docments, like I am with feathersjs and nedb adding a few extra keys to handle the quasar form field type and its props is no big deal and avoids a lot of hard coding of html templates.

      <script>
      
      export default {
        data () {
          return {
          }
        },
        render (element) {
          return element('div', {}, this.makeForm(element))
        },
        props: ['values', 'schema'],
        methods: {
          makeForm (element) {
            let form = []
            console.log('values', this.values)
            for (let key in this.values) {
              let field =
              element('q-field', {
                props: {
                  label: this.schema[key].label
                }
              }, [
                element(this.values[key].fieldType ? `q-${this.schema[key].fieldType}` : 'q-input', {
                  props: {
      // put function here to get props given fieldType
                    value: this.values[key]
                  },
                  on: { input: (value) => {
                    this.values[key] = value
                    this.$emit('input', { name: key, value: value })
                  }
                  }
                })
              ]
              )// end field
              form.push(field)
              // console.log('field', key, field)
            }// end form field loop
            // console.log('the form object', form)
            return form
          }
        }
      }
      </script>
      
      <style lang="stylus">
      </style>
      

      Then in the calling component

            <q-collapsible class="col-11" v-on:remove v-on:add :label="device.name">
              <q-field label="Device Name">
               <q-input  v-model="device.name"/>
              </q-field>
              <q-field label="Type">
               <q-select v-model="device.type" :options="deviceTypesOptions()" />
              </q-field>
              <q-field label="Description">
                <q-input  v-model="device.desc"/>
              </q-field>
              <q-form class="" @input="update(device,$event)" :values="device.settings" :schema="deviceTypes[device.type].settings" ></q-form>
              <q-btn color="positive" @click="saveChanges(device,index)">Save Changes</q-btn>
            </q-collapsible>
      

      schema looks like this.

      // if no fieldType it's assumed to be q-input
       {
          i2cAddress : { type: Number, required: true, unique: true, fieldType: 'input', label: 'I2C Address', help: 'enter hex address' },
         defaultConfig: { type: String, required: true, default: 'output', fieldType: 'select', valids: ['toggle','momentary','input','output','custom'], label: 'pins mode', help: 'choose a mode for all pins on chip' },
          iPinA : { type: Number, label: 'SBC Pin Number' },
          iPinB : { type: Number, label: 'SBC Pin Number' }
       }
      1 Reply Last reply Reply Quote 0
      • D
        dgk last edited by

        0_1505527545904_Screenshot at 2017-09-15 19:03:55.png

        fields I2C Address and below come from the generator and changes to them emit to the parent form which then can update it’s data accordingly.

        L 1 Reply Last reply Reply Quote 0
        • L
          leon @dgk last edited by leon

          @dgk 😀 Nice! Make it an npm dependecy.

          1 Reply Last reply Reply Quote 0
          • D
            dgk last edited by dgk

            @leon I can do that when it’s more tested plus a a little tutorial/docs on use. I can put the work in progress on github sooner though.

            In the meantime I’ve added a q-collapse-form which wraps the form component, plus I have a quasar-feathers component so one can display all how set of configurable documents from a server.

            Below is the latest, multi-schema would look. With these schemas quasar renders a three tab page with each tab allowing editing of that document/schemas fields. Shema now uses a fieldprops key so one can set the props for any quasar form component. Option-group options can be hard coded or are created at run time from other feathers services. Works slick although I am having this tab display issue. http://forum.quasar-framework.org/topic/920/formatting-generated-q-tabs-also-getting-a-explict-keys-warning/2

            const virtual = {
            
              name: { default: '', unique: true,
                fieldProps: { label: 'Name', tip: 'enter unique circuit name' }
              },
              desc: { default: '',
                fieldProps: { label: 'Description', tip: 'Describe Services' }
              },
              circuits: { default: [], fieldType: 'option-group',
                fieldProps: { label: 'Circuits', tip: 'Select circuits associated with this switch', inline: true, type: 'toggle', options: [] }
              }
            };
            
            
            
            const physicalExtras = {
            
              mode: { default: 'toggle' , fieldType: 'select',
                fieldProps: { label: 'Switch Mode', tip: 'Select Switch Mode Type',
                  options: [
                    {label: 'Toggle', value: 'toggle'},
                    {label: 'On/Off', value: 'onoff'},
                    {label: 'Momentary', value: 'momentary'},
                  ]}
              },
              virtual: { default: true , fieldType: 'checkbox',
                fieldProps: { label: 'Virtual Switch', tip: 'Create a corresponding virtual switch',
                  }
              },
              // TODO make this another doc type so users can edit this list - for now disable
              location: { default: '1' , fieldType: 'hidden',
                fieldProps: { label: 'Location in Buidling', tip: 'Select building location',
                  options: [
                    {label: 'First Floor', value: '1'},
                    {label: 'Second Floor', value: '2'},
                    {label: 'Outside', value: 'outside'}
            
                  ]}
              },
              bankid: { default: '', fieldType: 'select',
                fieldProps: { label: 'Bank/Board', tip: 'Select Bank/Board', options: [] }
              },
              port: { default: 'A', fieldType: 'select',
                fieldProps: { label: 'Port', tip: 'Select a Port',
                  options: [
                    {label: 'Port A', value: 'A'},
                    {label: 'Port B', value: 'B'}
                  ]}
              },
              pin: { default: 1,
                fieldProps: { label: 'Relay/Pin Number',min: 1, max: 8, step: 1 }
                //tip: 'Select a relay/pin number with the port '
              }
            
            };
            
            const physical = Object.assign({}, virtual);
            Object.assign(physical, physicalExtras);
            
            // views only for virtual switches
            virtual.views = { default: [],  fieldType: 'option-group',
                fieldProps: { label: 'Views', tip: 'Put this switch in checked views', type: 'toggle', options: [] }
              }
            
            const view = {
            
              name: { default: '', unique: true,
                fieldProps: { label: 'view name', tip: 'enter unique view name' }
              }
            
            };
            
            
            module.exports = { physical, virtual, view };
            
            1 Reply Last reply Reply Quote 1
            • Z
              Zyme last edited by Zyme

              I need something like this for my new project.

              Could you use JSON schema spec for this?

              Found a bunch of dead projects like this but not for Quasar components.

              Basically looking for this https://github.com/icebob/vue-form-generator/

              1 Reply Last reply Reply Quote 1
              • D
                dgk last edited by

                yes this is pretty close to JSON schema spec since it’s just json disguised as javascript. I like to write my json this way so I can use comments and easier to lint and I can also combine partical schemas programatically.

                See this https://github.com/uCOMmandIt/backend/tree/master/src/schemas

                This is all part of a working lightning system I just installed. No time now to share in a constructive way but check out the repo for now. You’ll see I set this up as a dual component. On for a form and one that uses a form in a collapsible. The schema is fetched from the backend as it’s used to build forms and also initialize a nosql document

                https://github.com/uCOMmandIt/frontend

                all check out my post here.
                http://forum.quasar-framework.org/topic/933/getting-proxied-server-data-to-play-app/4

                1 Reply Last reply Reply Quote 0
                • Cmacu
                  Cmacu last edited by

                  Any progress? I would love to use/contribute to this type of component.
                  One of the options is to form the vue-form-generator and migrate the input types to quasar components.

                  1 Reply Last reply Reply Quote 0
                  • N
                    njsteele last edited by

                    vue-form-json-schema supports any library. I’m testing it with Quasar now. It allows you to layout the UI as well so you don’t have a single ugly column for your forms too. Just all around butt-kicking. 🙂

                    If you’re already using ajv for your schemas (if not you SHOULD) and lodash (who doesn’t), you’ll be happy to know this entire form generator weighs in at under 20kb gzipped, smaller than all other form generators, and with TONS more features! (see https://bundlephobia.com/result?p=vue-form-json-schema@2.5.3)

                    github: https://github.com/jarvelov/vue-form-json-schema
                    detailed docs with demos: https://jarvelov.gitbook.io/vue-form-json-schema/

                    1 Reply Last reply Reply Quote 0
                    • N
                      njsteele last edited by

                      WOW. Just… WOW. I spent a day testing vue-form-json-schema, and not only is it FULLY Quasar compatible, you can literally use this to create ENTIRE LAYOUTS not just a single Quasar form… HOLY COW is it powerful with Quasar… 🤯

                      For anyone that would like to quickly use vue-form-json-schema with Quasar, here is some of my testing work… ☺

                      Just “npm i vue-form-json-schema” in your Quasar project, create a component and paste this code into it…

                      <template>
                      <div class="">
                         <vue-form-json-schema
                          v-model="value"
                          :schema="schema"
                          :ui-schema="uiSchema"
                          v-on:state-change="onChangeState"
                          v-on:validated="onValidated"
                          :components="components"
                        />
                      </div>
                      
                      </template>
                      
                      <script>
                      import { QInput, QCard, QExpansionItem } from 'quasar'
                      import VueFormJsonSchema from 'vue-form-json-schema/dist/vue-form-json-schema.esm.js'
                      export default {
                        props: ['value', 'schema', 'uiSchema'],
                        components: {
                          VueFormJsonSchema
                        },
                        data () {
                          return {
                            components: { // Add your sandboxed quasar or other components here (if you don't add it here, you can't use them)
                              'input': QInput,
                              'card': QCard,
                              'expansion': QExpansionItem
                            }
                          }
                        },
                        methods: {
                          onChange (value) {
                            this.$emit('change', value)
                          },
                          onChangeState (value) {
                            this.$emit('state', value)
                          },
                          onValidated (value) {
                            this.$emit('valid', value)
                          }
                        }
                      }
                      </script>
                      

                      Then from anywhere in app, add this to your template (you’ll have to add the above component to your project as well of course):

                      <form-generator v-model="yourModel" :schema="yourSchema" :uiSchema="yourUISchema"/>
                      

                      If you want some quick data that you can use to just see it working immediately, here is a q-card, with padding and spacing set, and inside it 2 input items, and they are all generated right from schema that you can put into config 🤯 …

                      yourModel: {
                              firstName: '', lastName: ''
                            },
                            yourSchema: {
                              type: 'object',
                              properties: {
                                firstName: {
                                  type: 'string'
                                },
                                lastName: {
                                  type: 'string'
                                }
                              }
                            },
                            yourUISchema: [
                              {
                                component: 'card',
                                fieldOptions: {
                                  class: ['q-ma-xl', 'q-pa-md']
                                },
                                children: [
                                  {
                                    component: 'input',
                                    model: 'firstName',
                                    fieldOptions: {
                                      on: ['input'],
                                      props: { outlined: true, label: 'First Name' }
                                    }
                                  },
                                  {
                                    component: 'input',
                                    model: 'lastName',
                                    fieldOptions: {
                                      props: { rounded: true, outlined: true, label: 'Last Name' },
                                      class: ['q-pa-xl'],
                                      on: ['input']
                                    }
                                  }
                                ]
                              }
                            ]
                      
                      G 1 Reply Last reply Reply Quote 1
                      • G
                        gh7531 @njsteele last edited by

                        @njsteele Thank you for your example! It really is awesome with quasar.
                        Do you know by any chance how/if the import of the quasar components can be skipped and ‘input’ be directly replaced with ‘q-input’?

                                  ...
                                  children: [
                                    {
                                      #component: 'input',
                                      component: 'q-input',
                                      model: 'firstName',
                                      fieldOptions: {
                                  ...
                        

                        Something simillar is done in the fourth example in the documentation but I cant get it to work with quasar in the same way.

                        1 Reply Last reply Reply Quote 0
                        • A
                          Amod last edited by Amod

                          @njsteele @gh7531 Thanks for your example. I started checking vue-form-json-schema for a project but couldn’t get it running. The default html UI elements work, but Quasar components dont.

                          My code is as, what am I missing? : Note: I get an error in the browser console - Unknown custom element: <q-input> - did you register the component correctly.

                          Failed to mount component: template or render function not defined - where is this to be added?

                          <template>
                            <q-page>
                              <DynaFormComponent :model="model" :schema="schema" :ui-schema="uiSchema" />
                            </q-page>
                          </template>
                          
                          <script>
                          import DynaFormComponent from 'vue-form-json-schema'
                          import QInput from 'quasar'
                          
                          export default {
                            name: 'vueform',
                            components: {
                              DynaFormComponent, QInput
                            },
                            data () {
                              return {
                                model: {},
                                schema: {
                                  type: 'object',
                                  properties: {
                                    firstName: {
                                      type: 'string'
                                    }
                                  }
                                },
                                uiSchema: [{
                                  component: 'q-input',
                                  model: 'firstName',
                                  fieldOptions: {
                                    class: ['form-control'],
                                    on: ['input'],
                                    props: {
                                      type: 'text',
                                      placeholder: 'Type here'
                                    }
                                  }
                                }]
                              }
                            }
                          }
                          </script>
                          

                          I have tried all possible combinations of component: ‘q-input’, component: ‘qinput’ etc. But cannot figure what I am missing.

                          Any help is appreciated !

                          Ty.

                          dobbel 1 Reply Last reply Reply Quote 0
                          • dobbel
                            dobbel @Amod last edited by

                            @Amod the error usually comes from the fact that the quasar component is not registered in the q.conf file.

                            https://quasar.dev/quasar-cli/quasar-conf-js#Property%3A-framework

                            if you’re not using Auto Import then you can do some thing like this:

                            components: ['QInput','QTable','QFoobar']
                            1 Reply Last reply Reply Quote 0
                            • A
                              Amod last edited by

                              @dobbel , Thanks for your reply.

                              I am using - importStrategy: ‘auto’, and tried removing the QInput from the component. No luck yet.

                              1 Reply Last reply Reply Quote 0
                              • A
                                Amod last edited by Amod

                                @dobbel , Thanks for the pointer. It now works. What I had to change was:

                                My import strategy was already auto, (though I can turn it off and use required components)

                                but to get this to work I had to even set
                                components: [‘QInput’] in the config file.

                                The configuration file now looks like:

                                framework: {
                                      iconSet: 'material-icons',
                                      lang: 'en-us',
                                      config: {},
                                      importStrategy: 'auto',
                                      components: ['QInput'], // added this
                                      plugins: []
                                    },
                                

                                It should have worked with importStrategy:auto in the first place. Right?

                                dobbel 1 Reply Last reply Reply Quote 0
                                • dobbel
                                  dobbel @Amod last edited by dobbel

                                  @Amod Yes I think you did everything right if you did not use the form-builder. What I think what went wrong in your case is that the form builder uses dynamic components and so not the q-input component explicitly in templates. So the ‘auto’ mode fails to see the need of importing q-input or whatever components the formbuilder creates.

                                  1 Reply Last reply Reply Quote 0
                                  • D
                                    dgk last edited by dgk

                                    My original post is quite old I have a much improved version of my form builder! as well as the app in general.

                                    9af3008d-ee90-4262-96ef-47908b3eb2df-image.png

                                    I did at one point try out vue-form-json-schema but it just didn’t fully meet my needs. One of the cool things my form builder is that it can use the values of one property in a schema instance as the option choices in another dynamically. Also I made it really easy to hide/show and have props of schema depend on the values of others. That you set in the schema. I really want to document and share this but just too preoccupied right now to do that. I have a major deployment coming up in the next week and after that I can put some attention to this if there is interest. In the meantime if you are savvy enough take a look at my repo of this project I am deploying that makes use of it. The component in question is Form.vue in the components subdirectory directory

                                    https://git.kebler.net/Light2/frontend/src/branch/master/src/components

                                    here are the schemas used. Notice they are in yaml format instead of json. This makes it WAY easier to comment stuff out and add comments. Of course they get read into a javascript object same as json.

                                    https://git.kebler.net/Light2/database/src/branch/master/schemas

                                    take a look at the config schema and page component. That is a simple single form implementation. The others are more complicated because they involved a collection of form instances.

                                    dobbel 2 Replies Last reply Reply Quote 0
                                    • dobbel
                                      dobbel @dgk last edited by

                                      @dgk Yes I would greatly appreciate if you took some time to document and share this new form builder with us!

                                      1 Reply Last reply Reply Quote 0
                                      • dobbel
                                        dobbel @dgk last edited by

                                        @dgk Hi, your form builder repo is offline 😞

                                        1 Reply Last reply Reply Quote 0
                                        • D
                                          david_bp last edited by david_bp

                                          I’ve been evaluating schema-based form generators too, as I want to move from server-generated DOM to a JSON serializaton of forms and their rules, so we can offer a better mobile experience, offline, etc. We have hundreds of fields in a form, dozens per “page”, with potentially a lot of business rules.

                                          • Vue-Form-Generator is not really maintained and doesn’t look like it quite made it to the next version. It also bakes in Bootstrap UI.

                                          • Vue Form JSON Schema looks promising, but I wish it was a little more “automatic” and less verbose. Last updated 5 months ago or so?

                                          • JSONForms (https://jsonforms.io/) I just came across. I think they recently added Vue support (was originally Angular and React). It uses Material as the UI styling. But it has some neat features like defaulting a UI Schema for you based on the data Schema. I like some of their dependent fields (if Yes, show/require this other field) stuff, and I like how using this would abstract us from Vue, in case we have to use React in some context in the future.

                                          • Vue Formulate has a newer generate-from-schema option (https://vueformulate.com/guide/forms/generating-forms/), but currently lacks much of the repeater/validators that the “statically-defined in template” method offers.

                                          • BlitzarForm (https://blitzar.cycraft.co/docs/blitz-form) is a new effort that also allows any component, so all Quasar components could be used.

                                          For something more than a pet project, I’m nervous to “place a bet” on what would be used by my company for years to come!

                                          1 Reply Last reply Reply Quote 1
                                          • First post
                                            Last post