Inline Edit (how to render a vuetifiy component based on the condition) - vue.js

Haii can anyone help me. I'm looping a array I want to render a field based on the condition. which I loop in simple table.my problem is that I'm directly
comparing the index value (which is index === 0 and secondIndex === 0 ) like that it seems to be a hardcode. It could be dynamic. I couldn't able to get as a dynamic.Could Anyone help me.
<v-row v-for="(item, index) in list" :key="index" no-gutters>
<v-col cols="12" sm="12" lg="12" xl="12">
<v-card class="mt-2 rounded-xl" hover>
<v-card-title v-if="index === 0" #mouseover="mouseOver = true" #mouseleave="mouseOver = false">
</v-card-title>
<v-card-subtitle class="pb-5 mt-3">
<v-row class="ml-1 mt-1 text--primary">
<v-icon color="primary">{{item.icon}}</v-icon>
<div class="ml-1 text-button">{{item.name}}</div>
</v-row>
<v-file-input style="display: none" ref="file" accept="image/*" v-model="systemAndTenantConfig.systemconfiguration.logo" #change="uploadProfile()"></v-file-input>
</v-card-subtitle>
<v-card-text>
<v-form ref="configReference">
<div class="ml-9">
<tr>
<v-simple-table align="justify" style="text-align:justify" v-for="(record, secondIndex) in item.tableValue" :key="secondIndex">
<v-hover v-slot:default="{ hover }">
<tr>
<th style="width:160px">{{record.label}}</th>
<td>
<p v-if="indexValue === index && secondIndexValue === secondIndex ? showText: true">{{record.value}}</p>
<v-col cols="12" md="12" lg="12" xl="12" v-if=" index === 0 && secondIndex === 0 && indexValue === index && secondIndexValue === secondIndex ? show : false">
<v-text-field dense hide-details outlined :rules="systemAndTenantConfig.systemconfiguration.email ? $_emailValidation : []" :label="$t('email')" v-model="systemAndTenantConfig.systemconfiguration.email"></v-text-field>
</v-col>
<v-col cols="12" lg="12" v-if="index === 0 && secondIndex === 1 && indexValue === index && secondIndexValue === secondIndex ? show : false">
<v-autocomplete dense hide-details outlined :label="$t('timezone')" v-model="systemAndTenantConfig.systemconfiguration.timezone" :items="listOfTimeZones" item-text="displayname" item-value="standardname"></v-autocomplete>
</v-col>
</v-col>
<v-col cols="12" lg="12" v-if="index === 0 && secondIndex === 2 && indexValue === index && secondIndexValue === secondIndex ? show : false">
<v-textarea dense hide-details outlined :label="$t('companyAddress')" v-model="systemAndTenantConfig.systemconfiguration.companyaddress"></v-textarea>
</v-col></td><td>
<v-expand-transition>
<v-layout justify-end v-if="hover">
<v-fade-transition>
<td>
<v-btn text x-small icon color="info" v-if="showEdit">
<v-icon style="float:right" small #click="getSingleRecord(index, secondIndex)" color="primary">{{record.icon}}</v-icon>
</v-btn>
</td>
</v-fade-transition>
</v-layout>
</v-expand-transition>
</td>
</tr>
</v-row>
list: [
{
name: this.$t('general'),
icon: 'mdi-folder-multiple-outline',
tableValue: [
{
label: 'Email',
value: this.systemAndTenantConfig.systemconfiguration.email,
icon: 'mdi-pencil',
name: 'email'
},
{
label: 'Phone',
value: this.systemAndTenantConfig.systemconfiguration.phone,
icon: 'mdi-pencil',
name: 'phone'
},
{
label: 'Company Address',
value: this.systemAndTenantConfig.systemconfiguration.companyaddress,
icon: 'mdi-pencil',
name: 'address'
}
]
}]
indexValue: ''
secondIndexValue: ''
getSingleRecord (firstIndex, secondIndex) {
this.indexValue = firstIndex
this.secondIndexValue = secondIndex
}

Related

how can i call objects in a row using vuetify?

I am a vuejs newbie and i am having difficulties trying to make my objects return back in a row they are in a column.
components/sellingItems.vue
<template>
<v-container class="my-5">
<v-row>
<v-col
sm="6"
md="4"
>
<v-card outlined>
<v-img :src="image" height="200px" />
<v-card-title> {{ name}} </v-card-title>
<v-card-subtitle> ${{ price }}</v-card-subtitle>
<v-card-actions>
<v-btn #click="addToCart" color="success" outlined >
<v-icon small left> add </v-icon>
Add to Cart
</v-btn>
</v-card-actions>
</v-card>
</v-col>
</v-row>
</v-container>
</template>
<script>
export default {
props: ['id', 'image', 'name', 'price'],
}
</script>
pages/index.vue
After adding the for loop my products list turns into a column, i prefer it in a row to suit my aim
The Index Page
Stack overflow wont let me post the index page code so heres a screenshot
Check this
use a row and columns by editing your class to determine how many items per row I have added code in codepen
https://codepen.io/Juan-Carlos-MA/pen/yLMdLRX?editors=1010
<div id="app">
<v-app id="inspire">
<br>
<br>
<v-slider
v-model="fruits"
:tick-labels="ticksLabels"
:max="3"
step="1"
ticks="always"
tick-size="4"
></v-slider>
<div class="row">
<div v-for="item in items" :class="selection">
<v-card :loading="loading" class="mx-auto my-12" max-width="374">
<template slot="progress">
<v-progress-linear color="deep-purple" height="10" indeterminate></v-progress-linear>
</template>
<v-img height="250" src="https://cdn.vuetifyjs.com/images/cards/cooking.png"></v-img>
<v-card-title>{{ item.mensaje }}</v-card-title>
<v-divider class="mx-4"></v-divider>
<v-card-title>{{ item.precio }}</v-card-title>
<v-card-actions>
<v-btn color="deep-purple lighten-2" text #click="reserve">
Add TO CART
</v-btn>
</v-card-actions>
</v-card>
</div>
</div>
</v-app>
</div>
new Vue({
el: "#app",
vuetify: new Vuetify(),
data: () => ({
loading: false,
selection: "col-6",
value: 0,
fruits: 1,
ticksLabels: ["one", "two", "tree", "four"],
items: [
{ mensaje: "Tamales", precio: "$300" },
{ mensaje: "Atole", precio: "$300" },
{ mensaje: "Taquito", precio: "$300" },
{ mensaje: "Taquito", precio: "$300" }
]
}),
methods: {
reserve() {
this.loading = true;
setTimeout(() => (this.loading = false), 2000);
}
},
watch: {
fruits: function (val) {
console.log(val);
if (val == 0) {
this.selection = "col-12";
} else {
if (val == 1) {
this.selection = "col-6";
} else {
if (val == 2) {
this.selection = "col-4";
} else {
if (val == 3) {
this.selection = "col-3";
}
}
}
}
}
}
});
Thew problem seems to be that you are creating a new row vor every item
<template>
<v-container class="my-5">
<v-row> <!-- <=== here is your row -->
<v-col sm="6" md="4">
... etc
</v-col>
</v-row>
</v-container>
</template>
you can either move the <v-row> into the parent component and wrap <SellingItems v-for...> or pass an array (products) into the component and have the v-for within that component
<SellingItems :items="products" ... >
<template>
<v-container class="my-5">
<v-row>
<v-col sm="6" md="4" v-for="item in items"> <!-- <=== move v-for here -->
... etc
</v-col>
</v-row>
</v-container>
</template>

Passing props from parent component to child component on dialog box vue

So I want to bind batch_code data from dashboard.vue parent to review.vue child component
so, the dashboard contains details like the batch_code, then I have trouble passing the data to the review component, of which it will get the batch_code upon clicking the "Rate and Review" button
when I did try, I am just getting null values from returning said data. any suggestions?
dashboard.vue
<template>
<div>
<v-col cols="10" class="mx-auto">
<v-card class="pa-4" outlined>
<v-card-title class="pb-0 pt-2">Dashbard</v-card-title>
<div v-if="checkifEmpty()">
<v-row>
<v-col
v-for="item in myBatch.all_batch"
:key="item.batch_code"
cols="6"
>
<v-card class="ma-2" outlined>
<div class="d-flex">
<v-avatar class="ma-3" size="150" tile>
<v-img :src="item.image"></v-img>
</v-avatar>
<div>
<v-card-title class="pb-0 pt-2"
>{{ item.offer }} ({{ item.level }})</v-card-title
>
<v-card-text>
<div class="mt-0">{{ item.techer_name }}</div>
<div class="mt-0">{{ item.batch_name }}</div>
<div class="Heading 6 pb-0">
{{ item.start_date }} -
{{ item.end_date }}
</div>
<div class="subtitle-1 pb-0">{{ item.type }}</div>
</v-card-text>
</div>
<v-btn elevation="3" v-on:click="openReviewDialog"
>Rate and Review!</v-btn
>
</div>
</v-card>
</v-col>
</v-row>
</div>
<div v-else>
<v-card-text class="pb-0 pt-2"
>You have no enrolled offers</v-card-text
>
</div>
</v-card>
</v-col>
<review />
</div>
</template>
<script>
import store from "../../store/index";
import review from "./review"
export default {
name: "Dashboard",
components:{
review,
},
computed: {
myBatch() {
return store.getters.getMyOffers;
},
},
methods: {
checkifEmpty() {
let batch = this.myBatch;
if (batch == null || batch.all_batch.length == 0) {
return false;
} else {
return true;
}
},
openReviewDialog() {
this.$store.dispatch("setreviewDialog");
this.sidebarFront = false;
}
},
};
</script>
<style>
</style>
‍‍‍review.vue
<template>
<v-row justify="center">
<v-dialog v-model="reviewDialog" persistent max-width="900px">
<v-card>
<v-card-title class="justify-center">
<span class="headline font-weight-bold"
>Rate and Review this Course!</span
>
</v-card-title>
<v-card-text>
<v-container fluid>
<v-row>
<v-col cols="12" sm="12" md="12">
<v-form
ref="userReview"
v-model="userReviewForm"
lazy-validation
>
<v-text-field
rounded
outlined
v-model="subject"
label="Subject"
required
></v-text-field>
<v-text-field
rounded
outlined
v-model="batch_code"
label="batch_code"
readonly
></v-text-field>
<v-textarea
rounded
outlined
v-model="review"
counter="250"
label="Review"
required
></v-textarea>
<v-rating v-model="rating">
<template v-slot:item="props">
<v-icon
:color="props.isFilled ? 'orange lighten-1' : 'grey lighten-1'"
size = "30"
#click="handleRatingChange(props)">mdi-star</v-icon>
</template>
</v-rating>
<div>
<v-btn
:loading="loginLoader"
large
block
rounded
elevation="0"
color="primary"
#click="submit"
>
Submit
</v-btn>
</div>
</v-form>
</v-col>
</v-row>
</v-container>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<div class="close"> <v-btn color="error" text #click="closeReviewDialog()"> Close </v-btn></div>
</v-card-actions>
</v-card>
</v-dialog>
</v-row>
</template>
<script>
import store from "../../store/index";
export default {
props: {
item:{
batch_code: null;
}
},
name: "review",
data() {
return {
getters: store.getters,
rating: null
};
},
computed: {
reviewDialog: function () {
return this.getters.getreviewDialog;
},
},
methods: {
closeReviewDialog: function () {
//this.show = false;
//this.$refs.card.hide();
//store.dispatch("removeLoginError");
store.dispatch("setreviewDialog");
},
handleRatingChange(props){
console.log(props.index + 1)
this.rating = props.index +1
}
},
};
</script>
'''
p.s: i don't know if it's different when calling props for a component than to a dialog box.
just update your code like below tips,
openReviewDialog() {
this.$store.dispatch("setreviewDialog", **your_rating_data**);
this.sidebarFront = false;
}
so update your dispatch/action accordingly in store.
and when loading your form just pull data from the store using getter and show on dialog.

Vuex store update but DOM is not

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.

Vuetify v-autocomplete have issue

I using vuetify.js on laravel project.
and I create [station][verhicle][take a time] form like this.
its simple form. but ...
station select box is used v-autocomplete component.
so it seems that the input tag is automatically embedded like this.
this input tag is unnecessary.
I expect return one array.
Is there any good way?
thank you
<template>
<v-container>
<v-row dense>
<v-col sm="4">
<v-autocomplete
v-model="StationModel"
:items="stationsSon"
:search-input.sync="search"
item-text="name"
item-value="id"
name="station_id[]"
label="station"
clearable
hide-details
hide-selected
outlined
>
<template v-slot:selection="{ item,selected }">
<span>{{ item.routell_name + item.name }}</span>
</template>
<template v-slot:item="{ item }">
<v-list-item-content>
<v-list-item-title v-text="item.name"></v-list-item-title>
<v-list-item-subtitle v-text="item.routell_name"></v-list-item-subtitle>
</v-list-item-content>
</template>
</v-autocomplete>
</v-col>
<v-col sm="4">
<v-select
name="verhicle_id[]"
:items="verhiclesSon"
item-value="id"
item-text="name"
label="verhicle"
outlined
clearable
>
</v-select>
</v-col>
<v-col sm="4">
<v-text-field
name="take_time[]"
type="number"
:rules="[v => v && v.length <= 2 || 'Warn:2 charactor']"
label="take a time"
outlined
>
</v-text-field>
</v-col>
</v-row>
</v-container>
</template>
<script>
export default {
data: () => ({
stationsDefault: [],
StationModel: null,
search: null,
tab: null,
}),
watch: {
model (val) {
if (val != null) this.tab = 0;
else this.tab = null;
},
search (val) {
if (this.stationsDefault.length > 0) return;
},
},
props:{
stationsSon:{
type: Array
},
verhiclesSon:{
type: Array
},
},
methods:{
snipeDown: function(){
const target = document.getElementsByClassName('v-select__selections');
document.removeChild(target("input"));
}
},
};
</script>

Vuetify dynamic form inputs with datepickers

I'm trying to make a dynamic form inside a dialog but having an issue with datepickers values. each datepicker doesn't set its value
<v-col
cols="12"
sm="12"
md="12"
v-if="typeOfContact === 'flexible'"
>
<v-btn
elevation="2"
color="primary"
#click="pushContract"
>
Add Contract
</v-btn>
</v-col>
<v-row
v-for="(contract, counter) in contracts"
v-bind:key="counter"
>
<v-col
cols="12"
sm="3"
md="3"
v-if="typeOfContact === 'flexible'"
>
<v-dialog
ref="contractStartDateDialog"
v-model="contractStartDateModal"
:return-value.sync="contract.startDate"
persistent
width="290px"
>
<template v-slot:activator="{ on, attrs }">
<v-text-field
v-model="contract.startDate"
label="Start Date"
prepend-icon="mdi-calendar"
readonly
v-bind="attrs"
v-on="on"
>
</v-text-field>
</template>
<v-date-picker
v-model="contract.startDate"
scrollable
>
<v-spacer></v-spacer>
<v-btn
text
color="primary"
#click="contractStartDateModal = false"
>
Cancel
</v-btn>
<v-btn
text
color="primary"
#click="$refs.contractStartDateDialog[counter].save(contract.startDate)"
>
OK
</v-btn>
</v-date-picker>
</v-dialog>
</v-col>
<v-col
cols="12"
sm="3"
md="3"
v-if="typeOfContact === 'flexible'"
>
<v-dialog
ref="contractEndDateDialog"
v-model="contractEndDateModal"
:return-value.sync="contract.endDate"
persistent
width="290px"
>
<template v-slot:activator="{ on, attrs }">
<v-text-field
v-model="contract.endDate"
label="End Date"
prepend-icon="mdi-calendar"
readonly
v-bind="attrs"
v-on="on"
>
</v-text-field>
</template>
<v-date-picker
v-model="contract.endDate"
scrollable
>
<v-spacer></v-spacer>
<v-btn
text
color="primary"
#click="contractEndDateModal = false"
>
Cancel
</v-btn>
<v-btn
text
color="primary"
#click="$refs.contractEndDateDialog[counter].save(contract.endDate)"
>
OK
</v-btn>
</v-date-picker>
</v-dialog>
</v-col>
<v-col
cols="12"
sm="2"
md="2"
v-if="typeOfContact === 'flexible'"
>
<v-text-field
v-model="contract.PIP"
label="Periodically Increase"
suffix="%"
required
:rules="[required('Periodically Increase'), minLength('Periodically Increase', 1), maxLength('Periodically Increase', 2), isNumuric('Periodically Increase')]"
/>
</v-col>
<v-col
cols="12"
sm="3"
md="3"
v-if="typeOfContact === 'flexible'"
>
<v-text-field
v-model="contract.PIA"
label="Periodically Increase Amount"
suffix="K EGP"
required
:rules="[required('Periodically Increase Amount'), minLength('Periodically Increase Amount', 1), maxLength('Periodically Increase Amount', 15), isNumuric('Periodically Increase Amount')]"
/>
</v-col>
<v-col
cols="12"
sm="1"
md="1"
v-if="typeOfContact === 'flexible'"
>
<v-icon
small
class="mt-6"
color="primary"
#click="deleteContract(counter)"
>
mdi-trash-can-outline
</v-icon>
</v-col>
</v-row>
script:
export default {
name: "data-management",
data: () => ({
contractStartDateModal: false,
contractEndDateModal: false,
contracts: [
{
startDate: new Date().toISOString().substr(0, 10),
endDate: new Date().toISOString().substr(0, 10),
PIP: null,
PIA: null,
},
{
startDate: new Date().toISOString().substr(0, 10),
endDate: new Date().toISOString().substr(0, 10),
PIP: null,
PIA: null,
},
],
}),
methods: {
closeContracts () {
this.contractsDialog = false;
this.$nextTick(() => {
this.editedItem = Object.assign({}, this.defaultItem);
this.editedIndex = -1;
});
this.closeContractsModal = true;
},
pushContract() {
this.contracts.push({
startDate: new Date().toISOString().substr(0, 10),
endDate: new Date().toISOString().substr(0, 10),
PIP: null,
PIA: null,
});
},
deleteContract(counter){
this.contracts.splice(counter,1);
}
},
}
when I assign the first start date it changes the second row's start date. And if I change the start date of the second row it it says
VDialog.ts?d213:245 Uncaught RangeError: Maximum call stack size
exceeded.
You have nested your v-dialog in your v-for hence generating as many v-dialog as rows. Ideally it would be preferable to declare it outside your looped element.