Vue update props on select options - javascript

I'm using vue cli and I have a select to display a dropdown list of measurements. I’m wondering how I can update props when I select a measurement?
I have a user profile card that opens a modal with a chart displaying measurement for that user and when I'm in the modal I would like to select another measurement and display that instead.
So when I click on volume, the chart text changes to volume and displays volume data for that user.
I tried to do it for text of the chart via an event listener #change but the props are not passing down and changing the text:
Select: <select name="show" class="show" v-model="value" #change="newText($event)">
<option :value="{ text: 'Volume'}">Vol</option>
<option :value="{ text: 'Weight'}">Weight</option>
<option :value="{ text: 'Temperature'}">Temp</option>
</select>
<script>
newText: function(event) {
const text = this.value.text;
this.text = text;
},
<script>
Here is a codesandbox example.
Any help would be great, thanks!

You need to find the user object and render the value of that user. Here I find the clicked user using computed property inside the tab and render the value of that user. codesandbox .
Computed inside Tabs.vue :
computed: {
selectedUser() {
if (this.name) {
let name = this.name;
return this.users.find(e => e.name == name);
} else return {}
}
}

Related

VueJS - when updating the list of options, the input label changes (the value remains the same)

I have a custom X-Select that acts like a select input. It expects two props - value and options.
The problem is that when options are reloaded in the parent component (root), they are usually prepended with a new item. In that case, select changes its label (like the index stayed the same) even if value hasn't changed.
Example:
options = [{value:'3', text:'3'},{value:'2', text:'2'},{value:'1', text:'1'},}]
current value = '2', current label = '2'
// options have been reloaded and one more item appeared at the beginning
options = [{value:'4', text:'4'},{value:'3', text:'3'},{value:'2', text:'2'},{value:'1', text:'1'},}]
current value = '2', current label = '3'
As you can see the value now does not correspond to the label. I think it's because something wasn't refreshed properly (label '2' was on index 1 and now label '3' is on that index).
<template>
<select id="type" name="type" :value="value" #input="$emit('input',$event.target.value)"
class="select form-control w-75 mx-auto">
<option v-for="option in options" :value="option.value">
{{ option.text }}
</option>
</select>
</template>
<script>
module.exports = {
name: "XSelect",
props: ['options', 'value'],
}
</script>
ROOT
<x-select :key="form.sourceUniAccountId" v-model="form.sourceUniAccountId"
:options="sourceInputOptions"
class="form-select"></x-select>
COMPUTED
sourceAppUniAccounts() {
if (!this.userUniAccounts) return []
return this.userUniAccounts.filter(obj => obj.name_or_provider === this.journeySourceAppName)
},
sourceInputOptions() {
return this.sourceAppUniAccounts.map(obj => ({text: obj.identifier, value: obj.uni_account_id}))
}
The variable userUniAccounts is the one that is in fact reloaded.
Do you know how to make this work? Setting key to combination of value and options works but I think there is a more "elegant" option.
<x-select :key="form.sourceUniAccountId+sourceInputOptions.length" v-model="form.sourceUniAccountId"
:options="sourceInputOptions"
class="form-select"></x-select>

Update state from <select> tag using onChange and filter through list of categories to display blog posts from that category

I'm rendering a dropdown list of categories dynamically by storing the names of these categories in strings within an array and want to update my list of blog posts based on which category is selected in the dropdown.
The category array looks like this:
const tags = ['Sustainability', 'Electrical', 'Mechanical', 'Engineering']
I'm then mapping through this array to display these strings in a select tag dropdown like so:
<div className='col-span-8 md:col-span-2'>
<select
placeholder='Categories'
onChange={handleChange}>
<option value='' selected disabled hidden>
Choose Category
</option>
{tags.map((t) => (
<option>{t}</option>
))}
</select>
</div>
I then have a list of blogs coming from Prismic (headless CMS) which I have stored in state, and am mapping through to list them out in the UI. I've stored these in state called selectedBlogs like so:
const [selectedBlogs, setSelectedBlogs] = useState(blogs);
And mapped through like so (this just displays every blog currently)
{selectedBlogs.results.map((blog) => (
<SwiperSlide key={blog.data.title} className='blog-wrap1'>
<a
href={`/resource/${blog.slugs}`}
className='h-full object-cover'>
<img src={blog.data.image.url} alt='' />
<div className='absolute bottom-5 text-left text-white p-5 w-full font-header'>
<h1 className='text-2xl overflow-ellipsis'>
{RichText.asText(blog.data.title)}
</h1>
</div>{' '}
</a>
</SwiperSlide>
))}
Simply put, I want to update this list of blogs based on which Category is selected in this dropdown, and when it is selected filter the blogs and display only those within that category.
I know I need to use an onChange in the select tag which I have but how can I store the dropdown item which is selected and re-render my blog posts based on that?
Many thanks in advance for any guidance!
I assume this is how you set your handleChange function, and after that do the following step :
const tags = ['Sustainability', 'Electrical', 'Mechanical', 'Engineering']
const [selectedBlogs, setSelectedBlogs] = useState(blogs);
/* you need this below state to store selected tag */
const [selectedTag, setSelectedTag] = useState("")
/* handle the value selected from the form option */
const handleChange = (e) => {
const selected_tag = e.target.value;
setSelectedTag(selected_tag)
}
useEffect(() => {
const filtered_blog = blogs.filter(blog => blog.data.tag === selectedTag);
setSelectedBlogs(filtered_blog)
}, [selectedTag]) // <--- listen to the changes on selectedTag that trigger this
// Then your selectedBlogs will update everytime you change the tag
I would introduce a new state to set the filter like so:
const [filter, setFilter] = useState('')
And then set the state with an onClick() handler on the select element.
Since this is not an input-field where we can track the change of each letter, i wouldn't use onChange.
<option onClick={()=>setFilter(t)}></option>
You should be able to pass that state into a filter-function:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/filter
To make sure the filter-function runs whenever the state of our filter-state changes I would wrap it in a useEffect-hook:
The useEffect hook takes in a state at the end. The function inside the hook runs once whenever that state gets updated. I your case whenever you update the 'filter' state by clicking on a tag.
useEffect(()=>{
console.log(your-filterfunction)
},[filter])

VueJS Component with datalist not showing options

I am utilizing VueJS and it's components to build a large series of datalists and selectors.. all with a submit button at the end of it when the form is validated...
so far I can make a datalist inside a component that renders options and has type completion.. works great! BUT when I attempted to turn the thing into a VueJS Component, and pass in the dataarray as a property... my list of options no longer render
Two Datalist elements...
Top one is the "raw" datalist, which works 100%
But when I goto the vue.js component version, nothing shown as an option...
it's just not there, when I mouse over like the first one...
The datalist VueJS Component
<template>
<div>
<input type="text" v-model="item" list="data_input" v-on:input="selectionChanged">
<datalist id="yourdatalist">
<option v-for="item in data_input">{{item}}</option>
</datalist>
</div>
</template>
<script>
export default {
name: 'Datalist',
props: ['inputDataList'],
data () {
return {
selection: '',
item:'',
data_input:this.inputDataList
}
},
methods: {
selectionChanged: function(element) {
console.log("selection = "+this.selection+", new value = " + element.target.value);
var newSelection = element.target.value;
if (newSelection != this.selection) {
// newSelection changes on every keystroke, so you must keep diffing it with your known data
for (var i=0; i<this.data_input.length; i++) {
if (this.data_input[i] == newSelection) {
this.selection = newSelection
console.log("selection = "+this.selection+" now");
this.$emit('selectionChanged', this.selection);
}
}
}
},
},
}
</script>
The calling component HTML code
<p>Examples of Datalists</p>
<input type="text" v-model="film" list="films" v-on:input="filmChanged">
<datalist id="films">
<option v-for="film in films">{{film}}</option>
</datalist>
<div v-if="focusedfilm">
<h6>You have picked {{focusedfilm}}</h6>
</div>
<br/>
<p>Examples of Child Component Datalist</p>
<Datalist :inputDataList="films"/>
Set the attribute 'list' equal to the attribute 'id' of the datalist.
Change
<datalist id="yourdatalist"> to <datalist id="data_input">
Regards
If Alfredo Lanzetta post his answer, you should accept his because he came with it first. I just want to explain why the solution works.
If you have the following code where you want a dropdrown list for an input field
<input type="text" v-model="item" list="data_input" v-on:input="selectionChanged">
<datalist id="yourdatalist">
<option v-for="item in data_input">{{item}}</option>
</datalist>
To correctly assign the datalist to the input field, the input field needs to have a link to said datalast. You can do that with the list property of the input field.
The way to link the two, is to set the list property of the input field to the id of the datalist. As you can see in example from your code, the datalist has the id yourdatalist but the input field has de list property set to data_input, thus it is looking for a datalist with the id data_input. Since there is no datalist with said id, you don't get to see that dropdrown list.

Angular - load select values on page reload

I have a combo box 2 that updates when the values of another combo box 1 are selected. To do this I used an onChange() function. But when I save my objects and reload the page, only the values of combo box 1 are shown. I think that's because the values of combo box 1 are loaded in the onInit() function, while combo box 2 waits for the onChange() method to be called.
Is there a way to load the stored values on combo box 2 too? Here's my code (only the relevant part, if other code is needed I'll provide it).
view
<div>
<select (change)="onChange($event.target.value)" [ngModel]="model.mycombo1" name="mycombo1" id="mycombo1">
<option disabled hidden [value]="unusedValue">Scegli...</option>
<option *ngFor="let d of combo1" [value]="d.id">{{d.descrizione}}</option>
</select>
</div>
<div>
<select [ngModel]="model.mycombo2" name="mycombo2" id="mycombo2">
<option disabled hidden [value]="unusedValue">Scegli...</option>
<option *ngFor="let d of combo2" [value]="d.id">{{d.descrizione}}</option>
</select>
</div>
component
export class InsertComponent implements OnInit {
combo1: Combo[];
combo2: Combo[];
constructor(private comboSrv: ComboService) { }
ngOnInit() {
this.comboSrv.getCombo1().then(dst => {
this.combo1 = dst;
});
}
onChange(idCombo1: number) {
this.comboSrv.getCombo2(idCombo1).then(dst => {
this.combo2= dst;
});
}
}
I solved it getting my combo2 values in the onInit function too. Otherwise the view doesn't know how to initialise the combo box when the page loads. Hope this tip helps someone.

Dynamically filled HTML select, change selected visual . Blade Laravel template

I have this code. I'm working in Blade template by Laravel framework.
<select class="form-control" name="id_zupanije" id="id_zupanije" onchange="popuniGradove(this, document.getElementById('id_grada'))">
#foreach($zupanije as $zupanija)
#if($zupanija->id == $idzupanije)
<option value="{{$zupanija->id}}" selected="selected">{{$zupanija->naziv_zupanije}}</option>
#else
<option value="{{$zupanija->id}}" selected="">{{$zupanija->naziv_zupanije}}</option>
#endif
#endforeach
<option value="0" selected="">--Odaberite--</option>
idzupanije is id of the select option that needs to be selected...
javascript function "popuniGradove" is for creating select options for another select.
What I want to know is how to visual update selected option, so when window loads I see created select and showing me selected option, not this one
"--Odaberite--".
EDIT
here is screenshoot of how it looks..
I have 3 selects.. first is Zupanija (eng. "province"), Grad (eng. City), Kvart (eng. quart).. when I select zupanija, select grad is filled with options -> cities that have foregin key id_zupanija in table .. samo for kvart, after city is selected, javascript creates options with proper kvarts
... After I press submit (bnt Filtriraj) I refresh the page and filter results below... but I want my selects to save their choosen options before before submiting.. they keep showing --Odaberite-- (default option, last created) afer submiting..
If I understand you right you could consider using a Package like the old laravel 4 FormBuilder.
E. g. https://github.com/kristijanhusak/laravel-form-builder
That way you can bind every form to the respective model like so:
{!! Form::model($user, array('route' => array('user.update', $user->id))) !!}
Laravel automatically checks if input is existing in cache and will attach that data to the form.
You have to add 2 selectize, in this example we have first one for states (for example) and a second one for cities (for example). when we select a state the page send an ajax request to fetch cities in this state, then we set cities list on the cities' select.
the state select :
<select id="select-cities-state" class="selectized">
<option value="1">State 1</option>
...
</select>
the cities select :
<select id="select-cities-city" class="selectized" disabled="">
<option value=""></option>
</select>
var xhr;
var select_state, $select_state;
var select_city, $select_city;
$select_state = $('#select-cities-state').selectize({
onChange: function(value) {
if (!value.length) return;
select_city.disable();
select_city.clearOptions();
select_city.load(function(callback) {
xhr && xhr.abort();
xhr = $.ajax({
url: 'https://jsonp.afeld.me/?url=http://api.sba.gov/geodata/primary_city_links_for_state_of/' + value + '.json',
success: function(results) {
select_city.enable();
callback(results);
},
error: function() {
callback();
}
})
});
}
});
$select_city = $('#select-cities-city').selectize({
valueField: 'name',
labelField: 'name',
searchField: ['name']
});
select_city = $select_city[0].selectize;
select_state = $select_state[0].selectize;
select_city.disable();

Categories