Reputation: 1571
Hope someone can help me! I have made a directive wrapping the Jasny Bootstrap Plugin more specifically the input-mask thing and everything goes well!
Now I have made a custom filter supported by moment to format the date field!
The date format that I receive from my backend application is YYY-MM-DD and I must show on the view as DD/MM/YYYY... I've tried v-model="date | myDate"
but it didn't work properly!
JS
Vue.directive('input-mask', {
params: ['mask'],
bind: function() {
$(this.el).inputmask({
mask: this.params.mask
});
},
});
Vue.filter('my-date', function(value, formatString) {
if (value != undefined)
return '';
if (formatString != undefined)
return moment(value).format(formatString);
return moment(value).format('DD/MM/YYYY');
});
var vm = new Vue({
el: 'body',
data: {
date: '2015-06-26',
}
});
HTML
<label>Date</label>
<input type="text" class="form-control" v-input-mask mask="99/99/9999" v-model="date">
<p>{{ date | myDate 'dd/mm/yyyy' }}</p>
There is the JSBin if somebody's interested!
Thanks in advance!
EDIT: Explaining better what I expect =)
When the page first load the input receive the value of 2015-06-26 and I would like to show that value as DD/MM/YYYY so 26/06/2015! It works properly only after I start typing something!
Upvotes: 31
Views: 65875
Reputation: 741
use value for bind on text field example:
<v-text-field :value="string | stringFormat"></v-text-field>
Upvotes: 0
Reputation: 87
I would like to offer an alternative, with the hook update from Vue-directive
export default {
data() {
return {
someData: '',
}
},
directives: {
lowercase: {
update(el) {
el.value = el.value.toLowerCase()
},
},
uppercase: {
update(el) {
el.value = el.value.toUpperCase()
},
},
capitalize: {
update(el) {
const lowerCase = el.value.toLowerCase()
el.value = lowerCase.charAt(0).toUpperCase() + lowerCase.slice(1)
},
},
},
}
or
Vue.directive('lowercase', {
update(el) {
el.value = el.value.toLowerCase()
}
})
Vue.directive('uppercase', {
update(el) {
el.value = el.value.toUpperCase()
}
})
Vue.directive('capitalize', {
update(el) {
const lowerCase = el.value.toLowerCase()
el.value = lowerCase.charAt(0).toUpperCase() + lowerCase.slice(1)
}
})
<input type="text" v-model="someData" v-capitalize />
Upvotes: 1
Reputation: 572
Template
<input type="text" v-model="date" @change="onDateChange">
Component
methods: {
onDateChange(event) {
this.myDate = event.target.value
}
getFormatedDate(date) {
return '2020/08/19'
}
},
computed: {
date() {
return this.getFormatedDate(this.myDate)
}
}
Upvotes: 1
Reputation: 2355
Go to main.js and add the following code :
import moment from 'moment'
Vue.filter('myDate', function (value) {
if (value) {
return moment(String(value)).format('dd/mm/yyyy')
}
});
In your HTML do the following :
<label>Date</label>
<v-text-field :value="date | myDate" @input="value=>date=value"></v-text-field>
<p>{{ date | myDate 'dd/mm/yyyy' }}</p>
So we used above v-bind to bind the value and @input event handler to have the v-model functionality.
Upvotes: 15
Reputation: 383
I've found that I can filter input using the ordinary component v-bind:value
/ v-on:input
dance without resorting to data
or watch
clauses if I just call $forceUpdate()
after emitting the filtered value:
The Vue component:
{
props: ['value'],
methods: {
mEmit: function(EVT) {
const VAL = EVT.target.value;
var FILTERED = myFilterFunction(VAL);
this.$emit('input', FILTERED);
this.$forceUpdate();
}
}
}
The component HTML (data is filtered as it is entered):
<input type="text" v-bind:value="value" v-on:input="mEmit($event)" />
Using the component:
<my-component v-model="myDataVar"></my-component>
Upvotes: 0
Reputation: 1044
This is how I implemented a vue filter for a v-model using the watch callback, this won't update the value on load.
Vue.filter('uppercase', function (value) {
return value.toUpperCase();
});
The html:
<input type="text" v-model="someData">
And the watch callback:
watch:{
someData(val) {
this.someData = this.$options.filters.uppercase(val);
},
}
Upvotes: 5
Reputation: 5186
I understand what you are trying to do, however, because of the two way binding when using v-model, it may be better to just format the date as you receive it from the server, and then, use it with the desired format in your front-end app ('DD/MM/YYYY'
).
When sending the data back to the back-end, you just format it back to the desired server format ('YYYY-MM-DD'
).
In your Vue app, the work flow would be something like this:
new Vue({
el: 'body',
data: {
date: null,
},
methods: {
getDataFromServer: function() {
// Ajax call to get data from server
// Let's pretend the received date data was saved in a variable (serverDate)
// We will hardcode it for this ex.
var serverDate = '2015-06-26';
// Format it and save to vue data property
this.date = this.frontEndDateFormat(serverDate);
},
saveDataToServer: function() {
// Format data first before sending it back to server
var serverDate = this.backEndDateFormat(this.date);
// Ajax call sending formatted data (serverDate)
},
frontEndDateFormat: function(date) {
return moment(date, 'YYYY-MM-DD').format('DD/MM/YYYY');
},
backEndDateFormat: function(date) {
return moment(date, 'DD/MM/YYYY').format('YYYY-MM-DD');
}
}
});
This works well for me, hope it helps.
Here is a fiddle for it:
https://jsfiddle.net/crabbly/xoLwkog9/
Syntax UPDATE:
...
methods: {
getDataFromServer() {
// Ajax call to get data from server
// Let's pretend the received date data was saved in a variable (serverDate)
// We will hardcode it for this ex.
const serverDate = '2015-06-26'
// Format it and save to vue data property
this.date = this.frontEndDateFormat(serverDate)
},
saveDataToServer() {
// Format data first before sending it back to server
const serverDate = this.backEndDateFormat(this.date)
// Ajax call sending formatted data (serverDate)
},
frontEndDateFormat(date) {
return moment(date, 'YYYY-MM-DD').format('DD/MM/YYYY')
},
backEndDateFormat(date) {
return moment(date, 'DD/MM/YYYY').format('YYYY-MM-DD')
}
}
})
Upvotes: 18
Reputation: 1439
I had a similar problem when I wanted to uppercase an input value.
This is what I ended up doing:
// create a directive to transform the model value
Vue.directive('uppercase', {
twoWay: true, // this transformation applies back to the vm
bind: function () {
this.handler = function () {
this.set(this.el.value.toUpperCase());
}.bind(this);
this.el.addEventListener('input', this.handler);
},
unbind: function () {
this.el.removeEventListener('input', this.handler);
}
});
Then I can use this directive on the input field with a v-model
.
<input type="text" v-model="someData" v-uppercase="someData">
Now, whenever I type into this field or change someData
, the value is transformed to uppercase.
This essentially did the same thing as I hoped v-model="someData | uppercase"
would do. But of course, you can't do that.
In summation: make a directive that transforms the data, not a filter.
Upvotes: 18
Reputation: 25221
When you get the value initially, adjust it to fit the input. I got it working in the ready
function, but you could do this after your DB call as well:
ready: function(){
var year = this.date.substr(0, 4);
var monDay = this.date.substr(5,5);
var result = monDay + "-" + year;
this.date = result.replace(/-/g,"/");
}
You may have to do something similar on the way back up to your database as well.
Upvotes: 2