14

I currently use Vue.JS 2.0 and I want to update the model off one Vue instance from an custom directive, but im looking a nice way to do it, this is because i trying to create an custom directive that implement JQueryUI-Datepicker the code is the follow:

<input type="text" v-datepicker="app.date" readonly="readonly"/>

Vue.directive('datepicker', {
  bind: function (el, binding) {
    $(el).datepicker({
      onSelect: function (date) {
        //this is executed every time i choose an date from datepicker
        //pop.app.date = date; //this work find but is not dynamic to parent and is very dirty
        Vue.set(pop, binding.expression, date); //this should work but nop
      }
    });
  },
  update: function (el, binding) {
    $(el).datepicker('setDate', binding.value);
  }
});

var pop = new Vue({
    el: '#popApp',
    data: {
        app: {
            date: ''
        }
    }
});

Someone know how to update pop.app.date in a dynamic way from the directive, i know that binding.expression return in this example app.date and date return the current date picked in the datepicker but i dont know how to update the model from the directive

3
  • 1
    Did you manage to find a solution @bal? Commented Nov 10, 2016 at 17:50
  • @chrisEdwards yes Commented Mar 7, 2017 at 22:36
  • can you elaborate please? Commented Mar 8, 2017 at 10:12

2 Answers 2

5

This will do the trick:

// vnode (third argument is required).
bind: function (el, binding, vnode) {
    $(el).datepicker({
        onSelect: function (date) {
            // Set value on the binding expression.
            // Here we set the date (see last argument).
            (function set(obj, str, val) {
                str = str.split('.');
                while (str.length > 1) {
                    obj = obj[str.shift()];
                }
                return obj[str.shift()] = val;
             })(vnode.context, binding.expression, date);
         }
    });
},

Reference: https://stackoverflow.com/a/10934946/2938326

Sign up to request clarification or add additional context in comments.

1 Comment

The self invoking function traverses the dot notation (e.g. app.date) dynamically by splitting on the dots and looping through until we reach the desired key (date in your example) and then sets its value based on the value you provide as the last argument.
0

Just to follow up on @Kamal Khan's answer (which works great).

I have just done the following and got it to work (below). This removes finding the object and relies on Vue's set functionality to set the value.

bind: function (el, binding, vnode) {
    $(el).datepicker({
        onSelect: function (date) {
             Vue.set(vnode.context, binding.expression, date);
         }
    });
},

My full directive is:

  Vue.directive("datepicker",{
    bind(el,binding, vnode) {
       console.log(binding);
       var self = el
      $(self).datepicker({
        dateFormat:'mm-dd-yy',
        onSelect: function (date) {
            Vue.set(vnode.context, binding.expression, date);
        }
    });      
    },
    updated: function (el,binding) {
    }
 });  

I can then call this in the template or html with:

 <input v-model="dtime" v-datepicker="dtime"> 

with dtime being my data model value.

Hope this helps somebody else as this drove me nuts.

2 Comments

When i try this on the version 2.5.16 i got an Vue warn and did not work "Avoid adding reactive properties to a Vue instance or its root $data at runtime - declare it upfront in the data option.". My first implementation is like @Kamal Khan's do it, i ended wrapping in a component and emiting the value
@DavidArreola can you share what you did on a codepen or something similar please :) ?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.