davestewart / vee-element

Replaces Element UI's validation engine with Vee Validate
http://vee-element.netlify.com
MIT License
73 stars 8 forks source link

TypeError: this.getDriver is not a function #10

Closed leonardotessaroalves closed 6 years ago

leonardotessaroalves commented 6 years ago

import ElementUi from 'element-ui' import VeeValidate from 'vee-validate' import VeeElement from 'vee-element'

const rules = { // add custom rules }

const options = { // add custom options }

const validator = new VeeValidate.Validator(rules, options)

// PLUGINS Vue.use(ElementUi) Vue.use(VeeElement, validator, true)

davestewart commented 6 years ago

Can you post your current vee validate and element ui versions?

leonardotessaroalves commented 6 years ago

@davestewart -fixed - Duplicated #8 can you show how validate with vee-validate?

this.validator.validateAll({
        email: this.email,
        name: this.name
      }).then((result) => {
        if (result) {
          // eslint-disable-next-line
          console.log('All is well');
          return;
        }
        // eslint-disable-next-line
        console.log('Oops!');
      });
davestewart commented 6 years ago

Sorry to take so long to get back to you.

Actually, you need to validating the Element UI form component, NOT the vee validate instance.

I'm sorry, I didn't make this clear in the docs as I assumed it was clear from Element UI's own documentation:

I'll look to update this in the next release, which will be in the next couple of days.

oller commented 5 years ago

Hi there,

I'm encountering the same issue.

TypeError: this.getDriver is not a function

Stack trace

TypeError: this.getDriver is not a function
    at VueComponent.options.computed.isRequired (vee-element.esm.js?d803:130)
    at Watcher.get (vue.runtime.esm.js?2b0e:3138)
    at Watcher.evaluate (vue.runtime.esm.js?2b0e:3245)
    at Proxy.computedGetter (vue.runtime.esm.js?2b0e:3503)
    at Proxy.render (element-ui.common.js?5c96:20338)
    at VueComponent.Vue._render (vue.runtime.esm.js?2b0e:4540)
    at VueComponent.updateComponent (vue.runtime.esm.js?2b0e:2784)
    at Watcher.get (vue.runtime.esm.js?2b0e:3138)
    at new Watcher (vue.runtime.esm.js?2b0e:3127)
    at mountComponent (vue.runtime.esm.js?2b0e:2791)

From the stack trace I can see the following, it seems getDriver() is undefined because the context of this is wrong?

image

I've tried various combinations of versions of vee-element and vee-validate, i've even knocked up a code sandbox to try and check if i was going mad. (this uses the latest version of both and works)

https://codesandbox.io/s/wyz98n37o7

So it must be something with my environment or implementation, as i'm lifting that working code directly from the sandbox and still getting this error.

My plugins file:

import Vue from 'vue'
import VeeValidate from 'vee-validate'
import Vuetrend from 'vuetrend'
import ElementUI from 'element-ui'
import locale from 'element-ui/lib/locale/lang/en'
import VeeElement from 'vee-element'
import Vue2Filters from 'vue2-filters'

// Create instance of VeeValidate to pass into VeeElement
const validator = new VeeValidate.Validator({}, {})

const registerPlugins = () => {
  Vue.use(Vuetrend)
  Vue.use(ElementUI, {
    locale
  })
  Vue.use(VeeElement, validator)
  Vue.use(Vue2Filters)
}

export default registerPlugins

Is called in main.js and works for all other plugins.

The app was scaffolded with vue-cli-3, i'm fairly new to the vue eco system, so apologies if it's something silly, but any help appreciated!

davestewart commented 5 years ago

Hey David,

Yes, that is a bit strange!

Let me download the repo and check. As you say, it works fine on code sandbox.

davestewart commented 5 years ago

Also, can you add a breakpoint at line 134 and check what's in the options.methods object?

Essentially, that code is monkey-patching the Element UI definitions:

https://github.com/davestewart/vee-element/blob/master/src/main.js#L33

oller commented 5 years ago

Hey @davestewart , thanks for the prompt response.

Sure here's the dump:

image

This error is invoked per <el-form-item>

I also tried explicitly stating the driver directive in the <el-form> with all possible values, but no change, I wonder how my implementation has changed

If you need anything else, let me know.

How did you finally resolve this @leonardotessaroalves? It's a little unclear what the particular problem was.

Thanks again!

davestewart commented 5 years ago

So in your first breakpoint, where the error is, do you see any of those methods?

The context for computed.isRequired should be the component itself - which you can see it is, as it says VueComponent at the top – so you should be able to scroll down the list of members and see the 4 methods in the plugin.

All but getDriver overwrite original methods; getDriver is new.

davestewart commented 5 years ago

Just the downloaded codesandbox and it runs fine here.

davestewart commented 5 years ago

How did you finally resolve this @leonardotessaroalves? It's a little unclear what the particular problem was.

@leonardotessaroalves was validating the validator, NOT the form, which he should have been :)

oller commented 5 years ago

How did you finally resolve this @leonardotessaroalves? It's a little unclear what the particular problem was.

@leonardotessaroalves was validating the validator, NOT the form, which he should have been :)

ah right, i'm not validating anything - this error is occurring on initial load, not on a submission event.

i'm just going through your previous comments, again thanks for the replies, but at my breakpoints, it looks like the options object does not have the new methods added. just for sanity - i've tried a couple of versions of node, but if you could let me know what you're running just so i can eliminate that

oller commented 5 years ago

The state of the object.methods object at line 129

image

i.e. no getDriver()

oller commented 5 years ago

Aha!

It's a conflict with another plugin.

https://github.com/freearhey/vue2-filters, if i disable that, it's all gravy.

I've added that to the sandbox so you can see the issue.

https://codesandbox.io/s/wyz98n37o7

davestewart commented 5 years ago

Well spotted! That thought crossed my mind, but I neglected to follow it.

Do you know what code in that repo conflicts, and why? I looked through the code, and there doesn't seem to be anything that would conflict (if it is actually this).

Does it change if you put it before or after VeeElement?

oller commented 5 years ago

I was only using that for currency formatting, so can probably find a workaround/replacement for that. But in the code sandbox it's not being referenced at all in the templates, just Vue.use()ing it is enough to cause this issue.

I'll dig a little deeper... In any case, thanks again for the prompt replies and a really handy plugin!

oller commented 5 years ago

https://github.com/freearhey/vue2-filters/issues/52

This thread looks rather ominous and suspicious!

davestewart commented 5 years ago

The only thing I can think, is that it somehow forces VeeElement to evaluate early. I'm not sure why this is.

I'll look to see if I can add a check to the computed function. Maybe that will prevent it on load, then subsequent calls will succeed.

Of course, I would like to know why it's not working though!

davestewart commented 5 years ago

This thread looks rather ominous and suspicious!

I recall seeing something similar a while ago!

I disliked the idea of bulk-adding all the filters anyway; normally I just add what I need.

Anyway - good spot, thanks!

davestewart commented 5 years ago

PS. ever come to the London Vue meetups?

oller commented 5 years ago

I intend to start! I feel I've a little more homework to do beforehand though! 😄

davestewart commented 5 years ago

Ah, just come along!

fromberg100 commented 5 years ago

Hi, I had the same issue with getDriver method. As mentioned, somehow the method doesn't exist in options object. I solved this way:

options.methods = {
    ...options.methods,
    ...{
        getDriver() {
            return drivers[this.form.driver || defaultDriver]
        },

        validate(trigger, callback) {
            const driver = this.getDriver()
            return driver.validate.apply(this, [trigger, callback, driver]) // pass driver as 3rd argument to get around binding
        },

        getRules() {
            return this.getDriver().getRules.apply(this)
        },

        getFilteredRule(trigger) {
            return this.getDriver().getFilteredRule.apply(this, [trigger])
        }
    }
};

Object.assign somehow is not working properly. I am using TypeScript and webpack, probably there is something with it.

I hope this gives you some ideas on what is causing the problem.

davestewart commented 5 years ago

@fromberg100 - did you read the thread above?

You are validating the form component and not the validator, right?

What versions of element ui and vee valdiate are you using?

fromberg100 commented 5 years ago

Actually I am not manually validating, I first was testing on blur events.

versions: vee-validate: 2.1.3 element-ui: 2.4.11

I will prepare a minimal project where the error is reproduced.

fromberg100 commented 5 years ago

Sorry, false alarm. When I prepared a minimal project, it worked. I tried many things and finally noted that the cause whas Vuex.

I had to place Vue.use(Vuex) before importing element components.

davestewart commented 5 years ago

Actually I am not manually validating, I first was testing on blur events.

I had to place Vue.use(Vuex) before importing element components.

Hmm.

It would be good for me to look at this anyway; perhaps I can update the docs so others don't fall into the same trap.

Would you mind posting a demo repo (or maybe on CodeSandbox) with these issues so I can examine?

fromberg100 commented 5 years ago

Sure, please check:

https://codesandbox.io/s/1806q70lpq

See lines 27 and 28, as follows: Vue.use(ElementUI); Vue.use(Vuex); *this way it fails

If you switch like this: Vue.use(Vuex); Vue.use(ElementUI); *this way it works

davestewart commented 5 years ago

Thanks!

oller commented 5 years ago

Argh this has reared its head again, even having disabled plugins (the previous cause in my case). I'm going to spend some time rolling back dependency updates / changes until I can diagnose the cause of the issue. Is there a way this could fail more gracefully?

davestewart commented 5 years ago

Good news - latest contract we will be using Element UI, so I will have time to spend on this lib again.

Did anyone ever figure out why this is happening in the first place?

Otherwise, then I could add a check and perhaps a console.warn().

oller commented 5 years ago

I've tried to distill down an example, but can't really top the one @fromberg100 put together. I've forked it and updated all deps to latest, the issue remains when toggling the order in which Vuex is referenced.

In the app I'm working on, making this change doesn't seem to resolve it (but i'm using vuex modules which are implemented slightly differently), but seeing as the error is the same, I'm sure the root issue is the same.

https://codesandbox.io/s/mrqn7078p

diegoaguilarf commented 5 years ago

Hi there,

I'm encountering the same issue.

TypeError: this.getDriver is not a function

when I had to place

Vue.use(ElementUI, { locale })
Vue.use(VeeElement)

before of

Vue.use(VueGoogleMaps, {
  load: {
    key: 'AIzaSyAHzdPfXH4HjURSH4FmfLqzIZgfOcvNwxM',
    libraries: 'places'
  }
})

the dependency is import * as VueGoogleMaps from 'vue2-google-maps'

oller commented 5 years ago

You may want to obfuscate your API key in the above post @Daafaguilar98

In my instance, i've managed to avoid the error by registering element-ui and vee-element plugins at the very end, after all my other plugins

i.e.

const registerPlugins = () => {
  Vue.use(VueMoment)
  Vue.use(VueBars)
  Vue.use(VLazyImagePlugin)
  Vue.use(VueProgressBar, {
    color: '#67c23a',
    failedColor: '#f56c6c'
  })
  Vue.use(Auth)
  Vue.use(ElementUI, {
    locale
  })
  Vue.use(VeeElement, validator, true)
}
whoisarpit commented 5 years ago

I was facing the same issue for a very long time and tried fixing it thrice to no avail.

Finally figured out the fix. Please check #24

ycgambo commented 5 years ago

when will you publish a new release to fix this issue

davestewart commented 5 years ago

Sorry everyone about this issue; it's been a crazy year, with no time for side work.

I'm doing Open Source work all next week, so I'll look at this then.

Thanks for your patience 🙏