Vue can't render curly brackets + value - vue.js

My issue is simple but kinda tricky.
I'm inside a v-for, named filter, and I'd like to display thing like item.properties.*value* which is the :items I passed to vuetify autocomplete , and the value has to different in each loop, because the infos to desired are not the same. In other words, I'd like to filter displayed items depending on the object I am.
Notice that the properties is an object with multiples props and I want to display only 1 on the prop in every loop. I did not made any v-forfor this object containing multiples props
The name of the prop I want to show as list on my autocomplete is determined by a variable called "label" that I passed as props in my v-for and therefore, in my looped component which looks like this label : 'filters.mission' (for example, mission)
(I have a traduction file so that's the reason we have a 'filters.mission' here because its all translated, for all the props)
Here is a simple exemple :
// imported array from data I want to display, binded as :items="data"
[
//..stuff
properties : {
"mission": foo,
"driver": bar,
"name": baz,
},
//..stuff
properties : {
"mission": foo2,
"driver": bar2,
"name": baz2,
},
],
In my looped component, I binded my :items="items" and I want to display props like item.properties.mission when my item.label = filters.mission, and so on
But here is the thing :
WORKING
{{ item.properties.mission}} OUTPUT : 'foo', 'foo2'
NOT WORKING
{{ item.properties + label.replace('filters', '') }}
OUTPOUT : [object Object].mission
I tried to parse label.replace('filters', '') but it made me an error.
I also tried to stringify...
Should I write a v-for for my :item object and filter the content ?
item.properties.filter(
(prop) => Object.keys(prop) === label.replace('filters.', ''))
)
If so, where should I filter my object ?
Thanks in advance for anyone answering this !

Because item.properties is an object, you can access mission also using item.properties['mission'].
In your case you can use
{{ item.properties[label.replace('filters', '')] }}

Related

Multiple VueSelect

I am obtaining from an API the data to fill a v-select type component, the component is filled correctly and I also obtain the options that the user already had assigned (multiple)
And the v-select component are filled correctly
But when i try to add another option occurs the next
Here is the Source Code
<validation-provider
#default="validationContext"
name="skill"
>
<b-form-group
label="Skills"
label-for="skill_id"
:state="getValidationState(validationContext)"
>
<v-select
v-model="itemData.skills"
:dir="$store.state.appConfig.isRTL ? 'rtl' : 'ltr'"
multiple
:options="skillOptions"
:clearable="false"
:reduce="(val) => val.value"
input-id="skill_id"
/>
<b-form-invalid-feedback
:state="getValidationState(validationContext)"
>
{{ validationContext.errors[0] }}
</b-form-invalid-feedback>
</b-form-group>
</validation-provider>
Here i have the array of objects, with multiple elements
itemEdit.value.skills
Then map to get a reduced array with only the value and label
I have probed using only the label without value and the result is the same
const openEdit = item => {
isSidebarActive.value = true
itemEdit.value = item
itemEdit.value.skills = item.skills.map(skill => ({
value: skill.id,
label: skill.skill,
}))
isAdd.value = false
}
Everything apparently goes right, the v-model match correctly with the available options, the problem comes when the user interact with the vSelect to add another item, the already selected items disappear
Thanks in advance
Based on this page o the Vue Select Documentation, the reduce prop is usually meant for use with a label prop, and is only needed if you provide an object to v-select.
I suspect you are providing an array of primitives in your v-model (ie itemData.skills is an array of strings) instead of an array of objects. If it is an array of objects instead, then I suspect you either don't have a [label] key on the object (the default that label is set to), or you don't have a [value] key (what you are trying to return with your reduce prop).
Ideally, you would give us an example of your data coming in for us to be able to help you better.
thanks for listen, the problem was solved removing:
:reduce="(val) => val.value"
From
<v-select
v-model="itemData.skills"
:dir="$store.state.appConfig.isRTL ? 'rtl' : 'ltr'"
multiple
:options="skillOptions"
:clearable="false"
:reduce="(val) => val.value"
input-id="skill_id"
/>

Vue-Multiselect - Set value to an attribute of the object instead of the entire object

I am using vue-multiselect with an array of objects which is working just fine. However, I need to pull the ID from the object to use in order for the API to accept the format.
For example, I can handle this format just fine:
<script>
{// person
id: 1
shirt: {
id: 1
color: 'blue'
}
}
</script>
// in my html, this works well, but I'd like to do formData.person.shirt_id and have multiselect set the id from the entire object instead of setting the entire object.
<multiselect
v-model="formData.person.shirt"
:options="shirts"
:searchable="true"
placeholder="Select a shirt">
</multiselect>
But I'm looking to set "shirt_id" instead of an entire shirt object.
Is there a simple solution to do something like this with vue-multiselect?

Vue JS - How can you ensure the same item from the common list <v-select> does not get selected twice in multiple components?

Quick Context:
I have a parent Parent.vue that feeds the same list
[{key: "one", selected: false], {key: "two", selected: false}, {key: "three", selected: false]
to multiple components one the same page. None of the items in the list can be selected twice.
What I have tried:
So my parent creates a Child.vue component and passes in this list. Child.vue props accepts it then populates the :items fields of the <v-select>. As a result we see all 3 items. I select "two". I bind to change event so I $emit to parent the key ("two") and the flag (selected: true) so the parent filters out the list so there is only "one" and "three" now. If I were to add another component at this point - all fine - it would only have "one" and "three" to select from. My problem is that when I select this "two" item - it disappears. Primarily because the parent takes this item out. But... how to I make it so it either stays (indicating that this item have been selected) and other components are not able to select it no more? Can I possible disable just this "two" item for selection (in case other components try to select it - they can't).
I can do it easily with plain HTML and JS - with Vue / Vuetify - how can I accomplish that?
You can do this by adding a property called disabled to your item and compute the value of that property based on the selection of other items:
get filteredItems() {
return this.items.map((item) =>
id: item.identifier, // replace this with the items identifier
text: item.text_value, // replace this with your items display text
disabled: this.items.filter((item) => [...this.firstSelection,...this.secondSelection].filter((selection) => selection === item).length > 0)
// ^ replace the above destructured array params with your real v-model bindings
// if the v-models bindings aren't arrays (and the select isn't multiple)
// then there is no reason to destructure that value
})
}
Now modify your v-select component and add a value for the item-disabled property that matches the key that we can lookup in the map:
<v-select :items="filteredItems" item-text="text" item-id="id" item-disabled="disabled"
So what I ended up doing is binding to :item-disabled property- I bind selected to and maintain it from the parent throughout all the child components. It get deselected - I emit the event to the parent saying hey element by id "this" is no longer selected. That in turn refreshes it for all the components that are getting this list through props. Ohgodwhy has a pretty similar solution (thanks!).

Vuejs Render list of Array based on key values

I have a dataArray with data like this:
dataArray: {'stat1': 'stat1stat', 'stat2': 'stat2stat', 'stat3': 'stat3stat'}
and so on with hundreds of statistics in the array.
I have been outputting things hard coded in the vue template like this:
{{dataArray.stat2}}
{{dataArray.stat3}}
..etc
What I would like to do is have a new array that specifies the keys I want to render. So something like this:
dataToShow: ['stat2', 'stat3']
And then somehow I could do a loop or v-for to only show the data that is in dataToShow
I've tried a few different ways and I can't get it to work. I think it needs to be a computed property but it isn't working.
Can anyone give some advice on how to implement this?
Wouldn't it just be this?
<template v-for="property in dataToShow">
{{ dataArray[property] }}
</template>
Plus any relevant markup for each entry.
dataToShow could be a computed property as you've suggested but it could just as easily be in your data:
data () {
return {
dataArray: {
stat1: 'stat1stat',
// etc.
},
dataToShow: ['stat2', 'stat3']
}
}

Vue Multi-select not showing all the options

I'm using https://vue-multiselect.js.org in my Vue component. I am using AJAX to update the select list option, and I see in the inspector that there are 10 values.
But when I actually click into the multiselect list, I only see a subset of these items and I can't figure out why.... Here are my multi-select props/events:
<multiselect
v-model="organization"
:allow-empty="true"
:loading="loading"
:options="organizationSearch"
:preserve-search="true"
#search-change="searchOrganizations"
#select="organizationSelected"
#remove="organizationDeselected"
placeholder="Search Organizations"
label="name"
track-by="id"
class="multiselect my-3"
>
</multiselect>
I figured it out. I dug into the component code a bit and found that all the options WERE in the options prop, but there were only 3 in the filteredOptions computed field. I added
:internal-search="false" into my component and then this fixed it.
I think the ultimate issue here had to do with conflict between the internal filtering, and the dynamic update of the options I was doing via AJAX.
Below is the definition of filteredOptions in the actual component definition.
It could be more helpful if you expand the options array in the inspector, so we could see what properties are presented in the objects.
track-by is used to identify the option within the options list thus it’s value has to be unique.
You set track-by="id" and label="name", so your options array should look something like this:
options: [
{ id: 1, name: 'Option #1' },
{ id: 2, name: 'Option #2' },
{ id: 3, name: 'Option #3' },
],
Make sure that all the items in your options array have an id property and it is unique for all of them, because the items with the same id will not appear in the multiselect list.
This depends on the structure of your options.
It shows that they are objects when they should probably be literal values.