A jQuery datepicker is wrappped in a Vue component. The component emits an update message used to update the app model.
The app has two datepicker input fields:
startDate
adjustmentDate
When startDate
is modified, adjustmentDate
is to be updated to the next first or fifteenth of the month. However, the adjustmentDate
datepicker component is not being notified of the update.
Expected behaviour:
startDate
datepickeronSelect
triggers the Vue componentemit
which is captured by Vue methodupdateStartDate
method
updateStartDate
sets model propertyadjustmentDate
It was hoped this would trigger the adjustmentDate
component update since the adjustmentDate
model attribute is bound to the datepicker componentDate
property which has a watch.
But changing the model doesn't have the affect of notifying the component.
Any suggestions how to do this properly and show the newly calculated adjustmentDate
when the startDate
is changed?
Demo code:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<link rel="stylesheet" href="http://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://unpkg.com/vue"></script>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
</head>
<body>
<div id="app">
<div><label>Start date</label></div>
<div>
<date-picker
v-model="startDate"
v-bind:component-date="startDate"
date-format="yy-mm-dd"
@update-date="updateStartDate"
v-once
></date-picker>
</div>
<div><label>Adjustment date</label></div>
<div>
<date-picker
v-model="adjustmentDate"
v-bind:component-date="adjustmentDate"
date-format="yy-mm-dd"
@update-date="updateAdjustmentDate"
v-once
></date-picker>
</div>
</div>
<script>
Vue.component('date-picker', {
props: ['dateFormat', 'componentDate'],
template: '<input/>',
mounted: function() {
var self = this;
var _convertDateStringToDate = function(dateString) {
var dateParts = dateString.split("-");
var year = dateParts[0];
var month = dateParts[1];
var dayOfMonth = dateParts[2];
return new Date(year, month, dayOfMonth);
};
$(this.$el).datepicker({
dateFormat: this.dateFormat,
onSelect: function(date) {
self.$emit('update-date', _convertDateStringToDate(date));
},
onClose: function(date) {
self.$emit('update-date', _convertDateStringToDate(date));
}
});
$(this.$el).datepicker('setDate', this.componentDate);
},
watch: {
componentDate: function(newValue, oldValue) {
$(this.$el).datepicker('setDate', this.componentDate);
}
},
beforeDestroy: function() {
$(this.$el).datepicker('hide').datepicker('destroy');
}
});
var _calculateAdjustmentDate = function(date) {
var year = date.getFullYear();
var month = date.getMonth();
var dayOfMonth = date.getDate();
if (dayOfMonth > 15) {
month = month + 1;
dayOfMonth = 1;
} else if (dayOfMonth > 1 && dayOfMonth < 15) {
dayOfMonth = 15;
}
return new Date(year, month, dayOfMonth);
};
var data = function() {
var now = new Date();
return {
startDate: now,
adjustmentDate: _calculateAdjustmentDate(now),
};
};
new Vue({
el: '#app',
data: data,
methods: {
updateStartDate: function(date) {
this.startDate = date;
this.adjustmentDate = _calculateAdjustmentDate(date);
},
updateAdjustmentDate: function(date) {
this.adjustmentDate = date;
},
}
});
</script>
</body>
</html>