Let Vue register datepicker event - javascript

How can i let Vue know that the datepicker changed the date?
new Vue({
el: '#app',
data: {
termin: ''
},
computed: {
},
methods: {
}
})
Just an input field:
<div id="app">
<div class="uk-form-icon"><i class="uk-icon-calendar"></i>
<input name="termin" v-model="termin" value="" placeholder="Choose date" type="text" data-uk-datepicker="{format:'DD.MM.YYYY'}" required="required">
</div>
<p>
Date: {{termin}}
</p>
</div>
If you chage the input field by hand Vue gets it, but not after triggering the picker.
https://jsfiddle.net/Honkoman/dfohvcpk/

The quickest way to do this would be to add a handler for the hide event from the datepicker in your Vue.
mounted(){
$(this.$el).on('hide.uk.datepicker', e => this.termin = this.$refs.date.value)
}
Here is your fiddle updated to do that.
However, traditionally, you should wrap jQuery interaction in a wrapper component.
Vue.component("datepicker",{
props:["value"],
template:`
<input ref="date" name="termin" :value="value" placeholder="Choose date" type="text" data-uk-datepicker="{format:'DD.MM.YYYY'}" required="required">
`,
mounted(){
$(this.$el).on('hide.uk.datepicker', e => this.$emit('input', this.$refs.date.value))
}
})
And your template would become
<div class="uk-form-icon"><i class="uk-icon-calendar"></i>
<datepicker v-model="termin"></datepicker>
</div>
And here is your fiddle updated to work with that.

UiKit events + Vue.set :
FIDDLE
$('input[name="termin"]').on('hide.uk.datepicker', function(){
Vue.set(vm, 'termin', document.querySelector('input[name="termin"]').value)
});

Related

How to make changes in vue v-model syntax in vue

I have a little task in vue.js and I want to change the syntax of v-model to model, or something else with webpack and vue-loader. I tried directives but that's not what I need.
This my example:
<input v-model="anyVarible">
<input model="anyVarible">
v-model is just a syntax sugar on setting & getting the data - prepared for all the input types:
You can use the v-model directive to create two-way data bindings on
form input, textarea, and select elements. It automatically picks the
correct way to update the element based on the input type. Although a
bit magical, v-model is essentially syntax sugar for updating data on
user input events, plus special care for some edge cases.
Source: Vue 2 v-model
That means, you can change v-model to something else, but then you have to handle the cases:
new Vue({
el: "#app",
data() {
return {
vmodeltext: null,
modeltext: null,
vmodelcb: null,
modelcb: null,
}
},
methods: {
handleInputText({
target: {
value
}
}) {
this.modeltext = value
},
handleInputCb({
target: {
checked
}
}) {
this.modelcb = checked
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<input type="text" v-model="vmodeltext" /><br /> With v-model: {{ vmodeltext }}<br />
<hr />
<input type="text" :value="modeltext" #input="handleInputText($event)" /><br /> With modeltext: {{ modeltext }}<br />
<hr />
<input type="checkbox" v-model="vmodelcb" /><br /> With v-model: {{ vmodelcb }}<br />
<hr />
<input type="checkbox" :checked="modelcb" #change="handleInputCb($event)" /><br /> With modelcb: {{ modelcb }}<br />
</div>
So, essentially you don't need to change v-model with Webpack or a loader - just write the code in the way you need.

Vue setCustomValidity with dynamic text

I'm currently trying to change the default invalid text from form inputs using the code below. The way I'm trying to do it works if the text is static but in my case, the text must be dynamic so I have to put in some sort of prop/data value instead. This is because users will have the ability to toggle between English and Chinese text. I've tried using #invalid and :oninvalid but those don't seem to work. Would anyone be able to help me get through this issue?
<input
ref="firstInput1"
type="email"
v-model="email"
oninvalid="this.setCustomValidity('custom text on invalid')"
onchange="this.setCustomValidity('')"
:placeholder="Email"
required
/>
oninvalid and onchange are the two key components to making this work. Hopefully we can find out how to do this with dynamic text.
For change event in Vue input you should use #change (not onchange)
And I think this sample can help you to set vue validation on email
<div class="container" id="app">
<div :class="['input-group', isEmailValid()]">
<span class="input-group-addon" id="basic-addon1"><span class="fa fa-envelope"></span></span>
<input type="email" class="form-control" placeholder="Email Address" v-model="email" />
</div>
</div>
and
new Vue({
el: '#app',
data: {
email: '',
reg: /^(([^<>()\[\]\\.,;:\s#"]+(\.[^<>()\[\]\\.,;:\s#"]+)*)|(".+"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,24}))$/
},
methods: {
isEmailValid: function() {
return (this.email == "")? "" : (this.reg.test(this.email)) ? 'has-success' : 'has-error';
}
}
});

Vuejs returning data while user typing

I have numeric input field and I'd like to return some results while user is filling the input field.
code
<input type="number" name="bid" v-model="bid.bid" class="form-control">
Logic
Users starts to type numbers in field above
Will get that number -%10 below it
Returned number will change consistently when user changes the input
example:
PS: The reason that I didn't share any watch, mounted, etc. code is
because i don't have any code for this question.
any idea?
You can insert the value directly into the page pretty easily using interpolation:
<div>You get: {{bid.bid * 0.9}}</div>
This is a very simple snippet. Hope it would be useful.
var app = new Vue({
el: '#app',
data: {
bid: 0
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
your bid: <input type="number" name="bid" v-model.number="bid" class="form-control">
<br>
your result: <span>{{bid*0.9}}</span>
</div>
You can use a computed property for that :
new Vue({
el: "#app",
data: {
bid: 1000
},
computed: {
reducedBid() {
return this.bid * 0.9
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<input type="number" name="bid" v-model="bid" class="form-control">
<p>You get {{ reducedBid }}</p>
</div>
Here is a resource on computed properties.
Hope it helps!

Vue - passing v-model from child to parent in v-for loop

I'm building a form builder in Vue which allows users to add/remove various types of input. My method so far is to have a template component for each input type, then when a user selects that input type I push it into an array on the parent component to loop over and display.
However, I also need to pass the value of the input up to the parent (and store it in the input type="hidden" element), so I'm emitting an event in the child component and catching it in the parent. My problem is that the value of labelText gets updated identically for every input type="hidden" at once when I type, rather than individually. I can't work out what I'm missing?
Text input template
<template>
<div id="TextInput">
<input type="text" placeholder="Question" class="form__input_label" #input="sendLabelUp($event.target.value)" />
<input type="text" placeholder="Test placeholder" />
<slot name="removeField"></slot>
<slot name="hiddenInputs"></slot>
</div>
</template>
<script>
export default {
name: 'TextInput',
methods: {
sendLabelUp: function(val) {
this.$emit('input', val);
},
},
};
</script>
Parent template (just including the part I think is relevant)
<transition-group name="form__input_list" tag="div">
<component :is="input.type" v-for="(input, index) in inputs" v-bind="input" :key="input" v-model="labelText" class="form__input">
<div slot="removeField">
<a class="btn btn--tertiary sml-push-top-half" #click="removeField(index)">Remove</a>
</div>
<div slot="hiddenInputs">
<!-- Hidden inputs used to store question config -->
<input type="hidden" :name="`pages[0]questions[${index}]type[${input.type}]label[${labelText}]`" />
</div>
</component>
</transition-group>
<script>
export default {
name: 'InputGenerator',
components: {
TextInput,
TextArea,
NumberInput,
LikertScale,
},
data() {
return {
inputs: [],
dropdownActive: false,
labelText: '',
};
},
};
</script>

Watch is not firing when v-model changes

I'm trying to trigger a method when a date is changed in my HTML. When I change the date it is updating the model selectedDate on the screen but its like my watch method just isn't seeing the change at all.
<div class="col-md-8">
<h3>Daily Summary - {{ selectedDate }}</h3>
</div>
<div class="col-md-4">
<p>Change date</p>
<input type="date" name="date" v-model="selectedDate">
</div>
My watch code:
data() {
return{
selectedDate: null
}
},
watch: {
selectedDate: function(){
console.log('date changed');
}
},
Edit: To give more context to the question, I'm running this code inside a template using export like so:
<template>
<div>
<div class="col-md-8">
<h3 v-on:click="testEvent(event)">Daily Summary - <span v-if="data.nxt_summary">{{ selectedDate }}</span></h3>
</div>
<div class="col-md-4">
<p>Change date</p>
<input type="date" name="date" v-model="selectedDate">
</div>
</div>
</template>
<script>
export default {
data() {
return{
selectedDate: null
}
},
watch: {
selectedDate: function(){
console.log('date changed');
}
},
}
</script>
It doesn't look like type="date" fires an input event till there's a whole date in the input. If you use the picker it'll fire, but if you update each piece separately it won't fire till the month, day AND year is filled in. https://jsfiddle.net/tg2s4kkq/1/
What I'd do it set selectedDate to a default value and mark the field required so the user can't empty it.
https://jsfiddle.net/tg2s4kkq/3/

Categories