Gregor Voinov
Gregor Voinov

Reputation: 2263

vuejs2 slots how to communicate with parent

I want to create a formRow component that have a slot for the input field and vee-validate for validation

this is my markup

//form
<vFormRow validate="required" v-slot="{ onInput, errors }">
  <vTextfield @input="onInput" :errors="errors"/>
</vFormRow>

I tried to emit the value to the parent and get the value with @input="onInput" on the slot, but this doesn't work

//formrow
<template>
  <div class="mb-4">
    <v-validation-provider
      v-slot="{ errors }"
      :rules="validate"
    >
      <label>{{ label }}</label>
      <slot 
        :onInput="onInput"
        :errors="errors"
      />
      <vFormError
        :message="errors[0]"
      />
    </v-validation-provider>
  </div>
</template>

<script>
import { ValidationProvider as vValidationProvider } from 'vee-validate'
import vRadioButton from '@primitives/textfield'
import vFormError from '@primitives/formError'
export default {
  components: {
    vTextfield,
    vFormError,
    vValidationProvider
  },
  props: {
    value: {
      type: String,
      default: '',
    },
    validate: {
      type: String,
      required: true,
    }
  },
  methods: {
    onInput(value) {
      console.log(value)
    }
  }
}
</script>
//textfield

<template>
  <div>
    <input :value="value" @input="onInput"/>
  </div>
</template>
<script>
export default {
  props: {
    value: {
      type: String,
      default: '',
    },
    errors: {
      type: Array,
      default: () => {}
    }
  },
  data: {
    return {
      // local_value: ''
    }
  }
  methods: {
    onInput(e) {
      // this.local_value = e.target.value
      this.$emit('input', e.target.value)
    }
  }
}
</script>

What I'm doing wrong?

Upvotes: 0

Views: 151

Answers (1)

tony19
tony19

Reputation: 138696

You're not actually passing the slot props to <vTextfield>. I think you might be assuming that data bindings and event handlers on the <slot> are automatically applied to the slot's children, but that's not true.

To use the value slot prop, destructure it from v-slot, and bind it to the <vTextfield> child:

<vFormRow validate="required" v-slot="{ value }">
  <vTextfield :value="value" />
</vFormRow>

You could also pass the onInput method as a slot prop:

// vFormRow.vue
<slot :onInput="onInput" />

Then bind the event handler to <vTextfield>:

<vFormRow validate="required" v-slot="{ onInput }">
  <vTextfield @input="onInput" />
</vFormRow>

Upvotes: 1

Related Questions