Reputation: 69
i've been struggling for some time with a dynamic form using Vuejs and Vuetify. First of all, i have an API that returns me the value for competences and skills to add to an appraisal. When creating a new appraisal i want to show the form in steps, so i'm using v-stepper. The problem is, in the third step, the user need to select one of the competences that he already selected before, and after he select this competence, he needs to add skills to this competence, so one competence can have multiple skills.
What i'm trying to do is, in step 2 I have a select that fills the selectedCompetences array, and in step 3, i have a selectedCompetence property, that holds the competence the user selected for adding skills, and a selectedSkills array, to add to this competence.
To post to the api i need an array like
[
competenceId: 1
skills:
[
{skillId: 1},
{skillId: 2},
{skillId: 3},
{skillId: 4},
]
]
And, i need to do this like, the user adds the first set of competences/skills. And he wants to add skills to another competence, so it needs to have a button to add 2 new fields to the form for him to fill the same way. I lost an entire day trying to figure out this logic, but nothing seems to work.
Below is my stepper component:
<template>
<v-stepper v-model="step" alt-labels>
<v-stepper-header>
<v-stepper-step editable step="1" :complete="step > 1">Avaliação</v-stepper-step>
<v-divider></v-divider>
<v-stepper-step editable step="2" :complete="step > 2">Competências</v-stepper-step>
<v-divider></v-divider>
<v-stepper-step editable step="3" :complete="step > 3">Fatores</v-stepper-step>
<v-divider></v-divider>
<v-stepper-step step="4">Resumo</v-stepper-step>
</v-stepper-header>
<v-stepper-content step="1">
<v-row align="center" justify="center">
<v-col cols="4">
<v-text-field label="Descrição"></v-text-field>
</v-col>
</v-row>
<v-row align="center" justify="center">
<v-col cols="4">
<v-text-field v-model="newAppraisal.year" label="Ano"></v-text-field>
</v-col>
</v-row>
<v-row align="center" justify="center">
<v-col cols="2">
<v-menu
v-model="menu_std"
:close-on-content-click="false"
:nudge-right="40"
transition="scale-transition"
offset-y
min-width="290px"
>
<template v-slot:activator="{ on }">
<v-text-field label="Data de Início" readonly v-on="on" :value="computedStartDate"></v-text-field>
</template>
<v-date-picker
v-model="newAppraisal.startDate"
show-week
@input="menu_std = false"
color="primary"
></v-date-picker>
</v-menu>
</v-col>
<v-col cols="2">
<v-menu
v-model="menu_end"
:close-on-content-click="false"
:nudge-right="40"
transition="scale-transition"
offset-y
min-width="290px"
>
<template v-slot:activator="{ on }">
<v-text-field label="Data de Término" readonly v-on="on" :value="computedEndDate"></v-text-field>
</template>
<v-date-picker
v-model="newAppraisal.endDate"
show-week
@input="menu_end = false"
color="primary"
></v-date-picker>
</v-menu>
</v-col>
</v-row>
<v-row align="center" justify="center">
<v-col cols="2">
<v-radio-group v-model="newAppraisal.type" row>
<v-radio label="Obrigatória" value="0" color="primary"></v-radio>
<v-radio label="Pontual" value="1" color="primary"></v-radio>
</v-radio-group>
</v-col>
<v-col cols="2">
<div v-if="newAppraisal.type === '1'">
<v-select label="Selecione o usuário" chips v-model="newAppraisal.appraised"></v-select>
</div>
</v-col>
</v-row>
<v-row>
<v-col cols="12">
<v-row align="center" justify="end">
<v-btn color="success" tile large @click.native="next">Continuar</v-btn>
</v-row>
</v-col>
</v-row>
</v-stepper-content>
<v-stepper-content step="2">
<v-row align="center" justify="center">
<v-col cols="4">
<v-select
v-model="selectedCompetences"
:items="competences"
multiple
item-text="name"
return-object
label="Selecione as competências"
chips
hint="Adicione as competências para essa avaliação"
persistent-hint
></v-select>
</v-col>
</v-row>
<v-row>
<v-col cols="12">
<v-row align="center" justify="space-between">
<v-btn color="error" tile large @click.native="previous">Voltar</v-btn>
<v-btn color="success" tile large @click.native="next">Continuar</v-btn>
</v-row>
</v-col>
</v-row>
</v-stepper-content>
<v-stepper-content step="3">
<v-row align="center" justify="center">
<v-col cols="8">
<v-subheader class="title">Competencia 1</v-subheader>
<v-divider></v-divider>
</v-col>
</v-row>
<v-row align="center" justify="center">
<v-col cols="4">
<v-autocomplete
:items="selectedCompetences"
item-text="name"
item-value="competenceId"
v-model="selectedCompetence"
label="Competência"
></v-autocomplete>
</v-col>
</v-row>
<v-row align="center" justify="center">
<v-col cols="4">
<v-select
:items="skills"
v-model="selectedSkills"
multiple
chips
label="Fatores"
item-text="name"
item-value="skillId"
></v-select>
</v-col>
</v-row>
<v-row>
<v-col cols="12">
<v-row align="center" justify="space-between">
<v-btn color="error" tile large @click.native="previous">Voltar</v-btn>
<v-btn color="success" tile large @click.native="next">Continuar</v-btn>
</v-row>
<v-btn color="success" @click.native="addSkillsToCompetence">teste aqui</v-btn>
</v-col>
</v-row>
</v-stepper-content>
<v-stepper-content step="4">
<v-list>
<v-list-item>{{newAppraisal.year}}</v-list-item>
<v-list-item>{{computedStartDate}}</v-list-item>
<v-list-item>{{computedEndDate}}</v-list-item>
<v-list-item v-if="newAppraisal.type === '0'">Obrigatória</v-list-item>
<v-list-item v-else-if="newAppraisal.type === '1'">Pontual</v-list-item>
<v-list-item
v-for="(competence, index) in selectedCompetences"
:key="index"
>{{competence.name}}</v-list-item>
</v-list>
<v-btn color="primary" @click.native="previous">Voltar</v-btn>
<v-btn color="primary" @click.native="save">Salvar</v-btn>
</v-stepper-content>
</v-stepper>
</template>
<script>
import moment from "moment";
export default {
data: () => ({
step: 1,
menu_std: false,
menu_end: false,
newAppraisal: {
year: "",
startDate: new Date().toISOString().substr(0, 10),
endDate: new Date().toISOString().substr(0, 10),
type: "0",
appraised: {
name: "",
sector: "",
admissionDate: new Date().toISOString().substr(0, 10),
jobTitle: "",
appraiserName: ""
}
},
competences: [],
selectedCompetences: [],
selectedCompetence: "",
competenceSkills: [],
skills: [],
selectedSkills: [],
errors: [],
teste: {
competenceId: "",
skills: []
}
}),
computed: {
computedStartDate() {
return this.newAppraisal.startDate
? moment(this.newAppraisal.startDate).format("DD/MM/YYYY")
: "";
},
computedEndDate() {
return this.newAppraisal.endDate
? moment(this.newAppraisal.endDate).format("DD/MM/YYYY")
: "";
}
},
methods: {
previous() {
this.step--;
},
next() {
this.step++;
},
save() {
// first save appraisal, then add skill to competence, then add competence to appraisal
},
loadCompetences() {
axios
.get("/questionnaire/competences")
.then(response => {
this.competences = response.data;
})
.catch(e => {
this.errors.push(e);
});
},
loadSkills() {
axios
.get("/questionnaire/skills")
.then(response => {
this.skills = response.data;
})
.catch(e => {
this.errors.push(e);
});
},
addSkillsToCompetence() {
console.log(this.selectedCompetence, this.selectedSkills);
this.teste.competenceId = this.selectedCompetence
this.teste.skills = this.selectedSkills
console.log(this.teste);
this.competenceSkills.push(this.teste)
}
},
created() {
this.loadCompetences();
this.loadSkills();
}
};
</script>
<style>
</style>
If someone could help with this, i'm stuck
Upvotes: 0
Views: 1803
Reputation: 5158
I'm not sure I understand you correctly but this is my solution:
<div id='app'>
<v-app>
<v-container>
<v-stepper
vertical
v-model='step'>
<v-stepper-step
editable
key='step-1'
:step='1'
:complete='step > 1'>
Step 1
</v-stepper-step>
<v-stepper-content
key='content-1'
:step='1'>
<v-select
multiple
label='Select Competencies'
v-model='selectedCompetencies'
:items='competencies'/>
</v-stepper-content>
<v-stepper-step
editable
key='step-2'
:step='2'
:complete='step > 2'>
Step 2
</v-stepper-step>
<v-stepper-content
key='content-2'
:step='2'>
<div v-for='set in selectedSkillSets'>
<div>{{ set.competence }}</div>
<v-select
multiple
label='Add Skill'
v-model='set.skills'
:items='skills'/>
</div>
<v-select
label='Add Skill Set'
v-if='availableCompetencies.length'
:items='availableCompetencies'
@change='addSkillSet($event)'/>
</v-stepper-content>
</v-stepper>
</v-container>
</v-app>
</div>
new Vue({
el: '#app',
vuetify: new Vuetify(),
data: () => ({
step: 1,
competencies: [
'Foo',
'Bar',
'Fizz',
'Buzz'
],
skills: [
'Communication',
'Teamwork',
'Adaptability',
'Problem-Solving',
'Creativity'
],
selectedCompetencies: [],
selectedSkillSets: []
}),
computed: {
availableCompetencies() {
let used = this.selectedSkillSets.map(set => set.competence)
return this.selectedCompetencies.filter(competence => (
!used.includes(competence)
))
}
},
methods: {
addSkillSet(competence) {
this.selectedSkillSets.push({
competence,
skills: []
})
}
}
})
I hope this help.
Upvotes: 1