I've looked through all the posts about this subject and can't seem to find an answer. My Vuex store IS updating fine, but the DOM is not.
This is a screenshot of what is going on
I have a getter called returnAmazonCredentials
returnAmazonCredentials(state) {
return state.amazonCredentials
},
I import it like this:
computed: {
...mapGetters('amazonCredentials', [
'returnAmazonCredentials',
]),
returnAmazonCredentials is an array and so I use it in my DOM with a v-for
v-for="(cred, index) in returnAmazonCredentials"
And I also use getters and setters to update the elements in the array. Here is one example
sellerId: {
get() {
return this.returnAmazonCredentials.merchant_id
},
set(value) {
this.$set(this.returnAmazonCredentials[this.credIndex], 'merchant_id', value)
}
},
this.credIndex is set when an element is clicked
When I want to remove an element from the returnAmazonCredentials array I do this:
this.returnAmazonCredentials.splice(index, 1)
The Vuex store is updated perfectly, while the DOM still shows old data that no longer exists in the store. I've tried:
this.$nextTick() as well as this.$forceUpdate()
No luck.. Where did I go astray?
EDIT: This is all my code in my component
<template>
<v-container fluid v-resize="getHeight">
<v-row align="center" justify="center">
<v-col cols="12">
<v-card
class="purple_top"
color="#e1bee7"
>
<v-container>
<v-row>
<v-col cols="1" align="start">
<v-icon class="my_dark_purple_text pretty_icon mt-2" x-large>info</v-icon>
</v-col>
<v-col cols="11" align="start">
<h1 class="text-h6 mont bold pt-3 pb-2">You will not be charged until after you've entered all your credentials below</h1>
<h1 class="text-subtitle-1 mont font-weight-bold">After your 7 day free trial your costs will be:</h1>
<v-list class="purple_list" dense>
<v-list-item>
<v-list-item-icon class="mr-2">
<v-icon class="my_dark_purple_text">info</v-icon>
</v-list-item-icon>
<v-list-item-content>
<div class="text-body-1 mont">$25/month for the first marketplace</div>
</v-list-item-content>
</v-list-item>
<v-list-item>
<v-list-item-icon class="mr-2">
<v-icon class="my_dark_purple_text">info</v-icon>
</v-list-item-icon>
<v-list-item-content>
<div class="text-body-1 mont">$20/month for each additional marketplace</div>
</v-list-item-content>
</v-list-item>
</v-list>
</v-col>
</v-row>
</v-container>
</v-card>
</v-col>
</v-row>
<v-row>
<v-col cols="8">
<v-card
color="#f1e7df"
id="devIds"
>
<v-card-title>
<v-icon class="my_dark_purple_text">vpn_key</v-icon>
<h1 class="text-h6 oswald my_dark_purple_text pl-2">DEVELOPMENT IDS</h1>
</v-card-title>
<v-container>
<v-row>
<v-col cols="6" class="ml-10">
<h1 class="text-h6 mont">US, Canada, Mexico</h1>
</v-col>
<v-col cols="5">
<h1 class="text-h6 mont">UK and the EU</h1>
</v-col>
</v-row>
<v-row>
<v-col cols="3" class="ml-10">
<v-text-field readonly solo :value="us" class="mont"></v-text-field>
</v-col>
<v-col cols="3">
<v-btn height="48px" class="my_dark_purple_btn ml-n7" #click="copyCreds(us)">Copy</v-btn>
</v-col>
<v-col cols="3" class="">
<v-text-field readonly solo :value="eu" class="mont"></v-text-field>
</v-col>
<v-col cols="2">
<v-btn height="48px" class="my_dark_purple_btn ml-n7" #click="copyCreds(eu)">Copy</v-btn>
</v-col>
</v-row>
<v-row>
<v-col cols="6" class="ml-10">
<h1 class="text-h6 mont">Australia</h1>
</v-col>
<v-col cols="5">
<h1 class="text-h6 mont">Japan</h1>
</v-col>
</v-row>
<v-row>
<v-col cols="3" class="ml-10">
<v-text-field readonly solo :value="us" class="mont"></v-text-field>
</v-col>
<v-col cols="3">
<v-btn height="48px" class="my_dark_purple_btn ml-n7" #click="copyCreds(australia)">Copy</v-btn>
</v-col>
<v-col cols="3" class="">
<v-text-field readonly solo :value="eu" class="mont"></v-text-field>
</v-col>
<v-col cols="2">
<v-btn height="48px" class="my_dark_purple_btn ml-n7" #click="copyCreds(japan)">Copy</v-btn>
</v-col>
</v-row>
</v-container>
</v-card>
</v-col>
<v-col cols="4">
<v-card
color="#d9d6e1"
:height="matchingHeights + 'px'"
>
<v-container fluid fill-height>
<v-row class="pt-2">
<v-col cols="12" justify="center" align="center">
<a href="https://youtu.be/-iWlFyX0254" target="_blank">
<v-img
src="how.png"
max-width="153px"
contain
></v-img>
</a>
</v-col>
</v-row>
<v-row>
<v-col cols="12">
<h1 class="mont text-h5 text-center">Do I retrieve my US Amazon credentials?</h1>
</v-col>
</v-row>
<v-row>
<v-divider class="mx-4"></v-divider>
</v-row>
<v-row class="pt-2">
<v-col cols="12" justify="center" align="center">
<a href="https://youtu.be/p4RwqegRc9s" target="_blank">
<v-img
src="how.png"
max-width="153px"
contain
></v-img>
</a>
</v-col>
</v-row>
<v-row>
<v-col cols="12">
<h1 class="mont text-h5 text-center">Do I retrieve my Amazon credentials outside of the US?</h1>
</v-col>
</v-row>
</v-container>
</v-card>
</v-col>
</v-row>
<p>credentials are {{ returnAmazonCredentials }}</p>
<v-row
v-for="(cred, index) in returnAmazonCredentials"
:key="index"
>
<v-col cols="12">
<v-card
color="#e9daea"
>
<v-card-title>
<v-icon class="my_dark_purple_text">language</v-icon>
<h1 class="text-h6 oswald my_dark_purple_text pl-2">ENTER YOUR AMAZON CREDENTIALS BELOW</h1>
</v-card-title>
<v-container>
<v-form>
<v-row>
<v-col cols="6">
<v-row>
<v-col cols="12">
<v-text-field
color="#6a0080"
label="Amazon Seller Id"
prepend-icon="person"
v-model="sellerId"
#click="setIndex(index)"
:rules="[() => !!returnAmazonCredentials[credIndex]['merchant_id'] || 'Please provide your Amazon seller id', sellerIdValidation(!!returnAmazonCredentials[credIndex]['merchant_id']) ]"
></v-text-field>
</v-col>
</v-row>
<v-row>
<v-col cols="12">
<v-select
:items="marketplaces"
label="Select your Amazon Marketplace"
color="#6a0080"
prepend-icon="map"
v-model="marketplace"
#click="setIndex(index)"
:rules="[() => !!returnAmazonCredentials[credIndex]['marketplace'] || 'Please select your Amazon marketplace', marketValidation(!!returnAmazonCredentials[credIndex]['marketplace']) ]"
></v-select>
</v-col>
</v-row>
<v-row>
<v-col cols="12">
<v-text-field
color="#6a0080"
label="Amazon Auth Token"
prepend-icon="https"
v-model="authToken"
#click="setIndex(index)"
:rules="[() => !!returnAmazonCredentials[credIndex]['auth_token'] || 'Please provide your Amazon auth token', authTokenValidation(!!returnAmazonCredentials[credIndex]['auth_token']) ]"
></v-text-field>
</v-col>
</v-row>
</v-col>
<v-col cols="1">
<v-divider vertical></v-divider>
</v-col>
<v-col cols="5">
<v-row class="mt-1">
<v-btn
color="#68007d"
outlined
block
x-large
:disabled="_.some(errors, (element) => _.includes(element, index))"
#click="saveMarketplace"
:loading="saveLoading"
>
<v-icon
left
>
check_circle
</v-icon>
SAVE THIS MARKETPLACE
</v-btn>
</v-row>
<v-row class="mt-11">
<v-btn
block
x-large
outlined
color="#388E3C"
#click="addMarketplace"
>
<v-icon
left
>
add_circle
</v-icon>
ADD ANOTHER MARKETPLACE
</v-btn>
</v-row>
<v-row class="mt-11">
<v-btn
block
x-large
outlined
color="#B71C1C"
:disabled="returnAmazonCredentials.length == 1"
#click="removeMarketplace(index)"
>
<v-icon
left
>
remove_circle
</v-icon>
REMOVE MARKETPLACE
</v-btn>
</v-row>
</v-col>
</v-row>
</v-form>
<v-row v-if="(returnAmazonCredentials.length - 1) == index">
<v-col cols="12">
<v-btn
class="white--text"
color="#68007d"
block
x-large
#click="sendCreds"
:loading="finishedLoading"
:disabled="errors.length > 0"
id="custom-disabled"
>
FINISHED
</v-btn>
</v-col>
</v-row>
</v-container>
</v-card>
</v-col>
</v-row>
<v-dialog
v-model="failDialog"
max-width="600px"
persistent
>
<v-card>
<v-card-title>
<span class="title font-weight-bold">Oh snap! It looks like your credentials are incorrect</span>
</v-card-title>
<v-card-text>
<v-row>
<v-col cols="12">
<h1
class="subtitle-1"
style="color: black !important;"
>Amazon let us know the following error:</h1>
</v-col>
</v-row>
<v-row
:class="spacing"
v-for="(reason, index) in failReasons"
:key="reason.marketplace"
>
<v-col cols="12">
<h1
class="subtitle-1"
>Your credentials failed in this marketplace: <strong>{{ reason.marketplace }}</strong></h1>
</v-col>
<v-col cols="12" class="mt-n5">
<h1
class="subtitle-1"
>For this reason: <strong>{{ reason.reason }}</strong></h1>
</v-col>
<v-col
cols="12"
justify="center"
align="center"
>
<a :href="whichVideoToShow(reason.marketplace)" target="_blank">
<v-img
src="blank_how.png"
max-width="100px"
contain
></v-img>
</a>
</v-col>
<v-col cols="12" class="mt-n5">
<h1 class="subtitle-1 text-center">Do I retrieve my Amazon credentials?</h1>
</v-col>
<v-divider class="mx-4 mt-3"></v-divider>
</v-row>
</v-card-text>
<v-card-actions class="">
<v-spacer></v-spacer>
<v-btn color="#68007d" large class="white--text" #click="closeDialog">I UNDERSTAND</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</v-container>
</template>
<script>
import axios from 'axios';
import { mapGetters, mapActions } from 'vuex'
export default {
data: function() {
return {
failDialog: false,
australia: "6078-0648-3237",
us: "7531-9706-4825",
eu: "4048-6340-0484",
japan: "1447-5438-8862",
matchingHeights: 295,
marketplaces:[
{ text: 'Australia', value: "A39IBJ37TRP1C6" },
{ text: 'Canada', value: "A2EUQ1WTGCTBG2" },
{ text: 'France', value: "A13V1IB3VIYZZH" },
{ text: 'Germany', value: "A1PA6795UKMFR9" },
{ text: 'Italy', value: "APJ6JRA9NG5V4" },
{ text: 'Japan', value: "A1VC38T7YXB528" },
{ text: 'Mexico', value: "A1AM78C64UM0Y8" },
{ text: 'Spain', value: "A1RKKUPIHCS9HS" },
{ text: 'United Kingdom', value: "A1F83G8C2ARO7P" },
{ text: 'United States', value: "ATVPDKIKX0DER" },
],
credIndex: 0,
errors: [],
finishedLoading: false,
saveLoading: false,
amazonError: '',
failReasons: [],
};
},
async mounted() {
await this.getRemoteAmazonCredentials()
},
computed: {
...mapGetters('amazonCredentials', [
'returnAmazonCredentials',
]),
sellerId: {
get() {
return this.returnAmazonCredentials.merchant_id
},
set(value) {
this.$set(this.returnAmazonCredentials[this.credIndex], 'merchant_id', value)
}
},
marketplace: {
get() {
return this.returnAmazonCredentials.marketplace
},
set(value) {
this.$set(this.returnAmazonCredentials[this.credIndex], 'marketplace', value)
}
},
authToken: {
get() {
return this.returnAmazonCredentials.auth_token
},
set(value) {
this.$set(this.returnAmazonCredentials[this.credIndex], 'auth_token', value)
}
}
},
methods: {
...mapActions('amazonCredentials', [
'getRemoteAmazonCredentials',
'testRemoteAmazonCredentials',
'removeAmazonCredential'
]),
setIndex(index) {
this.credIndex = index
},
getHeight() {
var devCard = document.getElementById("devIds");
this.matchingHeights = devCard.offsetHeight;
},
copyCreds(country) {
this.$clipboard(country);
},
sellerIdValidation(value) {
if(value){
_.pull(this.errors, `${this.credIndex}-id`)
}
else {
if(!_.includes(this.errors, `${this.credIndex}-id`)) {
this.errors.push(`${this.credIndex}-id`)
}
}
return true
},
marketValidation(value) {
if(value){
_.pull(this.errors, `${this.credIndex}-market`)
}
else {
if(!_.includes(this.errors, `${this.credIndex}-market`)) {
this.errors.push(`${this.credIndex}-market`)
}
}
return true
},
authTokenValidation(value) {
if(value){
_.pull(this.errors, `${this.credIndex}-auth`)
}
else {
if(!_.includes(this.errors, `${this.credIndex}-auth`)) {
this.errors.push(`${this.credIndex}-auth`)
}
}
return true
},
addMarketplace() {
this.returnAmazonCredentials.push({})
},
removeMarketplace(index) {
this.removeAmazonCredential(index)
this.credIndex = 0
},
async sendCreds() {
this.failReasons = []
this.finishedLoading = true
let me = this.returnAmazonCredentials
let response = await this.testRemoteAmazonCredentials()
this.addRemoveTestFailure(response)
},
async saveMarketplace() {
this.failReasons = []
this.saveLoading = true
let response = await this.testRemoteAmazonCredentials()
this.addRemoveTestFailure(response)
},
addRemoveTestFailure(response) {
response.forEach(element => {
if(element.result == "fail") {
this.failDialog = true
let failure = {
reason: element.reason,
marketplace: element.marketplace
}
this.failReasons.push(failure)
}
})
this.saveLoading = false
this.finishedLoading = false
},
closeDialog() {
this.failDialog = false
this.saveLoading = false
},
whichVideoToShow(marketplace) {
if(marketplace == "United States" || marketplace == "Mexico" || marketplace == "Canada") {
return 'https://youtu.be/-iWlFyX0254'
}
else {
return 'https://youtu.be/p4RwqegRc9s'
}
},
spacing() {
if(this.failReasons.length >= 1) {
return mt-n4
}
}
}
};
</script>
<style scoped>
#import '../../styles/global_styles.css';
#custom-disabled.v-btn--disabled {
background-color: rgba(104,0,125,.5) !important;
color: white !important;
}
</style>
I did add this mutation in my store to remove the element
removeCredential: (state, payload) => {
state.amazonCredentials.splice(payload, 1)
},
And this is the method that I've updated in the component itself:
removeMarketplace(index) {
this.removeAmazonCredential(index)
this.credIndex = 0
},
Where I send the index to be removed from the credentials array.
But yea I was already doing that in the component itself, and I'm getting the same effect. Data updated while the DOM is not..
You should dispatch an action that remove that item :
sellerId: {
get() {
return this.returnAmazonCredentials.merchant_id
},
set(value) {
this.$store.dispatch('removeCredential',this.credIndex)
}
},
store :
mutations: {
REMOVE_CREDENTIAL (state,index) {
state.amazonCredentials.splice(index, 1)
}
},
actions: {
removeCredential(context,index) {
context.commit('REMOVE_CREDENTIAL',index)
}
Wow, the answer surprises me. Its basically that if you have an array of objects in your Vuex store, you should NOT use getters / setters if you ALSO are stepping over that array in a v-for instead you can just get / set the values directly.
For example. If you do this:
<v-row
v-for="(cred, index) in myVuexStoreArrayOfObjects"
:key="index"
>
Then you should do this for your v-model
<v-text-field
v-model="cred.value"
></v-text-field>
So that finally you can remove an object from that array and maintain your reactivity. Like so:
removeObjectFromMyVuexStoreArray(index) {
this.myVuexStoreArrayOfObjects.splice(index, 1)
},
And there is no need to get/set. In fact if you get/set you will NOT be able to remove an item and remain reactive.
I am creating my first website with Vue so I am creating a website for saving recipes I have a home page where you click to add new recipes and it takes you to a page where you can write your recipes and it will save on the home page kind of like a ( to do list ), so I am having troubles with saving the data that the user inputs. how can I get back the saved data from getters? ps. I know this is very simple but I am new to Vue
here are my codes (newrecp page) :
<template>
<div class="container">
<v-text-field
class="mx-1 my-1"
label=" food name"
color="black"
outlined
v-model="data . title"
></v-text-field>
<v-timeline :dense=" $vuetify . breakpoint . s m And Down">
<v-timeline-item
color="purple lighten-2"
fill-dot
right
>
<v-card>
<v-card-title class="purple lighten-2">
<h2 class="display-1 white--text font-weight-light">Step 1</h2>
</v-card-title>
<v-container>
<v-row>
<v-col cols="12" md="10">
<v-text area
auto-grow
rows="4"
row-height="20"
shaped
v-model="data.one"
></v-text area>
</v-col>
</v-row>
</v-container>
</v-card>
</v-timeline-item>
<v-timeline-item
color="amber lighten-1"
fill-dot
left
small
>
<v-card>
<v-card-title class="amber lighten-1 justify-end">
<h2 class="display-1 mr-4 white--text font-weight-light">Step 2</h2>
</v-card-title>
<v-container>
<v-row>
<v-col cols="12" md="8">
<v-text area
auto-grow
rows="4"
row-height="20"
shaped
v-model="data. two"
></v-text area>
</v-col>
</v-row>
</v-container>
</v-card>
</v-timeline-item>
<v-timeline-item
color="cyan lighten-1"
fill-dot
right
>
<v-card>
<v-card-title class="cyan lighten-1">
<h2 class="display-1 white--text font-weight-light">Step 3</h2>
</v-card-title>
<v-container>
<v-row>
<v-col >
<v-text area
auto-grow
rows="4"
row-height="20"
shaped
v-model="data .three"
></v-text area>
</v-col>
</v-row>
</v-container>
</v-card>
</v-timeline-item>
<v-timeline-item
color="red lighten-1"
fill-dot
left
small
>
<v-card>
<v-card-title class="red lighten-1 justify-end">
<h2 class="display-1 mr-4 white--text font-weight-light">Step 4</h2>
</v-card-title>
<v-container>
<v-row>
<v-col cols="12" md="10">
<v-text area
auto-grow
rows="4"
row-height="20"
shaped
v-model="data .four"
></v-text area>
</v-col>
</v-row>
</v-container>
</v-card>
</v-timeline-item>
</v-timeline>
<v-layout row wrap>
<v-flex mx-3 >
<v-b t n block color="secondary" dark #click="addnew">Save</v-b t n>
</v-flex>
</v-layout>
</div>
</template>
<script>
export default {
data (){
return{
data: {
title:'',
one: '',
two: '',
three: '',
four: '',
}
},
methods: {
addnew(){
let savedrecp = this.data
this.$store.commit('newrecp', savedrecp)
this.$router.push({ path:'/' })
}},
}
</script>
In my store:
state: {
data : [],
},
mutations: {
newrecp(state, data) {
// mutate state
state. data .push(data)
}
},
getters: {
data(s){
return s .data
},
}
Script for my saved recipe page:
<script>
export default {
data (){
return{
data: {
title: '',
one: '',
two: '',
three: '',
four: ''
},
}
},
computed: {
item(){
return this. $store.getters.data
}
},
mounted() {
console.log(this. data);
},
}
</script>
Home page:
<template>
<div class="home">
<v-container grid-list-xs>
<v-btn bottom fixed to="/new" > Click to add new Recipes
<v-icon>fas fa-home</v-icon>
</v-btn>
<v-layout row wrap>
<v-flex xs12 x13 lg12 v-for="(item, index) in data" :key="index">
<v-card
>
<v-list-item three-line>
<v-list-item-content>
<div class="overline mb-4">Recipe </div>
<h1>{{item.title}}</h1>
<v-list-item-title class="headline mb-1">pizza</v-list-item-title>
<v-list-item-subtitle >Greyhound divisely hello coldly fonwderfully</v-list-item-subtitle>
</v-list-item-content>
</v-list-item>
<v-card-actions>
<v-btn class="button3" text>remove</v-btn>
<v-btn class="button1" text :to="'/savedrecp/'+item.title">open</v-btn>
</v-card-actions>
</v-card>
</v-flex>
</v-layout>
</v-container>
</div>
</template>
<script>
In general we use two-way bindings on form input, textarea, and select elements inorder to save input data you can read official document here.
regarding you'r code i don't see any problems in it unless there is something that you haven't shared right now you must be able to use you'r data like this:
savedRecipe() {
console.log(this.data) // => you can check you'r data in console.
}
UPDATE
You are trying to modify the vuex state from the vue component, You can not do it. You can only modify vuex store from a mutation.
In you'r store:
mutations: {
addRecipe(state, recipe) {
// mutate state
state.data.push(recipe)
}
and commit to mutation:
savedrecp(){
let savedrecp = this.data
this.$store.commit('addRecipe', savedrecp)
this.$router.push({ path:'/' })
}
I've been reading about text-fields but I can't figure it out.. I want to be able to type in a name and age, and then when I press the button "add", I want to be able to see the name and age displayed below. What is the easiest or best way of doing this?
My code:
<v-container>
<v-row>
<v-col cols="12" sm="6" md="3">
<v-text-field label="Name" solo></v-text-field>
</v-col>
<v-col cols="12" sm="6" md="3">
<v-text-field label="Age" solo></v-text-field>
</v-col>
<div class="addbutton">
<v-btn color="green darken-1" large v-on:click="add">Add</v-btn>
</div>
</v-row>
First you should bind inputs to the component data using v-model.
script:
export default {
data(){
return {
name: null,
age: null
}
}
}
html:
<v-col cols="12" sm="6" md="3">
<v-text-field label="Name" solo v-model="name"></v-text-field>
</v-col>
<v-col cols="12" sm="6" md="3">
<v-text-field label="Age" solo v-model="age"></v-text-field>
</v-col>
Now you can display current inputs values: <p>{{ name + ', ' + age }}</p>
If you want to show/hide them with a button, you can add a data property to store their state, create a method to toggle it and bind their visibility to the property using v-if:
script:
export default {
data(){
return {
name: null,
age: null,
showValues: false
},
methods: {
toggle() {
this.showValues = !this.showValues
}
}
}
html:
<v-row>
<v-col cols="12" sm="6" md="3">
<v-text-field label="Name" solo v-model="name"></v-text-field>
</v-col>
<v-col cols="12" sm="6" md="3">
<v-text-field label="Age" solo v-model="age"></v-text-field>
</v-col>
<div class="addbutton">
<v-btn color="green darken-1" large #click="toogle">Add</v-btn>
</div>
<p v-if="showValues">{{ name + ', ' + age }}</p>
</v-row>
Store the variables in the data of your vue component and the use it to render
<v-row>
<v-col cols="12" sm="6" md="3">
<v-text-field label="Name" solo></v-text-field>
</v-col>
<v-col cols="12" sm="6" md="3">
<v-text-field label="Age" solo></v-text-field>
</v-col>
<div class="addbutton">
<v-btn color="green darken-1" large v-on:click="add">Add</v-btn>
</div>
<v-col cols="12" sm="6" md="3" v-if="render!==null">
<p>{{ render.name }}</p>
<p>{{ render.age }}</p>
</v-row>
<script>
export default {
data(){
return {
name:null,
age:null,
render:null,
},
methods(){
add(){
const name = this.name;
const age = this.age;
this.render = {
name,
age
}
},
}
}
</script>
I've been trying to push a text field whenever the "add button" is pressed.
This is my code so far.
<v-container fluid>
<v-row>
<v-col cols="7">
<v-row class= "mx-1 my-1">
<v-text-field outlined label="Test 1" v-model="test1"></v-text-field>
</v-row>
</v-col>
<v-col cols="5">
<v-row class= "mx-4 my-1">
<v-text-field type="number" outlined label="Test 2" v-model="test2"></v-text-field>
</v-row>
</v-col>
</v-row>
<v-row>
<v-col cols="12">
<v-row class= "mx-1 my-n8">
<v-btn
#click="doWork()"
width = 100%
small
outlined
color="#0000b0"
>
<v-icon dark>mdi-plus</v-icon></v-btn>
</v-row>
</v-col>
</v-row>
</v-container>
Here is my javascript
<script>
export default {
data () {
return {
test1:'',
test2:''
}
},
methods: {
doWork () {
//just for debugging purposes
console.log(this.valor)
console.log(this.precio)
}
}
}
</script>
What should I add in the "doWork()" method in order to push another pair of text fields
Thanks in advance <3
You can transform your fields into a fields array:
data () {
return {
inputs: []
}
}
Your addWork method becomes a method that push a new value in this inputs array:
methods: {
doWork () {
this.inputs.push({
label: 'Test',
value: ''
})
}
}
And you display those inputs with a v-for directive:
<v-row>
<v-col cols="2" v-for="(input, index) in inputs" :key="index">
<v-row class="mx-1 my-1">
<v-text-field outlined :label="input.label" v-model="input.value"></v-text-field>
</v-row>
</v-col>
</v-row>
Working example: https://codesandbox.io/s/festive-dream-gbo6t?file=/src/App.vue
My code like this :
<v-row>
<v-col cols="12" sm="6" md="3">
<v-text-field
label="Phone"
outlined
dense
></v-text-field>
</v-col>
<v-col cols="12" sm="6" md="3">
<vue-tel-input v-model="phone"></vue-tel-input>
</v-col>
</v-row>
My codepen like this : https://codepen.io/positivethinking639/pen/qBBKYON?&editable=true&editors=101
I want to combine it to be like this :
The blue sign is taken from vue tel input. The text field next to it is taken from the vuetify component
How do I combine 2 different components into one like the image above?
Yes, it is possible to set the country code next to dropdown
Here is the working codepen: https://codepen.io/chansv/pen/pooZJey?editors=1010
<div id="app">
<v-app id="inspire">
<v-form>
<v-container>
<v-row>
<v-col cols="12" sm="6" md="3">
<v-text-field
label="Phone"
outlined
dense
></v-text-field>
</v-col>
<v-col cols="12" sm="6" md="3">
<vue-tel-input v-model="phone" #country-changed="countrySelected">
<template v-slot:arrow-icon>
<v-icon>arrow_drop_down</v-icon>
<strong>+{{countryCode}}</strong>
</template>
</vue-tel-input>
</v-col>
</v-row>
</v-container>
</v-form>
</v-app>
</div>
new Vue({
el: '#app',
vuetify: new Vuetify(),
data() {
return {
phone: null,
countryCode: null,
}
},
methods: {
countrySelected(val) {
this.countryCode = val.dialCode;
}
}
})