Yakalent
Yakalent

Reputation: 1152

Post Form empty data

for me NuxtJS application i've got multiple components thats come together in one form. Here the code:

AppButton.vue

<template>
  <button
    class="button"
    :class="btnStyle"
    :disabled="disabled"
    v-bind="$attrs"
    v-on="$listeners"><slot /></button>
</template>

<script>
export default {
  name: 'AppButton',
  props: {
    btnStyle: {
      type: String,
      default: ''
    },
    disabled: {
      type: String
    }
  }
}
</script>

AppFormInput.vue

<template>
  <div class="form-input">
    <input
      v-bind="$attrs"
      :name="name"
      :value="value"
      :type="type"
      :placeholder="placeholder"
      :max="max"
      :min="min"
      :pattern="pattern"
      :required="required"
      :disabled="disabled"
      @input="$emit('input', $event.target.value)">
  </div>
</template>

<script>
export default {
  name: 'AppFormInput',
  props: {
    controlType: {
      type: String,
      default: 'input'
    },
    name: {
      type: String
    },
    value: {
      type: String,
      default: ''
    },
    type: {
      type: String,
      default: ''
    },
    placeholder: {
      type: String,
      default: ''
    },
    max: {
      type: String
    },
    min: {
      type: String
    },
    pattern: {
      type: String
    },
    required: {
      type: String,
    },
    disabled: {
      type: String
    }
  }
}
</script>

FormGroup.vue

<template lang="html">
  <div class="form-group">
    <AppLabel :label="label"/>
    <AppFormInput :v-bind="$attrs"/>
  </div>
</template>

<script>
import AppLabel from '~/components/atoms/AppLabel'
import AppFormInput from '~/components/atoms/AppFormInput'

export default {
  components: {
    AppLabel,
    AppFormInput
  },
  props: {
    label: {
      type: String,
      default: 'Form Label'
    }
  }
}
</script>

Form.vue

<template lang="html">
  <form @submit.prevent="onSave">
    <FormGroup label="Form Input" v-model="formPosts.forminput"/>
    <FormGroup label="Form Input Disabled" disabled="disabled" v-model="formPosts.forminputdisabled"/>
    <FormGroup label="Form Input With Placeholder" placeholder="Set placeholder" v-model="formPosts.forminputplaceholder"/>
    <FormGroup label="Form Input Required" required="required" v-model="formPosts.forminputrequired"/>
    <FormGroup label="Form Email" type="email" v-model="formPosts.forminputemail"/>
    <FormGroup label="Form Date" type="date" v-model="formPosts.forminputdate"/>
    <FormGroup label="Form Number" type="number" value="1" min="1" max="5" v-model="formPosts.forminputnumber"/>
    <FormGroup label="Form Tel" type="tel" pattern="\d{3}-\d{3}-\d{4}" placeholder="XXX-XXXX-XXXX" v-model="formPosts.forminputtel"/>
    <!--Add Select normal and disabled-->
    <FormGroup label="Form Radio" type="radio" value="1" v-model="formPosts.forminputradio"/>
    <FormGroup label="Form Checkbox" type="checkbox" value="2" v-model="formPosts.forminputcheckbox"/>
    <AppButton type="submit" btn-style="btn-brand">Save</AppButton>
  </form>
</template>

<script>
import FormGroup from '~/components/molecules/FormGroup'
import AppButton from '~/components/atoms/AppButton'

export default {
  components: {
    FormGroup,
    AppButton
  },
  data() {
    return{
      formPosts: {
        forminput: '',
        forminputdisabled: '',
        forminputplaceholder: '',
        forminputrequired: '',
        forminputemail: '',
        forminputdate: '',
        forminputnumber: '',
        forminputtel: '',
        forminputradio: '',
        forminputcheckbox: '',
      }
    }
  },
  methods: {
    onSave() {
      console.log(this.formPosts);
      this.$emit('submit', this.formPosts)
    },
  }
}
</script>

At least, the index.vue

<template lang="html">
  <div class="container">
    <h1>Forms</h1>
    <Form @submit="onSubmitted"/>
  </div>

</template>

<script>
import Form from '~/components/organism/Form'

  export default {
    components: {
      Form
    },
    methods: {
      onSubmitted(data){
        console.log(data);
      }
    }
  }
</script>

when the form is submitted the fields stays empty. The required field must have a value for example but it stays empty. I think that the some components not have access through the value of the field. Does anyone have tips?

Thanx for any help

Upvotes: 0

Views: 958

Answers (1)

acdcjunior
acdcjunior

Reputation: 135762

$attrs (in v-bind="$attrs") will only bind attributes, not props (bold is mine):

vm.$attrs: Contains parent-scope attribute bindings (except for class and style) that are not recognized (and extracted) as props. When a component doesn't have any declared props, this essentially contains all parent-scope bindings (except for class and style), and can be passed down to an inner component via v-bind="$attrs" - useful when creating higher-order components.

You need to set the props yourself in FormGroup.vue.

  • In FormGroup.vue, declare the value prop so you can use in the template:

      <script>
      import AppLabel from '~/components/atoms/AppLabel'
      import AppFormInput from '~/components/atoms/AppFormInput'
    
      export default {
        components: {
          AppLabel,
          AppFormInput
        },
        props: {
          label: {
            type: String,
            default: 'Form Label'
          },
          value: {                  // added this
            type: String            // added this
          }                         // added this
        }
      }
      </script>
    
  • In FormGroup.vue, Add :value="value" @input="$emit('input', $event)" to the template.

      <template lang="html">
        <div class="form-group">
          <AppLabel :label="label"/>
          <AppFormInput :v-bind="$attrs" :value="value" @input="$emit('input', $event)" />
        </div>
      </template>
    

The code above will set <AppFormInput>'s value and will propagate (up) it's input event. Not the v-models in Form.vue should work.

Upvotes: 1

Related Questions