formly-js / vue-formly

JavaScript powered forms for Vue.js
MIT License
237 stars 33 forks source link

Dynamic Rows #21

Open blalan opened 6 years ago

blalan commented 6 years ago

Tried to add a button that pushes changes to fields, got this error: [Vue warn]: Unknown custom element: - did you register the component correctly? For recursive components, make sure to provide the "name" option.

Is adding fields an option? Or am I doing it wrong?

matt-sanders commented 6 years ago

Hmm, it sounds like you were maybe adding a field without a type. Can you post your source ( or at least the relevant parts ) so that I can take a look at it?

blalan commented 6 years ago
<template>
  <form @submit.prevent="onSubmit">
    <formly-form :form="form" :model="model" :fields="fields"></formly-form>
    <button type="button" v-on:click="addDep">Add Row</button>
    <button type="submit">Next Step</button>
  </form>
</template>
<script>
  // import Vue from 'vue'
  export default {
    name: 'missionary2',
    data () {
      return {
        form: {},
        model: [{
          dependants: '',
          name: '',
          birthday: '',
          spouse: ''
        }],
        fields: [
          {
            key: 'dependants',
            type: 'list',
            options: ['True', 'False'],
            templateOptions: {
              inputType: 'radio',
              label: 'Do you have Dependants?'
            },
            required: true
          }, {
            key: 'name',
            type: 'input',
            templateOptions: {
              inputType: 'text',
              label: 'Name',
              atts: {
                name: 'name',
                placeholder: 'Name'
              }
            },
            display: 'model.dependants == "True"'
          }, {
            key: 'birthday',
            type: 'datepicker',
            templateOptions: {
              inputType: 'datepicker',
              label: 'Birthday',
              atts: {
                name: 'birthday'
              }
            },
            display: 'model.dependants == "True"'
          }
        ]
      }
    },
    methods: {
      addDep: function (model, fields) {
        var newRow = [
          {
            key: 'name1',
            type: 'input',
            templateOptions: {
              inputType: 'text',
              label: 'Name',
              atts: {
                name: 'name',
                placeholder: 'Name'
              }
            },
            display: 'model.dependants == "True"'
          }, {
            key: 'birthday1',
            type: 'datepicker',
            templateOptions: {
              inputType: 'datepicker',
              label: 'Birthday',
              atts: {
                name: 'birthday'
              }
            },
            display: 'model.dependants == "True"'
          }]
        this.fields.push(newRow)
      }
    }
  }
</script>
<style>
  .vdp-datepicker {
    display: inline-block;
  }
</style>
blalan commented 6 years ago

Also then, how is the model updated for the dynamic inputs?

model: {
name: ['','']
}

?

matt-sanders commented 6 years ago

Ah, I see. Well, firstly the error is this line this.fields.push(newRow). What you're doing is pushing that whole array as a new entry into the array. What you should be doing is pushing everything inside that array either with a this.fields.concat(newRow) or this.fields.push(...newRow) depending on your preference. The above is actually resulting in the following:

[
   { key: 'dependants', ...},
   { key: 'name', ...},
   { key: 'birthday', ...},
   [ 
      { key: 'name1', ...},
      { key: 'birthday1', ...}
   ]
]

I haven't tried setting up the dependants as an array so you will have to play around with that to see if you can get it to work. Maybe something like:

model: {
   names: []
},
fields: [
    { key: 'name[0]' }
]

Note that I haven't tested that so it may not work. Alternatively you could do something like:

deps: 1,
model: {
   name1: ''
}

and then in your addDep method do something like:

this.deps++;
this.model[`name${this.deps}`] = '';
this.fields.push( { key: `name${this.deps}`, ... } )

OR you could make your dependants an actual field type. This would require you to add your own field type to Vue Formly but then you could do something like:

model: {
   dependancies: []
},
fields: [
   {
      key: 'dependancies',
      type: 'dependants'
   }
]

and you could handle the adding/removing of dependants in that dependants field. See here for how to create your own fields.

blalan commented 6 years ago

Thanks you. I was thinking that most of this might be the case, so glad that I'm starting to get it. Just wanted to check to see if you had more of this worked out than what is in the documentation. Could this be added. At least that Dynamic updates are available? Maybe using this or something similar as an example?

Thanks again.

matt-sanders commented 6 years ago

Yup, sure, I'll put it on the list of things to do :) I'll leave this open for now so that I don't forget.

killua99 commented 6 years ago

EDIT: I'm terrible sorry, I miss the vue-formly-bootstrap now everything works normally

I'm having the same problem but rather to be advance like blalan, is quite simple still I got the same error.

Unknown custom element: <formly_input> - did you register the component correctly? For recursive components, make sure to provide the "name" option.
<template id="actions-bar">
  <div class="actions-bar">
    <button class="btn btn-blue" @click="showAddForm = true"><icon name="plus" class="btn__icon"></icon>{{ $t('add-client') }}</button>
    <modal v-if="showAddForm" @close="showAddForm = false">
      <h3 slot="header">{{ $t('add-client') }}</h3>
      <div slot="body">
        <form @submit="handleSubmission">
          <formly-form :form="form" :model="model" :fields="fields"></formly-form>
          <button>Submit</button>
       </form>
      </div>
    </modal>
  </div>
</template>

<script>
  import 'vue-awesome/icons/plus'
  import Modal from './../Modal'

  export default {
    components: {
      Modal
    },
    data () {
      return {
        showAddForm: false,
        model: {
          salutation: '',
          name: [],
          idno: '',
          address: '',
          postcode: '',
          land: '',
          country: '',
          telephone: '',
          email: ''
        },
        form: {},
        fields: [
          {
            key: 'salutation',
            type: 'input'
          },
          {
            key: 'name[0]',
            type: 'input',
            required: true,
            templateOptions: {
              label: this.$tc('clients.form.name')
            }
          },
          {
            key: 'idno',
            type: 'input',
            required: true
          },
          {
            key: 'address',
            type: 'input',
            required: true
          },
          {
            key: 'postcode',
            type: 'input',
            required: true
          },
          {
            key: 'land',
            type: 'input',
            required: true
          },
          {
            key: 'country',
            type: 'input',
            required: true
          },
          {
            key: 'telephone',
            type: 'input',
            required: true
          },
          {
            key: 'email',
            type: 'input',
            required: true
          }
        ]
      }
    },
    methods: {
      handleSubmission () {
        return true
      }
    }
  }
</script>

<style lang="scss">

</style>
matt-sanders commented 6 years ago

no worries, glad it's working :)