4

Trying to build a component that works with daepicker and using v-model to bind the input value. But the input event does not appear to be firing and I can’t seem to figure out why. Here’s my component:

<div id="app">
    <datepicker v-model="date"></datepicker>
</div>

Vue.component('datepicker', {
        template: '<input type="text" class="form-control pull-right" placeholder="dd/mm/aaaa" autocomplete="off">',
        mounted: function() {
            $(this.$el).datepicker({
                autoclose: true,
                startView: 'years',
            }).on('changeDate', function(e) {
                this.$emit('input', e.format('dd/mm/yyyy'));
            });
        },
        destroyed: function () {
            $(this.$el).datepicker('destroy');
        }
    });

var app = new Vue({
    el: '#app',
    data: {
        date: '2018-03-01'
    }
})

In addition, the following error appears in the console:

Uncaught TypeError: this.$emit is not a function

Sairam Santana
  • 63
  • 1
  • 1
  • 7
  • Are you using jQuery and Vue.js together? If so, `this` in the jQuery event handler is not the same as `this` in the Vue component context – Stephen Thomas Jun 20 '18 at 21:35
  • after this code `mounted: function() {` add `var self = this` and the for the emit, use `self.$emit` meaning change: `this` to `self` – samayo Jun 20 '18 at 21:36

2 Answers2

4

If you're mixing jQuery and Vue (just a guess from the code fragment), you're mixing up your contexts. One (of many) ways to fix:

   mounted: function() {
        const self = this;
        $(this.$el).datepicker({
            autoclose: true,
            startView: 'years',
        }).on('changeDate', function(e) {
            self.$emit('input', e.format('dd/mm/yyyy'));
        });
    },
Stephen Thomas
  • 13,843
  • 2
  • 32
  • 53
3

I failed with jacky's answer, but thanks to https://github.com/Xelia, problem sovled (even in Vue 1.0, using ready life cycle instead of mounted)

Manually update vue data in datepicker changeDate event listener, like this

var app = new Vue({
  el: '#app',
  data: {
    startDate: '',
  },
  mounted() {
    $("#startDate").datepicker().on(
      "changeDate", () => {this.startDate = $('#startDate').val()}
    );
  },
})

https://jsfiddle.net/3a2055ub/

And by the way, if you are working on legacy company project using ES5 function instead of ES6 fat arrow function. Need to bind this, which is vue instance, into the function. For example:

mounted() {
  var self = this; // the vue instance
  $("#startDate").datepicker().on(
    "changeDate", function() {self.startDate = $('#startDate').val()}
  );
},

Of course there are other ways to reach this goal, as this blog written by Jason Arnold shows.

Reference: https://github.com/vuejs/vue/issues/4231

Probable related question: v-model not working with bootstrap datepicker

xofred
  • 174
  • 2
  • 6