Vue.JS checkbox without v-model - vue.js

Trying to create a checkbox without using v-model
<input type="checkbox" :value="value" #change="$emit('input', $event.target.checked)" />
The checkbox will check and uncheck, and the input event is sent to the parent, but the value doesn't change. My parent component looks like this:
<custom-component v-model="some_boolean_value"></custom-component>

For checkboxes, use :checked instead of :value. See demo below.
Vue.component('custom-component', {
template: '#custom',
props: ['value']
})
new Vue({
el: '#app',
data: {
some_boolean_value: true
}
})
<script src="https://unpkg.com/vue"></script>
<div id="app">
<p>some_boolean_value: {{ some_boolean_value }}</p>
<custom-component v-model="some_boolean_value"></custom-component>
</div>
<template id="custom">
<div style="border: 2px dashed red;">
<input type="checkbox" :checked="value" #change="$emit('input', $event.target.checked)" />
</div>
</template>

Related

VeeValidate with Yup: input type="number" value is converted to string on submit

I use VeeValidate and Yup for form validation and don't know why my input field with type="number" is converted to string on submit.
When I input 78 and submit the form the output of the console.log in the onSubmit(values) function is the following:
values: {
prioritaet: "78"
}
Am I doing something wrong here or is this the normal behavior of VeeValidate and Yup? I would like to have a number instead of a string after submit.
My code looks like this:
<template>
<div class="container m-3">
<div class="row bg-primary align-items-center py-2">
<div class="col">
<h3 class="text-light mb-0">Format {{ this.action }}</h3>
</div>
<div class="col-auto">
<h5 class="text-light mb-0">{{ this.formatTitle }}</h5>
</div>
</div>
<Form #submit="onSubmit" :validation-schema="formatSchema" v-slot="{ errors }" ref="formatForm">
<div class="row mt-4">
<div class="col">
<h5>Formatdaten</h5>
</div>
</div>
<div class="row mb-2">
<div class="col-4">
<label for="prioritaet-input">Priorität: </label>
</div>
<div class="col">
<Field type="number" name="prioritaet" id="prioritaet-input" class="w-100" />
</div>
</div>
<div class="row justify-content-end">
<div class="col-auto me-auto">
<button class="btn btn-outline-primary">Änderungen übernehmen</button>
</div>
<div class="col-auto">
<button class="btn btn-outline-primary">Abbrechen</button>
</div>
<div class="col-auto">
<button type="sumbit" class="btn btn-outline-primary">Speichern</button>
</div>
</div>
<div class="row mt-4">
<template v-if="Object.keys(errors).length">
<span class="text-danger" v-for="(message, field) in errors" :key="field">{{ message }}</span>
</template>
</div>
</Form>
</div>
</template>
<script>
import { Form, Field } from "vee-validate";
import deLocale from "../assets/yup-localization.js";
import * as Yup from "yup";
import { markRaw } from "vue";
import { mapActions, mapState } from "vuex";
Yup.setLocale(deLocale);
export default {
name: "FormatBearbeitungsSchirm",
props: ["material_id"],
data() {
let action = "neu";
let formatTitle = "Format neu";
let formatSchema = markRaw(Yup.object().shape({
prioritaet: Yup.number().min(1).max(100).integer().label("Priorität"),
}));
return { formatSchema, action, formatTitle };
},
created() {
},
components: {
Form,
Field,
},
methods: {
onSubmit(values) {
console.log("values", values);
},
},
};
</script>
It looks like there is currently no support for specifying the .number modifier on the internal field model value of <Field>, so the emitted form values would always contain a string for number-type fields.
One workaround is to convert the value in the template, updating <Form>'s values slot prop in <Field>'s update:modelValue event:
<Form #submit="onSubmit" v-slot="{ values }">
<Field 👆
type="number"
name="prioritaet" 👇
#update:modelValue="values.prioritaet = Number(values.prioritaet)"
/>
<button>Submit</button>
</Form>
demo
Another simple workaround is to convert the property inside onSubmit before using it:
export default {
onSubmit(values) {
values.prioritaet = Number(values.prioritaet)
// use values here...
}
}
You must use the .number modifier.
You can read about it here
If you want user input to be automatically typecast as a Number, you can add the number modifier to your v-model managed inputs:
const app = new Vue({
el: "#app",
data: () => ({
mynumber1: undefined,
mynumber2: undefined
}),
methods: {
submit() {
console.log(typeof this.mynumber1, this.mynumber1)
console.log(typeof this.mynumber2, this.mynumber2)
}
}
})
<script src="https://cdn.jsdelivr.net/npm/vue#2.6.14/dist/vue.js"></script>
<div id="app">
<form>
<!-- number modifier -->
<input type="number" v-model.number="mynumber1" placeholder="Type here" />
<!-- no modifier -->
<input type="number" v-model="mynumber2" placeholder="Type here" />
<input type="button" #click="submit" value="submit" />
</form>
</div>

Vue.js convert all inputs to a v-model

I just want to know if what i'm doing is correct.
The goal
here is to convert all input fields in a v-model.
Right now im using jQuery to do that, and is working well.
Is there any way to do it with pure vue.js?
Some considerations:
I don't want to use v-model or any vue attribute on the html like ref="foo".
The data must be in and object and I don't want to predefine.
Thanks
const vueApp = new Vue({
el: '#vue-app',
data: {
dataForm: {}
},
created() {
$("input").each(function(){
var $input_name = 'dataForm.' + $(this).attr('name');
$(this).attr('v-model', $input_name);
});
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="vue-app">
<div class="">
First Nane : {{ dataForm.firstName }}
</div>
<div class="">
Last Name : {{ dataForm.lastName }}
</div>
<div class="">
<input type="text" name="firstName" value="">
<input type="text" name="lastName" value="">
</div>
</div>

Set v-model value within a slot in Vuejs

I have two components
child-component.vue
<template>
<div class="container">
<slot>
</div>
</template>
parent-component.vue
<template>
<my-component>
<input type="text" v-model="myinput1">
<input type="text" v-model="myinput2">
<input type="text" v-model="myinput3">
</my-component>
</template>
<script>
export default {
data() {
return {
myinput1: '',
myinput2: '',
myinput3: '',
}
}
}
</script>
I need to set the values of each input field inside the slot directly from child-component (the number of input fields could change).
Is there a way to achieve it without triggering an event from child component?
Thanks
EDIT - modified the code to handle variable number of inputs
In the child component
<template>
<div class="container">
<slot :data="slotData" />
</div>
</template>
<script>
export default
{
data()
{
return {
slotData: ['1', '2', '3']
};
}
}
</script>
In the parent component
<template>
<my-component>
<template slot-scope="props">
<input v-for="item in props.data" type="text" v-model="item">
</template>
</my-component>
</template>

Vue v-model lazy modifier not working on array elements

I have an array of objects which I iterate over with v-for and create an input for one of the object's properties and use vee-validate on that input. I want to validate lazily so I use v-model.lazy to update only on change and this is where the issue occurs. The data binding doesn't seem to happen correctly. The below fiddle reproduces my issue. Any advice would be much appreciated.
https://jsfiddle.net/1r944gnc/
Vue.use(VeeValidate)
new Vue({
el: '#app',
data: {
users: [
{
email: null
}
]
},
methods: {
}
})
<div id="app">
<div v-for="user in users">
<input type="text" name="foo" v-model.lazy="user.email" v-validate="'email'" />
<span v-show="errors.has('foo')">{{ errors.first('foo') }}</span>
</div>
</div>
I think this is a bug of VeeValidate.
There is a workaround which has same effect as your desire: Validate on blur event
<div id="app">
<div v-for="user in users">
<div>Email: {{ user.email }}</div>
<input type="text" name="foo" v-model="user.email" v-validate="'email'" data-vv-validate-on="blur"/>
<span v-show="errors.has('foo')">{{ errors.first('foo') }}</span>
</div>
</div>
Demo https://jsfiddle.net/4zjf2ph3/

How do I pick the date format?

How do I get bootstrap datetimepicker to pick date format as DD/MM/YY.Below is my code.Having referenced this SO answer. I created the following JSFiddle. As at now the result of the datepicker is like Fri Jan 12 2018 09:27:28 GMT+0300.
Below is the template code:
<div id="app" class="container">
<h3>Bootstrap Datetimepicker (eonosdan) Sample</h3>
<hr/>
<div class="row">
<div class="col-md-4">
<label>Select Date</label>
<vue-datetimepicker></vue-datetimepicker>
</div>
</div>
</div>
<template id="dttemplate">
<div class='input-group date'>
<input type='text' v-model="value" class="form-control" />
<span class="input-group-addon">
<span class="glyphicon glyphicon-calendar"></span>
</span>{{value}}
</div>
</template>
The JS component is as below:
Vue.component('vue-datetimepicker', {
template: '#dttemplate',
props: ['value'],
mounted: function() {
var vm = this
var mycomp = $(this.$el).datetimepicker({format: 'DD-MM-YYYY'})
mycomp.on('dp.change', function(e) {
vm.value = e;
app.$data.requestdate = e.date.format('DD-MM-YYYY');
vm.$emit('change', vm.value)
})
}
});
new Vue({
el: '#app',
data: {},
methods: {requestdate:moment().format('DD-MM-YYYY')}
})
<div class="form-group">
<date-picker v-model="requestdate"></date-picker>
</div>
Taking out the props: ['value'] from the component and v-model="value" results in datetimepicker being properly formatted.But well that renders it useless in terms of reusability.
Edit: After updating my code to the above it 'sort of works' but it renders the component only useful for a single datetimepicker.