how do you do this? I have a method that gets called on a select where on change I want to hide everything else thats not the selected attribute. When the see all option is picked, everything should be shown.
The thought process is to leverage v-model to check if its equal to a data attribute and hide everything else otherwise. If all options are selected, the v-model (in this case, "selectedDep") equals out to just nothing, show them all.
Vue.js v-if for attributes
is only talking about adding the attr which is not my problem.
I'm trying to do something like this:
Select Tag:
<select type="text" id="job-teams" #change="onDepChange($event)" placeholder="Filter By Department" name="teams" v-model="selectedDep">
<option value="">All Departments</option>
<option v-for="listing in listings" :value="listing.title">{{ listing.title }}</option>
</select>
Div I want to hide based on selected option (this is where I'm stuck)
<div v-for="listing in listings" :data-department="listing.title" v-if="selectedDep === '' || selectedDep === data-department">
Data
data: {
listings: [],
locations: [],
message: 'job postings',
selectedDep: '',
error: null
},
Method
onDepChange: function(event) {
this.selectedDep = event.target.value
console.log(this.selectedDep)
}
the first attempt looks like this:
<div v-for="listing in listings" :data-department="listing.title" v-if="selectedDep === '' || selectedDep === data-department">
This throws multiples of the same error in the console:
Property or method "department" is not defined on the instance but
referenced during render. Make sure that this property is reactive,
either in the data option, or for class-based components, by
initializing the property. See:
https://v2.vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties.
Where is it getting "department"? I don't have "department" but "data-department"? I read the documentation:
Since Vue doesn’t allow dynamically adding root-level reactive
properties, you have to initialize Vue instances by declaring all
root-level reactive data properties upfront, even with an empty value:
If you reference my data object above I'm doing that. The link/documentation is not helpful.
The second attempt:
<div v-for="listing in listings" :data-department="listing.title" v-if="selectedDep === '' || selectedDep === :data-department">
I thought maybe adding a colon would do it but
[Vue warn]: Failed to generate render function:
SyntaxError: Unexpected token ':' in
Is apparently a syntax error so that doesn't work.
v-show based on select option data attribute value
This answer only seems to address boolean values (true/false) not comparing several data attribute values.
To conclude
In the context of vue js, how do you do: "if the selected item in a dropdown matches the data attribute of a div - show that one and hide everything else, otherwise if its empty show them all" ... ?
You don't need a v-if for controlling what data you want to display. Also, you shouldn't use v-if on the same tag as with v-for (more on this here).
Solution: create a computed value and list that with a v-for.
new Vue({
el: "#app",
data: {
listings: [{
title: "Listing 1",
},
{
title: "Listing 2",
},
{
title: "Listing 3",
},
],
locations: [],
message: 'job postings',
selectedDep: '',
error: null
},
computed: {
selectedListing() {
return this.selectedDep ? this.listings.filter(({
title
}) => title === this.selectedDep) : this.listings
},
},
methods: {
onDepChange: function(event) {
this.selectedDep = event.target.value
console.log(this.selectedDep)
}
},
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<select type="text" id="job-teams" #change="onDepChange($event)" placeholder="Filter By Department" name="teams" v-model="selectedDep">
<option value="">All Departments</option>
<option v-for="listing in listings" :value="listing.title">{{ listing.title }}</option>
</select>
<div v-for="listing in selectedListing" :department="listing.title">
{{ listing.title }}
</div>
</div>
Ok I figured it out: vue,js doesn't like comparing something to data-department (I don't know why, if anyone reading wants to leave a comment explaining why, much appreciated) you instead have to compare to the object value (in this case, listing.title)
So:
<div v-for="listing in listings" v-if="selectedDep === '' || selectedDep === listing.title">
Related
I am retrieving a list of data from an api and need to fill the specific <select></select> tags, which is associated to a few radio button, with some of the data as <options></options>. The radio buttons waiting for an event (#change/#click) and executing and axios get request. Everthing works fine. I click on a radio button and retrieving the data as response (vue tools also showing the right data) but the <option></option> tags are not updating. Now when I click on another radio button, I am getting again the right data from the api BUT now the <option></option> tags are refreshing with the data from the previous response.
Template
<!-- CREATING 7 RADIO BUTTONS FOR THE CURRENT WEEK FROM MON-SUN -->
<div class="wrapper" v-for="item in inputDetails">
<input :id="'datetime[0]['+item.labelText+']'" type="radio" name="datetime[0][date]" v-model="formData.datetime[0].date" :value="item.inputValue" #change="getTimes" />
</div>
<!-- CREATING THE TIME PICKER -->
<select id="datetime[0][time]" name="datetime[0][time]" v-model="formData.datetime[0].time">
<option selected="selected"></option>
<option v-for="item in selectOptionTimes[0]" :value="item.value">{{ item.label }}</option>
</select>
<!--
2 MORE RADIO BUTTON SECTION AND TIME PICKER SECTIONS WITH DIFFERENT INDEXES
<input id="datetime[1][time]"...
-->
Script
data() {
return {
formData: {
datetime: [
{date: '', time: ''},
{date: '', time: ''},
{date: '', time: ''},
]
}
selectOptionTimes: [],
}
},
methods: {
getTimes: function (current) {
let instanceIndex = current.currentTarget.id.match(/(?<=\[)([0-9])(?=])/g)[0]; // getting the index of the current datetime section
axios.get('/api-url', {
params: {
location_id: this.formData.location_id,
date: current.currentTarget.value
}
}).then(response => {
this.selectOptionTimes[instanceIndex] = response.data;
});
}
}
Does someone know what the problem is here?
You cannot assign a value to an arbitrary index within an empty Array in this way. You must either completely replace the Array with values that hydrate that index, or you must use $set.
So, to recap:
BAD
this.selectOptionTimes[instanceIndex] = response.data
GOOD
this.$set(this.selectOptionTimes, instanceIndex, response.data)
Note though, that this has an unintended consequence. If you have an empty array, and call this.$set on an index greater than 0, the array will be filled with empty values up to your index.
What might make more sense is using an {} instead along with this.$set and looping over the Object.keys instead of the array directly.
Fiddle showing $set on index with an empty array
Fiddle showing Object usage instead
How do I set the first option as a default value in dropdownlist?
<select :disabled=true class="custom-select" v-model="Status">
<option disabled value>Select Any</option>
<option v-for="status in statusList" v-bind:value="{StatusId:status.StatusId,StatusName:status.StatusName}" :key="status.StatusId">{{ status.StatusName }}</option>
</select>
Here v-model="Status" is an object. So, when I have set it like below It's not working:
data() {
return {
Status: 1
};
},
Here, 1 is the id of first option.
Status needs to be an object as well if you want it to match.
data() {
return {
Status: { StatusId: 1, StatusName: 'name' }
}
}
All of the properties of your default Status will need to match one of the options in order for it to be selected.
But note that there is probably no good reason here to use this pattern of setting the option value to an object. Better to set it to the StatusId, and use that selected id or a computed to process the option wherever you need to use it.
I'm using v-validate with Vue. I'm trying to figure out how to force v-validate to update rules. For example, I have something like this:
<template>
<div v-for="field in fields">
<input :name="field.name" v-validate="field.rules">
</div>
</template>
<script>
export default {
data() {
fields: [
{
name: "city",
rules: {
included: []
}
}
]
}
}
</script>
As you can see, my "included" array is empty on page load. I get the array from an AJAX request, and then I update my data:
this.fields[0].rules.included = cities
But v-validate doesn't seem to acknowledge the newly-added array. It only works if I hardcode the cities into my data. How can I force v-validate to respond to the updated rules?
Vue.js is unable to track updates on nested reference types.
Try:
let fields = [...this.fields]
fields[0].rules = cities
this.fields = fields
Use Vue.set to track changes : https://v2.vuejs.org/v2/guide/reactivity.html
Vue.set(this.fields[0], 'rules', cities);
Context: I receive from Elasticsearch the result of a search (example below) which I put into a Vue.js data object. I then list the data via <div v-for="result in results">{{result.name}}</div>.
var vm = new Vue({
el: "#root",
data: {
results: [{
'name': 'john',
'big': true
},
{
'name': 'jim',
'tall': true
},
{
'name': 'david'
}
]
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.3/vue.js"></script>
<div id="root">
<div v-for="result in results">{{result.name}}</div>
</div>
I now would like to filter the results. To do so, I will have switches which will be bound via v-model.
Question: what is the correct way to handle filtering in Vue.js?
I would like to render (via a v-if, I guess) only elements from results which match a filter (say, big is checked - so only johnshould be visible), or a concatenation of filters (logical AND).
The part I have a hard time turning into Vue.js philosophy is "display the element if all active switches are present (value true) in that element).
Since I am sure that having a chain of v-ifs is not the right approach, I prefer to ask before jumping into that (and I would probably rather rerun a search with parameters than go this way - but I would prefer to avoid the search way).
Create a computed property which returns only the filtered results:
computed: {
filteredResults() {
return this.results.filter((result) => {
// your filter logic, something like this:
// return result.big || result.tall
});
}
}
And use it in the v-for instead:
<div v-for="result in filteredResults">{{result.name}}</div>
I can't seem to find the way to filter my options in my drop down.
<div>
<select>
<option ng-repeat="draw in draws| filter:{draw.perform == true && automatic == false}">
</option>
</select>
</div>
data looks like :
{
automatic: true,
date: 1417388400000,
drawQuantity: 0,
number: 1,
offer: {
image: "/"test,
number: 1
},
perform: true
}
I get the data from firebase, that's why i need to do filtering on frontend. If anyone was wondering.
Your syntax is incorrect. Try this instead:
ng-repeat="draw in draws| filter:{perform: true, automatic: false}"
If you need to filter by property values you should use object notation.