Fill with values - dynamic dropdowns - vue.js

I'm trying to fill dropdowns with values while dropdowns are "sent" trough props. I'm getting the data from server correctly, and storing it in array where I am using that array to fill selected dropdown.
This problem looks like its Vuetify or Vue bug but I'm not sure.
Code for dynamic dropdowns looks like this (Vuetify):
<v-col cols="12" lg="2" md="2" sm="6" xs="6" v-for="(dropdowns, index) in dropdownNumber" v-bind:key="index">
<v-select
:v-model="dropdowns.field_name"
:loading="loadingInputs"
:label="dropdowns.dropdown_name"
:disabled="enableDropdowns"
:items="getData[dropdowns.field_name]"
:clearable="true"
:item-text="dropdowns.field_name"
:item-value="dropdowns.field_name"
:item-key="dropdowns.field_name"
#mousedown="changeFields(dropdowns.field_name, index)"
#change="selectedValue(dropdowns.field_name, $event)"
:multiple="dropdowns.multiple"
>
</v-select>
And function for take data from server:
async getDropdownData($event, index) {
const key = $event
try {
this.values['sector_name'] = this.categoryName()
this.keys.forEach(element => {
if(localStorage.getItem(element) != null) {
this.values[element] = localStorage.getItem(element)
}
});
this.takeServerData = (await DataService.getDropdownData({
existingValues: this.values,
selectedDropdown: $event
})).data
this.getData[key] = this.takeServerData
console.log(this.getData)
} catch (error) {
this.error = "Dogodila se pogreška prilikom dohvaćanja vrijednosti za tu opciju."
}
},
Sometimes, while I'm editing my code it normally fill already clicked dropdown, but after refreshing site it does not work.
Photo example: https://imgur.com/a/MutkZQC
Is there something I'm missing?
Any help or advice is welcome!

It sounds like a reactivity problem related to nested objects.
https://v2.vuejs.org/v2/guide/reactivity.html
Either sure your arrays are predefined within the getData object.
data () {
return {
getData: {
field1 : [],
field2 : []
}
}
},
Or update your getData object like this
this.$set(this.getData, key, this.takeServerData)

Related

v-mask not working correctly with veutifyjs input

I'm using veutifyjs text-input to show phone number. I have a button to assign phone number to v-model. But after assign it not change there text input. if I enter some think on text-input v-mask work. But if I assign value to v-model it not working. Also i'm tying next trick but its not have any difference.
<v-text-field
v-model="form.phone_number"
v-mask="'(###) ###-####'"
dense
outlined
autocomplete="new-password"
hide-details="auto"
label="Phone Number"
placeholder="Phone Number"
></v-text-field>
<v-btn color="warning" #click="dataupdate()">Add</v-btn>
dataupdate() {
this.$nextTick(() => {
this.form.phone_number = '4032223344'
})
},
You have to set the v-mask dynamically after you set the value of form.phone_number, so we could create a phoneNumberMask variable:
data() {
return {
phoneNumberMask: '',
};
}
Set it as the v-mask value:
<v-text-field
v-model="form.phone_number"
v-mask="phoneNumberMask"
...
then at dataupdate():
dataupdate() {
this.form.phone_number = '4032223344'
this.$nextTick(() => {
this.phoneNumberMask = '(###) ###-####'
})
/*
* you'd just have to deal with calling this funcition
* when phoneNumberMask has already a value
* and that depends on your business rules
*/
},
I had the same issue after migration to Vuetify 2 and fixed it so: Just replaced v-mask library with vue-input-facade as mentioned here.
It works exactly the same as the old mask from the first Vuetify but you should use the parameter "v-facade" instead.

Vuetify combobox - How to disable typing in vuetify's combobox

The vuetify combobox is allowing the user to type inside the combobox. Any clue on how to disable this.
This is how I have implemented my combobox.
<v-combobox
:loading="isSurveyBeingPopulated"
class="static--inputs"
color="red"
box
:items="folders"
:rules="[rules.required]"
item-text="value"
dense
placeholder="Select Survey Folder"
item-value="key"
slot="input"
v-model="selectedSurveyFolder">
</v-combobox>
Combobox:
The v-combobox component is a v-autocomplete that allows the user to
enter values that do not exist within the provided items. Created
items will be returned as strings.
So if you want to disable the typing you should use a select: https://vuetifyjs.com/en/components/selects
Select fields components are used for collecting user provided
information from a list of options.
You can just delete new item after changed.
<v-combobox
v-model="selected"
:items="[...selected, ...items]"
multiple
#change="onChangeCombobox"
/>
onChangeCombobox(items) {
this.selected = items.filter((item) => this.items.includes(item))
}
I had the same problem, I used v-select instead of v-combobox, it works fine:
<v-select
return-object
></v-select>
I've gone thru the same, i need combobox to list item and custom values but i must disable typing, my solutions was to use key events and "change"its behavior like:
#keydown="$event.target.blur()"
#keypress="$event.target.blur()"
#keyup="$event.target.blur()"
Yes, you can achieve filtering of a combobox by using the rules code, e.g.
<v-combobox
v-model="selection"
:items="items"
:search-input.sync="input"
:rules="intRule"
chips
clearable
dense
multiple
small-chips
item-text="title"
autocomplete="off"
return-object
>
</v-combobox>
and then in your script section in data, sth like
data() {
return {
selection: [],
input: null,
items: [],
valid: false,
intRule: [
function(v) {
if (!v || v.length < 0) {
return false
} else if (v.length > 0) {
for (let i = 0; i < v.length; i++) {
if (/[^0-9]/g.test(v[i].id)) {
v.splice(-1, 1)
return false
}
}
return false
} else {
return true
}
}
]
}
}
the input could be used to overwrite a no results slot and show for what input are no results found.
hope this is helping

vue element checkbox not working in edit mode

I am using checkbox given by vue-element, visit https://element.eleme.io/#/en-US/component/checkbox.
But in edit mode they are not able to select anymore.
Please help me out.
<el-checkbox-group v-model="form.activity_type" size="small">
<el-checkbox-button
v-for="(all_type,index) in all_activity"
:key="index"
:label="all_type.id"
>{{all_type.activity_type_name}}</el-checkbox-button>
</el-checkbox-group>
<el-checkbox-group v-model="form.activity_type" size="small">
<e`enter code here`l-checkbox-button
v-for="(all_type,index) in all_activity"
:key="index"
:label="all_type.id">
{{all_type.activity_type_name}}
</el-checkbox-button>
</el-checkbox-group>
Hi you in order to show checkbox in edit mode you can do it like this:
data() {
return {
form: {
activity_type: []
}
};
}
import {activityData} from "#/api/activity";
2)under method function:
activityData(id).then(response => {
this.form = response.res;
});
3) and then from your controller function you can pass data in this format:
$allData = [];
$allData['activity_type'] = array(1,3);//the ids one you want to show check
return response()->json(["res" => $allData]);

Set a variable inside a v-for loop on Vue JS

I have a v-for loop with vue.js on a SPA and I wonder if it's posible to set a variable at the beginning and then just print it everytime you need it, because right now i'm calling a method everytime i need to print the variable.
This is the JSON data.
{
"likes": ["famiglia", "ridere", "caffè", "cioccolato", "tres leches", "ballare", "cinema"],
"dislikes":["tristezze", "abuso su animali", "ingiustizie", "bugie"]
}
Then I use it in a loop:
<template>
<div class="c-interests__item" v-for="(value, key) in interests" :key="key" :data-key="key" :data-is="getEmotion(key)" >
// NOTE: I need to use the variable like this in different places, and I find myself calling getEmotion(key) everythime, is this the way to go on Vue? or there is another way to set a var and just call it where we need it?
<div :class="['c-card__frontTopBox', 'c-card__frontTopBox--' + getEmotion(key)]" ...
<svgicon :icon="getEmotion(key) ...
</div>
</template>
<script>
import interests from '../assets/json/interests.json'
... More imports
let emotion = ''
export default {
name: 'CInfographicsInterests',
components: {
JSubtitle, svgicon
},
data () {
return {
interests,
emotion
}
},
methods: {
getEmotion (key) {
let emotion = (key === 0) ? 'happy' : 'sad'
return emotion
}
}
}
</script>
// Not relevanty to the question
<style lang='scss'>
.c-interests{...}
</style>
I tried adding a prop like :testy="getEmotion(key)" and then { testy } with no luck...
I tried printing { emotion } directly and it doesn't work
So, there is anyway to acomplish this or should i stick calling the method every time?
Thanks in advance for any help.
It's not a good idea to use methods inside a template for non-user-directed actions (like onClicks). It's especially bad, when it comes to performance, inside loops.
Instead of using a method, you can use a computed variable to store the state like so
computed: {
emotions() {
return this.interests.map((index, key) => key === 0 ? 'happy' : 'sad');
}
}
This will create an array that will return the data you need, so you can use
<div class="c-interests__item"
v-for="(value, key) in interests"
:key="key" />`
which will reduce the amount of times the item gets re-drawn.

Toggle detailed row in buefy table

I have a buefy table with details. Whenever I click on a chevron, the detailed view of the according row shows. It would be much better in my case, to have only one detailed view open. The desired outcome is: Whenever I click on a chevron, that detailed view opens and all other close.
In buefy, the opening of the detailed view is programmed like this:
<td v-if="detailed">
<a role="button" #click.stop="toggleDetails(row)">
<b-icon
icon="chevron-right"
both
:class="{'is-expanded': isVisibleDetailRow(row)}"/>
</a>
</td>
...
props: {
...
detailed: Boolean
...
}
...
methods: {
...
toggleDetails(obj) {
const found = this.isVisibleDetailRow(obj)
if (found) {
this.closeDetailRow(obj)
this.$emit('details-close', obj)
} else {
this.openDetailRow(obj)
this.$emit('details-open', obj)
}
// Syncs the detailed rows with the parent component
this.$emit('update:openedDetailed', this.visibleDetailRows)
},
openDetailRow(obj) {
const index = this.handleDetailKey(obj)
this.visibleDetailRows.push(index)
},
closeDetailRow(obj) {
const index = this.handleDetailKey(obj)
const i = this.visibleDetailRows.indexOf(index)
this.visibleDetailRows.splice(i, 1)
},
isVisibleDetailRow(obj) {
const index = this.handleDetailKey(obj)
const result = this.visibleDetailRows.indexOf(index) >= 0
return result
},
...
}
I see that there is an update_event sent to the parent. Do I have to save the
visibleDetailRows and tell the Child component to close it, when the button is pressed again? How would I do that?
The way I did it was to use the #details-open event to call a custom function :
<b-table
:data="data"
:opened-detailed="defaultOpenedDetails"
detailed
detail-key="id"
#details-open="(row, index) => closeAllOtherDetails(row, index)"
>
When you expand a row, the event is triggered.
And the called function closeAllOtherDetails() deletes all elements of the defaultOpenedDetails array, except the current row you just expanded :
closeAllOtherDetails(row, index) {
this.defaultOpenedDetails = [row.id]
}
That does the trick. Simple!