I'm using vue.js with vuetify and saving some data in localstorage but whenever I save once and try to save a new data it calls the save function until the end but it doesn't save in localstorage being necessary to reload the page to be able to save a new data.
<v-card>
<v-card-title>
<span class="text-h5">{{ formTitle }}</span>
</v-card-title>
<v-card-text>
<v-container>
<v-row>
<v-col cols="12" sm="12" md="12">
<v-text-field
v-model="contact.name"
label="Name"
:error-messages="nameErrors"
required
#input="$v.contact.name.$touch()"
#blur="$v.contact.name.$touch()"
>
</v-text-field>
</v-col>
<v-col cols="12" sm="12" md="12">
<v-text-field
v-model="contact.cellPhone"
label="Phone"
v-mask="'(##) #####-####'"
:error-messages="cellPhoneErrors"
required
#input="$v.contact.cellPhone.$touch()"
#blur="$v.contact.cellPhone.$touch()"
>
</v-text-field>
</v-col>
</v-row>
</v-container>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="blue darken-1" text #click="close"> Cancel</v-btn>
<v-btn color="blue darken-1" text #click="save"> Save </v-btn>
</v-card-actions>
</v-card>
save() {
this.submitted = true;
this.$v.$touch();
if (this.$v.$error) {
return;
}
this.editing = false;
if (this.contact.id === 0) {
this.contact.id = this.contacts.length + 1;
this.contact.ddd = this.contact.cellPhone.substr(
1,
2
);
this.contacts.push(this.contact);
} else {
this.contacts[this.index] = this.contact;
}
localStorage.setItem(
'contacts',
JSON.stringify(this.contacts)
);
this.close();
this.contact = {
id: 0,
name: null,
cellPhone: null,
ddd: null,
};
},
I've already tried using async await but the problem remains, the only solution so far was using a normal html form instead of the vuetify form.
"Menus can be placed within almost any component" says in the Vuetify's docs
but I'm trying to place it into a List Item, and it doesn't work:
<template>
<v-row align="center" justify="center" cols="12">
<v-col cols="12" sm="10" md="6" lg="8">
<v-list three-line>
<v-subheader>Saved Addresses</v-subheader>
<template v-for="address in userAddresses">
<v-menu bottom left :id="address.id">
<template v-slot:activator="{ on, attrs }">
<v-list-item :key="address.id" #click="">
<v-list-item-avatar>
<v-icon>home</v-icon>
</v-list-item-avatar>
<v-list-item-content>
<v-list-item-title>{{address.adress}}
</v-list-item-title>
<v-list-item-subtitle>{{address.country_id }}, {{address.state_id}},
{{address.city_id}}
<strong>| {{address.postal_code}}</strong></v-list-item-subtitle>
</v-list-item-content>
</v-list-item>
</template>
<v-list>
<v-list-item>
<v-list-item-title>Edit</v-list-item-title>
</v-list-item>
</v-list>
</v-menu>
</template>
</v-list>
</v-col>
</v-row>
</template>
When I click any list item it doesn't show the dropdown menu, I tried different combinations of wrapping the menu template, but same result, or even error.
i'm trying to make a dynamic form to work.
I have an array of competences, and inside, i have a skills array. Each skill of the entire competence is going to be evaluated, so it need to have an answer.
Everything is organized in a v-stepper with dynamic steps, and my form fields are being generated by a v-for. For each skill the answer need to have, maybe an array like
answers: [
skillId:
skillLevel:
feedback:
feedforward:
...
]
My question is, being the form dynamically generated, how can i set the v-models for each field? Because a competence can have many skills, so the models need to be different to bind.
Here's my code
<template>
<v-stepper v-model="e1" :appraisal="appraisal">
<v-stepper-header>
<template v-for="n in steps">
<v-stepper-step :key="`${n}-step`" :step="n" :complete="e1 > n" editable></v-stepper-step>
<v-divider v-if="n !== steps" :key="n"></v-divider>
</template>
</v-stepper-header>
<v-stepper-items>
<v-stepper-content v-for="n in steps" :key="`${n}-content`" :step="n">
<v-row align="center" justify="center">
<v-col cols="4">
<v-subheader class="headline">{{appraisal.appraisalCompetences[n-1].competence.name}}</v-subheader>
</v-col>
</v-row>
<v-row>
<v-col cols="12">
<v-row justify="center">
<v-col cols="3">
<v-subheader class="title">Fatores</v-subheader>
</v-col>
<v-col cols="2">
<v-subheader class="title">Presença da competência</v-subheader>
</v-col>
<v-col cols="2">
<v-subheader class="title">Feedback do Gestor</v-subheader>
</v-col>
<v-col cols="2">
<v-subheader class="title">Auto Avaliação</v-subheader>
</v-col>
<v-col cols="3">
<v-subheader class="title">Feedforward</v-subheader>
</v-col>
</v-row>
</v-col>
</v-row>
<v-divider></v-divider>
<template v-for="competence in appraisal.appraisalCompetences[n-1]">
<v-form :key="`${competence.competenceId}-form`">
<v-row v-for="(item, index) in competence.competenceSkills" :key="index">
<v-col cols="12">
<v-row class="mb-n10" justify="center">
<v-col cols="3" class="mt-4">
<span>{{item.skill.name}}</span>
</v-col>
<v-col cols="2">
<v-select
v-model="answers.skillLevel"
outlined
:items="selectLevels"
:name="`skill-level-${item.skill.skillId}`"
label="Selecione"
item-text="level"
item-value="value"
></v-select>
</v-col>
<v-col cols="2">
<v-textarea outlined rows="3" :name="`skill-feedback-${item.skill.skillId}`"></v-textarea>
</v-col>
<v-col cols="2">
<v-textarea
outlined
rows="3"
:name="`skill-selfappraisal-${item.skill.skillId}`"
></v-textarea>
</v-col>
<v-col cols="3">
<v-textarea outlined rows="3" :name="`skill-feedforward-${item.skill.skillId}`"></v-textarea>
</v-col>
</v-row>
</v-col>
</v-row>
</v-form>
</template>
<v-row>
<v-col cols="12">
<v-row align="center" justify="space-between">
<v-btn tile large color="error" #click="previous(n)">
<v-icon dark left>mdi-arrow-left</v-icon>Voltar
</v-btn>
<v-btn tile large color="success" #click="next(n)">
Continuar
<v-icon dark right>mdi-arrow-right</v-icon>
</v-btn>
</v-row>
</v-col>
</v-row>
</v-stepper-content>
</v-stepper-items>
</v-stepper>
</template>
<script>
export default {
data: () => ({
e1: 1,
steps: 1,
appraisal: [],
selectLevels: [
{ value: 0, level: "Ausente" },
{ value: 1, level: "A Desenvolver" },
{ value: 2, level: "Satifatória" },
{ value: 3, level: "Excelencia" },
{ value: 4, level: "Não se aplica" }
],
answers: [
{
competenceId: "",
appraisalId: "",
skillId: "",
skillLevel: "",
feedback: "",
selfAppraisal: "",
feedforward: ""
}
]
}),
created() {
this.initialize();
},
methods: {
initialize() {
axios
.get(`/questionnaire/appraisals/${this.$route.params.appraisalId}`)
.then(response => {
this.appraisal = response.data;
this.steps = this.appraisal.appraisalCompetences.length;
});
},
previous(n) {
if (this.e1 == 1) {
this.$router.push("/app/pdc");
} else {
this.e1 = n - 1;
}
},
next(n) {
if (n === this.steps) {
this.e1 = 1;
} else {
this.e1 = n + 1;
}
}
}
};
</script>
EDITED
Let me try to improve the question
In my form, for each competence, i have a set of skills that will be evaluated. So for each of these skills, i need to have a separate answer, like
for skill 1
skillId:
skillLevel:
feedback:
feedforward:
...
And so on for all other skills. after the user types the answers for every skill in the competence, i need to do the same for competence 2 an so on.
The problema is in the answers part of the form, I don't know how to make every single line count as one answer and after add them to an array of answers
This is what i came up so far
<template v-for="competence in appraisal.appraisalCompetences[n-1]">
<v-row v-for="(item, index) in competence.competenceSkills" :key="index">
<v-col cols="12">
<v-form :key="`${item.skillId}-form`">
<v-row class="mb-n10" justify="center">
<v-col cols="3" class="mt-4">
<span>{{item.skill.name}}</span>
</v-col>
<v-col cols="2">
<v-select
v-model="`${item.skillId}-form`.skillLevel"
outlined
:items="selectLevels"
label="Selecione"
item-text="level"
item-value="value"
></v-select>
</v-col>
<v-col cols="2">
<v-textarea v-model="answer.feedback" outlined rows="3"></v-textarea>
</v-col>
<v-col cols="2">
<v-textarea v-model="answer.selfAppraisal" outlined rows="3"></v-textarea>
</v-col>
<v-col cols="3">
<v-textarea v-model="answer.feedForward" outlined rows="3"></v-textarea>
</v-col>
</v-row>
</v-form>
</v-col>
</v-row>
</template>
export default {
data: () => ({
e1: 1,
steps: 1,
appraisal: [],
selectLevels: [
{ value: 0, level: "Ausente" },
{ value: 1, level: "A Desenvolver" },
{ value: 2, level: "Satifatória" },
{ value: 3, level: "Excelencia" },
{ value: 4, level: "Não se aplica" }
],
answer: {
competenceId: "",
skillId: "",
skillLevel: "",
feedback: "",
selfAppraisal: "",
feedForward: ""
},
anwers: []
}),
first of all there are some good vuejs-vuetify ready form generator, which isbased on standard json-schema.
see below examples and projects, specially the github code for more detail and idea about how to create a good form generator,so you can use them.
https://github.com/koumoul-dev/vuetify-jsonschema-form
https://koumoul-dev.github.io/vuetify-jsonschema-form/latest/?example=basic
if you want to write some project from scrach, you shoud consider that the idea is simple like rendering a inline edit in a table (by using refrence by means of object passing):
see below example:
watch the logic, you should index properly, when i debugged your code, the code always refrences to answer 0 to 5 at least. so you couldnt make it work.
read below with care to fix you problem:
<v-col cols="2">
<v-select
v-model="answers[index + (competence.competenceId-1)*competence.competenceSkills.length ].skillLevel"
outlined
:items="selectLevels"
label="Selecione"
item-text="level"
item-value="value"
></v-select>
</v-col>
<v-col cols="2">
<v-textarea v-model="answers[index + (competence.competenceId-1)*competence.competenceSkills.length].feedBack" outlined rows="3"></v-textarea>
</v-col>
<v-col cols="2">
<v-textarea v-model="answers[index + (competence.competenceId-1)*competence.competenceSkills.length].selfAppraisal" outlined rows="3"></v-textarea>
</v-col>
<v-col cols="3">
<v-textarea v-model="answers[index + (competence.competenceId-1)*competence.competenceSkills.length].feedForward" outlined rows="3"></v-textarea>
</v-col>
or you can use a better idea, seperation of answers like below:
see below for how i fixed the problem to get the idea:
I have a side panel with searching mechanism and I want to delete, or empty the existing data from each text fields and v-model on button click.
<search-panel :rightDrawer="rightDrawer" #cancelSearch="cancelSearch" #searchData="searchCustomers" #clearData="clearData">
<v-layout row>
<v-flex xs11 offset-xs1>
<v-text-field name="input-1-3" label="Frist Name" light v-model="searchVm.contains.firstName"></v-text-field>
</v-flex>
</v-layout>
<v-layout row>
<v-flex xs11 offset-xs1>
<v-text-field name="input-1-3" label="Last Name" light v-model="searchVm.contains.lastName"></v-text-field>
</v-flex>
</v-layout>
<v-layout row>
<v-flex xs11 offset-xs1>
<v-text-field name="input-1-3" label="Application Name" light v-model="searchVm.contains.applicationName"></v-text-field>
</v-flex>
</v-layout>
<v-layout row>
<v-flex xs11 offset-xs1>
<v-select v-model="searchVm.contains.status"
:items="statuses"
label="Status"
item-text= "name"
item-value= "id"
:return-object="false"></v-select>
</v-flex>
</v-layout>
</search-panel>
clearData() {
for (var e in this.searchVm.contains) {
e.Value=""; //just for demonstartion
}
}
Try this by looping through the keys of your object and use that keys to access the object properties in order to set them to empty strings
Object.keys(this.searchVm.contains).forEach(key=>{
this.searchVm.contains[key]="";
});
I am using Vuetify framework for VueJS and I am trying to recreate the Data table edit dialog but instead of static values, I want the edit dialog to be dynamic (User can specify editable fields).
The problem is that I can't use the key I get from v-for for v-model like this.
<v-dialog v-model="dialog" max-width="500px">
<v-card>
<v-card-title>
<span class="headline">Edit Item</span>
</v-card-title>
<v-card-text>
<v-container grid-list-md>
<v-layout wrap>
<v-flex xs12 sm6 md4 v-for="(item, key, index) in editable_fields">
{{key}}
<h1>{{editedItem}}</h1>
<v-text-field v-model="editedItem.key" :label="key"></v-text-field>
</v-flex>
</v-layout>
</v-container>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="blue darken-1" flat #click.native="close">Cancel</v-btn>
<v-btn color="blue darken-1" flat #click.native="save_edit">Save</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
And these are my props and data:
props: {
editable_fields: {
type: Object
default: ()=> {name: '', email: ''}
}
}
data: ->
editedItem = #editable_fields
return {editedItem: editedItem}
So the question is how should I approach to this?