reset a vuetify stepper - vue.js

I'm looking for a function who can resetting my stepper made with vuetify.
the e1 is set as 0 but if I make a function who reset this value to 0, it doesn't work and the stepper set as the same screen.

It is possible to reset a stepper to default state
Find the working codepen here: https://codepen.io/chansv/pen/wvvzddP?editors=1010
<div id="app">
<v-app id="inspire">
<v-stepper v-model="step" vertical>
<v-stepper-header>
<v-stepper-step step="1" :complete="step > 1">Your Information</v-stepper-step>
<v-divider></v-divider>
<v-stepper-step step="2" :complete="step > 2">Your Address</v-stepper-step>
<v-divider></v-divider>
<v-stepper-step step="3">Misc Info</v-stepper-step>
</v-stepper-header>
<v-stepper-items>
<v-stepper-content step="1">
<v-text-field label="Name" v-model="registration.name" required></v-text-field>
<v-text-field label="Email" v-model="registration.email" required></v-text-field>
<v-btn color="primary" #click.native="step = 2">Continue</v-btn>
</v-stepper-content>
<v-stepper-content step="2">
<v-text-field label="Street" v-model="registration.street" required></v-text-field>
<v-text-field label="City" v-model="registration.city" required></v-text-field>
<v-text-field label="State" v-model="registration.state" required></v-text-field>
<v-btn flat #click.native="step = 1">Previous</v-btn>
<v-btn color="primary" #click.native="step = 3">Continue</v-btn>
</v-stepper-content>
<v-stepper-content step="3">
<v-text-field label="Number of Tickets" type="number"
v-model="registration.numtickets" required></v-text-field>
<v-select label="Shirt Size" v-model="registration.shirtsize"
:items="sizes" required></v-select>
<v-btn flat #click.native="step = 2">Previous</v-btn>
<v-btn color="primary" #click.prevent="submit">Save</v-btn>
</v-stepper-content>
</v-stepper-items>
</v-stepper>
</v-app>
</div>
const defaultReg = Object.freeze({
name:null,
email:null,
street:null,
city:null,
state:null,
numtickets:0,
shirtsize:'XL'
});
new Vue({
el: '#app',
vuetify: new Vuetify(),
data () {
return {
step:1,
registration: Object.assign({}, defaultReg),
sizes:['S','M','L','XL']
}
},
methods:{
submit() {
this.registration = Object.assign({}, defaultReg);
this.step = 1;
}
}
})

A simpler approach at resetting your stepper is by using the key prop assigning to it a value and then in the function increasing this value. Something like this:
<template>
<v-stepper
:key="stepperKey"
v-model="e1"
>
...
</v-stepper>
</template>
<script>
export default {
data () {
return {
e1: 1,
stepperKey: 0
}
},
methods: {
increaseKey () { this.stepperKey++ }
}
}
</script>
The key prop or attribute is a build in Vue.js feature. Even if you don't see it it's been used on the back. Changing the key will trigger a re render.
If you have doubt about the key attribute/prop here is a nice article about it

Related

Modify drop down value with preset value

I'm designing a form that can both used to create and edit something.
The form has a dropdown, which isn't initialized when created, but is set with a value when used for editing.
I want to be able to modify the value of the drop down, both for creating & updating, yet is only working when the mode is CREATE.
Here's my template:
<template>
<v-row justify="center">
<v-form ref="form" v-model="valid" lazy-validation>
<v-text-field v-model="title" label="Title*" :rules="rules.fieldRules" prepend-icon="mdi-text">
</v-text-field>
<v-text-field v-model="website_link" label="URL" prepend-icon="mdi-web">
</v-text-field>
<h3>Description</h3>
<text-editor #update:modelValue="getValue" :rules="rules.fieldRules" :modelValue="description">
</text-editor>
<br />
<v-select v-model="selectedState" :readonly="false" :items="items" filled label="Which state?*" prepend-icon="mdi-help"></v-select>
<v-file-input v-model="files" prepend-icon="mdi-camera" multiple label="File input"></v-file-input>
<v-layout v-for="file of files" :key="file">
<v-img :src="generateUrl(file)" max-width="10%" max-height="10%">
</v-img>
</v-layout>
<v-combobox v-model="tags" prepend-icon="mdi-lightbulb" label="Tags" chips clearable multiple filled
rounded></v-combobox>
<v-btn :disabled="mode == 'EDIT' ? false : !valid" color="success" class="mr-4" #click="validate">
Validate
</v-btn>
<v-btn color="blue" class="mr-4" #click="backToProfile">
Back
</v-btn>
</v-form>
</v-row>
</template>
selectedState is a computed method described as below here:
selectedState: {
get() {
if (this.mode == 'CREATE') {
return this.state
} else {
const state = this.items.filter((item) => item.value = this.currentConcept.state)[0].title;
this.setState(state);
return this.state;
}
},
set(value) {
console.log(`value: ${value}`)
this.state = value;
}
}
Am I missing something?
TIA

Dynamic calculation using Vuetify

I'm trying to create dynamic calculator using Vuetify. Here's my code
<v-row class="mt-8 align-self-center">
<v-col cols="2">
<v-text-field :value="weight" label="Weight (kg)" placeholder="Type here" filled rounded></v-text-field>
</v-col>
<v-col cols="2">
<v-text-field :value="distance" label="Distance (km)" placeholder="Type here" filled rounded></v-text-field>
</v-col>
</v-row>
<v-card v-model="result" height="100" width="500">
Estimated shipping cost is: {{result}}
</v-card>
and here's my script
export default {
data() {
return {
inputDistance: '',
inputWeight: '',
result: ''
}
},
computed: {
result: function(){
var totalCost = this.inputDistance * this.inputWeight *2000;
return totalCost;
}
}
}
I have tried using v-model too but it still doesn't work. Any idea on what I suppose to write?
Thanks!
replace :value with v-model in your v-text-field, use the variable names and then remove v-model from v-card.
<v-row class="mt-8 align-self-center">
<v-col cols="2">
<v-text-field v-model="inputWeight" label="Weight (kg)" placeholder="Type here" filled rounded></v-text-field>
</v-col>
<v-col cols="2">
<v-text-field v-model="inputDistance" label="Distance (km)" placeholder="Type here" filled rounded></v-text-field>
</v-col>
</v-row>
<v-card height="100" width="500">
Estimated shipping cost is: {{result}}
</v-card>
and then use parseFloat in computed
export default {
data() {
return {
inputDistance: '',
inputWeight: '',
/** removed result variable **/
}
},
computed: {
result: function(){
var totalCost = parseFloat(this.inputDistance, 10) * parseFloat(this.inputWeight,10) *2000;
return totalCost;
}
}
}

Can you please help me with my on step behind issue in my vue code?

I got a question about my vue code I'm making a filter dropdown but when I input a key to trigger the key down event for filtering the arr it's changing the dom each time after the second event (one step behind).
Here is the code pen :
https://codepen.io/dyonvangerwen/pen/zYvjMdY
it's only keeping the values in the arr that are matching the input
template:
<div id="app">
<v-app id="inspire">
<v-form>
<v-container>
<v-row>
<v-col cols="12" sm="6" md="3">
<v-text-field
v-model="inputValue"
label="Filled"
placeholder="Placeholder"
filled
v-on:keydown="tester"
></v-text-field>
<v-card
class="mx-auto"
max-width="400"
tile
>
<v-list-ite >
<v-list-item-content v-for=" item in itemsInDropdown" :key="item">
<v-list-item-title>{{item}}</v-list-item-title>
</v-list-item-content>
</v-list-ite>
</v-card>
</v-col>
</v-row>
</v-container>
</v-form>
</v-app>
</div>
script:
new Vue({
el: '#app',
vuetify: new Vuetify(),
data: () => ({
inputValue:'',
itemsInDropdown:['a','b','c','d','e','ab','cd','ea']
}),
methods:{
tester:function(){
this.itemsInDropdown = this.itemsInDropdown.filter((x)=>{
if(x.includes(this.inputValue)){
return true
}
else{return false}
})
}
}
})
It is better to use computed in this case:
Replace the method with this:
computed:{
itemsInDropdownFiltered:function(){
return this.itemsInDropdown.filter((x)=>{
return x.includes(this.inputValue);
});
}
}
Change the array to be rendered from itemsInDropdown to itemsInDropdownFiltered as follows:
<v-list-item-content v-for="item in itemsInDropdownFiltered" :key="item">

How to unit test a variable in vue and vuetify with jest?

This might be pretty simple.
I have a component that renders a receive a message via props and renders it in a v-card-text. It doesn't do that in an optimal way, the whole v-if is messy, but it works.
<template>
<!-- Needed to be rendered big -->
<div v-if="start == true" class="ma-0">
<v-card class="text-xs-right" dark color="rgb(0,140,69)" height="50" width="1060" >
<v-btn dark text icon #click= "isOpen = !isOpen;" color="rgb(0,140,69)" >
<v-icon dark>fullscreen</v-icon>
</v-btn>
<v-btn class="mx-2" icon dark small color="rgb(0,140,69)">
<v-icon dark>thumb_up</v-icon>
</v-btn>
</v-card>
<v-card v-model='text' color="" height="200" width="1060">
<v-card-text ref="tcardbig" color="rgb(0,140,69)" style="color:rgb(0,140,69);display:flex;height:100%;justify-content:center;" class="display-2 font-weight-black align-center"> {{text}}</v-card-text>
</v-card>
</div>
<!-- Needed to be rendered small -->
<div v-else class="ma-2">
<v-card class="text-xs-right" dark color="rgb(0,140,69)" height="50" width="500" >
<v-btn dark text icon #click= "isOpen = !isOpen;" color="rgb(0,140,69)" >
<v-icon dark>fullscreen</v-icon>
</v-btn>
<v-btn class="mx-2" icon dark small color="rgb(0,140,69)">
<v-icon dark>thumb_up</v-icon>
</v-btn>
</v-card>
<v-card v-model='text' color="" height="350" width="500">
<v-card-text ref="tcardsmall" color="rgb(0,140,69)" style="color:rgb(0,140,69);display:flex;height:100%;justify-content:center;" class="display-2 font-weight-black align-center"> {{text}}</v-card-text>
</v-card>
</div>
</template>
<script>
export default {
data(){
return {
text: 'lorem ipsum',
start: true
}
},
props: ['textProps', 'startProps'],
mounted(){
this.text = this.textProps
this.start = this.startProps
}
}
</script>
I'm trying to unit test it with jest. How do I check if the text is properly rendered?
In other how I check the {{text}} in the OR how I check if the text variable of the component has the value I sent via prop. What am I doing wrong?
import {createLocalVue, mount} from '#vue/test-utils'
import textCard from './textCard.vue'
import Vue from 'vue'
import Vuetify from 'vuetify'
Vue.use(Vuetify)
const localVue = createLocalVue()
describe('textCard.vue', () => {
const wrapper = mount(textCard,
{
localVue,
vuetify,
propsData: {
text: 'Random Text',
start: false
},
}
)
it('renders a vue instance', () => {
expect(mount(textCard).isVueInstance()).toBe(true);
});
const content = wrapper.find({ ref: 'tcardsmall' })
it('Checks the if the variable text is correct', () => {
expect(content.selector).toMatch('Random Text')
})
}
)

How can I get country code on vue tel input?

My component
<v-form>
<v-container>
<v-row>
<v-col cols="12" sm="6" md="3">
<vue-tel-input v-model="phone"></vue-tel-input>
</v-col>
</v-row>
</v-container>
<v-btn
color="success"
#click="submit"
>
submit
</v-btn>
</v-form>
When I click submit, I just get phone. How can I get country code too?
[Reference] https://www.npmjs.com/package/vue-tel-input-vuetify
[Codepen] https://codepen.io/positivethinking639/pen/YzzjzWK?&editable=true&editors=101
It seems like vue-tel-input provides a country-changed event. According to the docs it's even fired for the first time and it returns an object:
Object {
areaCodes: null,
dialCode: "31",
iso2: "NL",
name: "Netherlands (Nederland)",
priority: 0
}
So this event handler can be added to the component and the country code can be stored in the component as you already do for the phone value.
HTML part
<div id="app">
<v-app id="inspire">
<v-form>
<v-container>
<v-row>
<v-col cols="12" sm="6" md="3">
<vue-tel-input v-model="phone" v-on:country-changed="countryChanged"></vue-tel-input>
</v-col>
</v-row>
</v-container>
<v-btn
color="success"
#click="submit"
>
submit
</v-btn>
</v-form>
</v-app>
</div>
JS Part
new Vue({
el: '#app',
vuetify: new Vuetify(),
data() {
return {
phone: null,
country: null
}
},
methods: {
countryChanged(country) {
this.country = country.dialCode
},
submit() {
console.log(this.phone);
console.log(this.country);
}
}
});
Here you can see a working version:
https://codepen.io/otuzel/pen/PooBoQW?editors=1011
NOTE: I don't use Vue on daily basis so I am not sure if this the best practice to modify the data via the event handler.
<vue-tel-input v-model="phone" v-bind="bindProps"></vue-tel-input>
data() {
return {
phone: null,
bindProps:{
mode: 'international'
}
}
}
It's achievable in vue-tel-input#3.1.1 by setting prop mode: 'international', in this case, the phone number will always be converted to +123 123 123...