kazupon / vue-validator

:white_check_mark: Validator component for Vue.js
MIT License
2.19k stars 431 forks source link

How can we use the vue-validator with child components? #186

Open ksdev-pl opened 8 years ago

ksdev-pl commented 8 years ago

Hi

Related to #131, #96, #154, #160:

How can we use the vue-validator with child components?

Example:

AjaxForm.vue template:

<ajax-form>
    <validator name="validator">
        <form>
            <text-input :model.sync="user.name"></text-input>
            <select-input></select-input>
            <button :disabled="!$validator.valid">Save</button>
        </form>
    </validator>
</ajax-form>

TextInput.vue:

<template>
    <div class="form-group">
        <label for="name" class="col-sm-2 control-label">Name</label>
        <div class="col-sm-10">
            <input type="text"
                   class="form-control"
                   id="name"
                   v-model="model"
                   v-validate:name="['required']">
        </div>
    </div>
</template>

<script>
    module.exports = {
        props: {
            model: String
        }
    }
</script>

As you can see, the button should be disabled when validation is invalid. How do we pass and use the $validator in <text-input> component so that the validation inside the component is visible also in the parent <ajax-form> component?

Thanks for your work.

kazupon commented 8 years ago

Sorry, In currently version, vue-validator can't use the validator was defined at parent vm instance. Maybe, I'll try to plan at next major version releasing.

jorisnoo commented 8 years ago

this would be a great feature!

cgarnier commented 8 years ago

Hey, I have the same issue for validating custom input components. But i think it s better to put the v-validate on the component then inside its template. That way, we should be able to customize the validation rules as we wish.

cgarnier commented 8 years ago

Possible workarround:

grecaptcha(:response.sync="response")
input(type="hidden" v-model="response", v-validate:captcha="['required']")
.error(v-if!="$validation.captcha.required && $validation.captcha.dirty", v-html="'required'")
xjchengo commented 8 years ago

I did a try to support child components validation at feature-support-child-components.

kazupon commented 8 years ago

@xjchengo That's look good. 👍 If you will try to challenge this feature, I'm waiting for your PR. 😺

xjchengo commented 8 years ago

@kazupon Okay, I will have a try to finish the feature.

oliverzy commented 8 years ago

@cgarnier the workaround does work, but not perfect. The touched, prisitine status cannot be synced with hidden input

perkola commented 8 years ago

@xjchengo any status on the child component support? I would be happy to try to contribute if you need it.

vvenv commented 8 years ago

@perkola see this PR: https://github.com/xjchengo/vue-validator/pull/1 works fine for me, but i have NOT enough time to add some tests

xjchengo commented 8 years ago

@crossjs Hi, I have read your PR. Why need to use current component's vm as fallback?

xjchengo commented 8 years ago

@perkola I will send a PR soon and post my questions. Any advise is welcome.

vvenv commented 8 years ago

@xjchengo

Why need to use current component's vm as fallback?

ensuring _evalModel get the model defined in child https://github.com/crossjs/vue-validator/blob/feature-support-child-components/src/validations/base.js#L260

for example:

// app.vue
<template>
  <validator name="...">
    <form>
      <text :value="value" ...></text>
    </form>
  </validator>
</template>
<script>
export default {
  data () {
    return {
      value: 'xyz'
    }
  }
}
</script>

// text.vue
<template>
  <input
      :field="field"
      v-model="value"
      v-validate="validate">
</template>
<script>
export default {
  props: {
    field: {
      type: String,
      default: ''
    },
    value: {
    },
    validate: {
    }
}
</script>

without fallback to child vm, validator will try to get the model value in the root, and the REAL model value could NOT be reached.

at last, here is my practice: https://github.com/crossjs/plat/blob/master/src/components/c-form.vue

xjchengo commented 8 years ago

@crossjs Thanks.

xjchengo commented 8 years ago

@kazupon Currently validator and v-validate are hard coupled. How about using events to communicate between them? Following is my thought:

In this way, validator and v-validate are decouple and can use separately.

kazupon commented 8 years ago

It look good to me. 😺

incraigulous commented 8 years ago

+1 on this. I use field components as well. I built my own validator that works across child components, but I'm looking forward to being able to switch to vue-validator as soon as this is merged in.

Are we just waiting on tests? I could help write some if someone could provide me with some direction on where I could be most useful.

@kazupon The big problem with using events is that Evan is dropping $broadcast and $dispatch support in Vue 2.0. We'll be limited to using $emit after 2.0.

vvenv commented 8 years ago

Here is my simplex implementation, take a look at it? https://github.com/crossjs/plato/blob/mobile/src/plugins/validator/index.js

incraigulous commented 8 years ago

Hey @crossjs! What am I looking at here?

@xjchengo, anything I can do to help get you closer to a pull request?

kazupon commented 8 years ago

@incraigulous I'll plan to develop vue-validator v3.0 with full-scratch while maintaining as much as possible the compatibility, because the rendering architecture (virtual dom) of vue 2.0 is different from vue 1.x. However, In vue 1.x, I think that support for child-component.

incraigulous commented 8 years ago

Hey @kazupon, are you thinking that you will will end up merging child component support in using $dispatch for communication then?

kazupon commented 8 years ago

@incraigulous No, I don't merge $dispatch commuication. In v3.0, I have a idea that will plan to validator element by using the component of vue.js

kazupon commented 8 years ago

I'll try to implement at v3.0.

joeyzone commented 8 years ago

I am waiting in hope for v3.0.

Pixelime commented 8 years ago

Hey guys, I am not sure if this is related but I got this error when I try to call the this.$validate method from a parent component (and the validator is defined in the children one) Uncaught TypeError: this.$validate is not a function Any idea?

thanks

JsonSong89 commented 8 years ago

i find a very strange way: in my custom rule, i can access the "current vm"(maybe is a component). like this:this.el.__vue__.propName , then return the value we want to check.

luxueyan commented 8 years ago

mark