Vue is not rendering on right tags component - vue.js

The way i am defining my props;
<template>
<div>
<vinput id="login_name" label="Phone number"></vinput>
<div class="flex flex-col">
<label for="email-phone">School slug</label>
<input type="text" id="email-phone" class="border py-2 rounded">
</div>
</div>
</template>
<script>
import vinput from '../../components/Input.vue'
export default {
components:{
vinput
}
}
</script>
The way i am passing the props
<vinput id="login_name" label="Phone number"></vinput>
Please why is the browser rendering it this way:
<div class="mt-4">
<div class="flex flex-col" id="login_name" label="Phone number">
<label></label>
<input type="tex" class="border py-2 rounded">
</div>
<div class="flex flex-col"><label for="email-phone">School slug</label><input type="text"
id="email-phone" class="border py-2 rounded"></div></div>
I was expecting interpolation in the label and input not in the div
====Edited====
vinput component
<template>
<div class="flex flex-col">
<label :for="id">{{ label }}</label>
<input :type="type ? type : 'tex'"
:class="classes ? classes :''" class="border py-2 rounded"/>
</div>
</template>
<script>
export default {
data(){
return {
props:['label', 'id','type', 'classes']
}
}
}
</script>

Move your props:['label', 'id','type', 'classes'] away from data.
Those are totally different things.
<script>
export default {
props: ['label', 'id','type', 'classes'],
data(){
return {};
},
};
</script>

Related

how to $emit in vuejs

VueJS emit doesn't work, I'm trying to change the value of a boolean, but it doesn't want to emit the change
here is the first component:
<template>
<div id="reg">
<div id="modal">
<edu></edu>
</div>
<div :plus="plus" v-if="plus" #open="plus = !plus">
abc
</div>
</div>
</template>
the script:
<script>
import edu from './education/edu.vue'
export default {
components: {
edu
},
data() {
return {
plus: false
}
}
}
</script>
the second component with the emit:
<template>
<div id="container">
<h2>Education</h2>
<form action="">
<input type="text" class="input" placeholder="preparatory/bachelor/engineering..">
<input type="text" class="input" placeholder="University..">
<input type="text" class="input" placeholder="Where?..">
<h6>Start date</h6>
<input type="date" class="input" value="2017-09-15" min="2017-09-15" max="2021-09-15">
<div class="end-date">
<h6>End date</h6>
<div class="flexend">
<h6>present</h6><input type="checkbox" name="" id="checkbox" #click="checked">
</div>
</div>
<input type="date" class="input" v-if="show" value="2017-09-15" min="2017-09-15">
<div class="flex-end">
<button class="btn-plus" #click="$emit('open')"><i class="fas fa-plus"></i></button>
</div>
<div class="flex-end">
<button class="btn">next <i class="fas fa-arrow-right"></i></button>
</div>
</form>
</div>
</template>
the script:
<script>
export default {
props:{
plus: Boolean
},
data(){
return{
show: true,
}
},
I thought this is working, but it seems like it's not
You should use the component name instead of the div element :
<edu :plus="plus" v-if="plus" #open="plus = !plus">
abc
</edu>

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>

Bind data with router-link in the vue

I have declared a data variable inside my component. There is a select box that dynamically changes this data value. what I want to use this data value inside my router-link. but somehow it is not working.
Here is my code for the same:
<template>
<div class="row bg-blue content-padding pdt-70 relative d-flex">
<div class="col-md-8">
<div class="row mgb-60">
<form>
<div class="col-8 form-group mgb-30">
<label for="work-profile" class="color-white">Work Profile*</label>
<select id="work-profile" v-model="page" name="work-profile" class="form-control">
<option value="self-employed">Self Employed</option>
<option value="salaried">Salaried</option>
</select>
</div>
<div class="col-12 form-group">
<router-link :to=["/"+page]>
<button type="submit" class="btn form-button button-blue d-flex-inline justify-content-center align-items-center color-white bg-blue">Get Started</button>
</router-link>
</div>
</form>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: "LandingPage",
data: function()
{
return{
page:'salaried'
}
},
components: {
},
};
</script>
Replace <router-link :to=["/"+page]> to <router-link :to="'/'+page"> you do not need [] with binding to

Vue Conditional Classes from Prop Variable

So, currently, I have a set of radio buttons on my home.vue page and binding to a child component like so -
<div class="radio-toolbar prev-selector">
<input type="radio" id="one" value="Default" v-model="preview" />
<label for="one">Default</label>
<input type="radio" id="two" value="Padded" v-model="preview" />
<label for="two">Padded</label>
<input type="radio" id="three" value="Full" v-model="preview" />
<label for="three">Full</label>
<span>Picked: {{ preview }}</span>
</div>
<div class="media-wrapper">
<CardStyle
v-bind:card="this.preview"
/>
</div>
Which is then passing that "preview" data to the CardStyle Prop.
The prop is receiving it as ['card'] and I can use the data within my component.
However, am wondering how I can use the potential value of "this.preview" (which could be 'default', 'padded' or 'full') as a dynamic class to my child component without having to convert them to a true/false outcome and use -
:class="{ default: isDefault, padded: isPadded, full: isFull }"
(I have classes called .default, .padded and .full ready to use if it is as simple as passing the data in somehow.)
As long as this.preview has a value of the class name you want to use, just use :class="this.preview".
I built a couple of sample components that demonstrate how to solve your problem.
Parent.vue
<template>
<div class="parent">
<h5>Select Card Style</h5>
<div class="row">
<div class="col-md-6">
<div class="form-check">
<input class="form-check-input" type="radio" id="one" value="default" v-model="preview" />
<label class="form-check-label" for="one">Default</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" id="two" value="padded" v-model="preview" />
<label class="form-check-label" for="two">Padded</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" id="three" value="full" v-model="preview" />
<label class="form-check-label" for="three">Full</label>
</div>
</div>
</div>
<card-style :preview="preview" />
</div>
</template>
<script>
import CardStyle from './CardStyle.vue'
export default {
components: {
CardStyle
},
data() {
return {
preview: 'default'
}
}
}
</script>
CardStyle.vue
<template>
<div class="card-style">
<hr>
<div class="row">
<div class="col-md-6">
<span :class="preview">{{ preview }} Card Style</span>
</div>
</div>
</div>
</template>
<script>
export default {
props: {
preview: {
type: String,
required: true
}
},
}
</script>
<style scoped>
.default {
background-color: burlywood;
}
.padded {
background-color:lightskyblue
}
.full {
background-color:lightcoral
}
</style>
You can build a computed variable for your field class in your component. This will allow you to select or define what classes to use based on your conditions or case.
computed: {
myclasses() {
return [
'class1',
'class2',
[this.condition ? 'class3' : 'class4'],
{ class5: this.othercondition },
];
},
},
Then, just use it your template:
<div :class="myclasses"></div>

Is there a way to get the data from multiple selects as array?

I'm currently stuck on a task on VueJS. Basically I'm trying to create an array from multiple select inside a form to get all the data as an array or Object to process it further. I just searched but got no results or an idea on how to solve my issue.
Parent Component
<template>
<div id="product" class="mt-12">
<div class="flex flex-wrap mb-4">
<div class="w-1/2 pr-12">
<img src="https://placehold.it/800" alt="">
</div>
<div class="w-1/2">
<div class="flex justify-between content-center h-12 mb-4">
<div class="text-gray-700 py-2">
<h2 v-if="product.brand" class="leading-none font-bold text-sm">{{ product.brand }}</h2>
<h1 class="text-xl leading-snug">{{ product.name }}</h1>
</div>
<div class="text-gray-700 py-2">
<p class="text-xl font-bold leading-none">{{ product.price }}</p>
<p class="text-xs text-right leading-none">Inkl. 19% MwSt.</p>
</div>
</div>
<div class="divider bg-gray-400 mt-4 mb-4" />
<div id="variations">
<form action="">
<ProductVariation v-for="(variations, type) in product.variations" :type="type" :variations="variations" :key="type" v-model="form.variation"/>
<div class="flex w-full">
<button class="w-full leading-none bg-blue-500 hover:bg-blue-600 text-white py-2 rounded" type="submit">Add to cart</button>
</div>
</form>
</div>
</div>
</div>
</div>
</template>
<script>
import ProductVariation from '#/components/products/ProductVariation'
export default {
data () {
return {
product: null,
form: {
variation: null
}
}
},
components: {
ProductVariation
},
async asyncData({ params, app }) {
let response = await app.$axios.$get(`products/${params.slug}`)
return {
product: response.data
}
}
}
</script>
ProductVariation Component
<template>
<div class="flex mb-4">
<div class="w-full">
<label class="block text-gray-700 w-full text-sm font-bold">{{ type }}</label>
<select class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight" :name="type">
<option value="0">Please select</option>
<option v-for="variation in variations" :key="variation.id" :value="variation.id">{{ variation.name }} <span>( +{{ variation.price }} )</span></option>
</select>
</div>
</div>
</template>
<script>
export default {
props: {
type: {
required: true,
type: String
},
variations: {
required: true,
type: Array
}
},
}
</script>