link3151 link3152 link3153 link3154 link3155 link3156 link3157 link3158 link3159 link3160 link3161 link3162 link3163 link3164 link3165 link3166 link3167 link3168 link3169 link3170 link3171 link3172 link3173 link3174 link3175 link3176 link3177 link3178 link3179 link3180 link3181 link3182 link3183 link3184 link3185 link3186 link3187 link3188 link3189 link3190 link3191 link3192 link3193 link3194 link3195 link3196 link3197 link3198 link3199 link3200 link3201 link3202 link3203 link3204 link3205 link3206 link3207 link3208 link3209 link3210 link3211 link3212 link3213 link3214 link3215 link3216 link3217 link3218 link3219 link3220 link3221 link3222 link3223 link3224 link3225 link3226 link3227 link3228 link3229 link3230 link3231 link3232 link3233 link3234 link3235 link3236 link3237 link3238 link3239 link3240 link3241 link3242 link3243 link3244 link3245 link3246 link3247 link3248 link3249 link3250 link3251 link3252 link3253 link3254 link3255 link3256 link3257 link3258 link3259 link3260 link3261 link3262 link3263 link3264 link3265 link3266 link3267 link3268 link3269 link3270 link3271 link3272 link3273 link3274 link3275 link3276 link3277 link3278 link3279 link3280 link3281 link3282 link3283 link3284

[Vue.js] bind Kendo vue dropdownlist to array of objects

SAMPLE https://stackblitz.com/edit/usjgwp?file=index.html

to show a number of kendo dropdownlist(s) on a page. The exact number depends on an API call. This API call will give me an array of stakeholder objects. Stakeholder objects have the following properties: Id, name, type, role and isSelected.

The number of dropdownlist that has to be shown on this page should be equal to the number of unique type values in the API response array. i.e,
numberOfDropdowns = stakeholders.map(a => a.type).distinct().count().

Now, each dropdown will have a datasource based on the type property. i.e, For a dropdown for type = 1, dataSource will be stakeholders.filter(s => s.type == 1).

Also the default values in the dropdowns will be based on the isSelected property. For every type, only one object will have isSelected = true.

there is achieved these things by using the following code:

<template>
<div
v-if=”selectedStakeholders.length > 0”
v-for=”(stakeholderLabel, index) in stakeholderLabels”
:key=”stakeholderLabel.Key”
\>
<label>{ stakeholderLabel.Value }:</label>
<kendo-dropdownlist
v-model=”selectedStakeholders[index].Id”
:data-source=”stakeholders.filter(s => s.type == stakeholderLabel.Key)”
data-text-field=”name”
data-value-field=”Id”
\></kendo-dropdownlist>

<button @click=”updateStakeholders”>Update form</button>
</div>
</template>

<script>
import STAKEHOLDER_SERVICE from “somePath”;
export default {
name: “someName”,
props: {
value1: String,
value2: String,
},
data() {
return {
payload: {
value1: this.value1,
value2: this.value2
},
stakeholders: [],
selectedStakeholders: [],
stakeholderLabels: [] // [{Key: 1, Value: “Stakeholder1”}, {Key: 2, Value: “Stakeholder2”}, … ]
};
},
mounted: async function() {
await this.setStakeholderLabels();
await this.setStakeholderDataSource();
this.setSelectedStakeholdersArray();
},
methods: {
async setStakeholderLabels() {
let kvPairs = await STAKEHOLDER_SERVICE.getStakeholderLabels();
kvPairs = kvPairs.sort((kv1, kv2) => (kv1.Key > kv2.Key ? 1 : -1));
kvPairs.forEach(kvPair => this.stakeholderLabels.push(kvPair));
},
async setStakeholderDataSource() {
this.stakeholders = await STAKEHOLDER_SERVICE.getStakeholders(
this.payload
);
}
setSelectedStakeholdersArray() {
const selectedStakeholders = this.stakeholders
.filter(s => s.isSelected === true)
.sort((s1, s2) => (s1.type > s2.type ? 1 : -1));

selectedStakeholders.forEach(selectedStakeholder =>
this.selectedStakeholders.push(selectedStakeholder)
);
},
async updateStakeholders() {
console.log(this.selectedStakeholders);
}
}
};
</script>

The problem is that when not able to change the selection in the dropdownlist the selection always remains the same as the default selected values. Even when I choose a different option in any dropdownlist, the selection does not actually change.

I’ve also tried binding like this:

<kendo-dropdownlist
v-model=”selectedStakeholders[index]“
value-primitive=”false”
:data-source=”stakeholders.filter(s => s.type == stakeholderLabel.Key)”
data-text-field=”name”
data-value-field=”Id”
\></kendo-dropdownlist>

If I bind like this, when able to change selection but then the default selection does not happen, the first option is always the selection option i.e, default selection is not based on the isSelected property.

My requirement is that there is to show the dropdown with some default selections, allow the user to choose different options in all the different dropdowns and then retrieve all the selection then the update button is clicked.

UPDATE:
When I use the first method for binding, The Id property of objects in the selectedStakeholders array is actually changing, but it does not reflect on the UI, i.e, on the UI, the selected option is always the default option even when user changes selection.
Also when I subscribe to the change and select events, I see that only select event is being triggered, change event never triggers.

Solution :

So it turns out that it was a Vue.js limitation (or a JS limitation which vue.js inherited),
Link

I had to explicitly change the values in selectedStakeholders array like this:

SAMPLE https://stackblitz.com/edit/usjgwp?file=index.html

to show a number of kendo dropdownlist(s) on a page. The exact number depends on an API call. This API call will give me an array of stakeholder objects. Stakeholder objects have the following properties: Id, name, type, role and isSelected.

The number of dropdownlist that has to be shown on this page should be equal to the number of unique type values in the API response array. i.e, numberOfDropdowns = stakeholders.map(a => a.type).distinct().count().

Now, each dropdown will have a datasource based on the type property. i.e, For a dropdown for type = 1, dataSource will be stakeholders.filter(s => s.type == 1).

Also the default values in the dropdowns will be based on the isSelected property. For every type, only one object will have isSelected = true.

there is achieved these things by using the following code:

<template>
<div
v-if=”selectedStakeholders.length > 0”
v-for=”(stakeholderLabel, index) in stakeholderLabels”
:key=”stakeholderLabel.Key”
\>
<label>{ stakeholderLabel.Value }:</label>
<kendo-dropdownlist
v-model=”selectedStakeholders[index].Id”
:data-source=”stakeholders.filter(s => s.type == stakeholderLabel.Key)”
data-text-field=”name”
data-value-field=”Id”
@select=”selected”
\></kendo-dropdownlist>

<button @click=”updateStakeholders”>Update form</button>
</div>
</template>

And in methods:

selected(e) {
const stakeholderTypeId = e.dataItem.type;
const selectedStakeholderIndexForTypeId = this.selectedStakeholders.findIndex(
s => s.type == stakeholderTypeId
);
this.$set(
this.selectedStakeholders,
selectedStakeholderIndexForTypeId,
e.dataItem
);
}