Vue.js multiple select to populate another multiple select - javascript

Is it possible to have two multiple select fields, and the second select options will be filled based upon what is selected in the first select?
Explanation:
Each category has many descriptions related to them.
The main select menu is called "categories", and the options are static, they don't change.
The second select menu is called "descriptions".
I can select as many categories as I want. If I select one category, the second select menu will have all descriptions related to that category as the options. When I select another category in the category select field, the descriptions related to that category will be added to the second select menu, and so on. Same goes for deselecting. I want it to be reactive.
I have found these:
https://github.com/sagalbot/vue-select
https://github.com/monterail/vue-multiselect
But I haven't been able to find a solution to do this with two multiple selects yet. Any pointers?
PS. There are not too many categories and descriptions, so I can load them all into the view so vue can play around with them. I don't need an ajax call.

You need to populate the second select dynamically and update its data source based on events coming from the first one.
Here's a small sketch, I hope it helps.
<template>
<div class="root">
<!-- initial select (options hardcoded) -->
<select v-on:change="populate($event)" multiple="multiple">
<option value="1">One</option>
<option value="2">Two</option>
</select>
<select>
<!-- options variable is reactive -->
<option v-for="option in options" :value="option.value">{{option.text}}</option>
</select>
</div>
</template>
<script>
export default {
name: 'Selects',
data () {
return {
options: []
}
},
methods: {
populate (event) {
const options = []
// iterate over the selected options
// event.target.selectedOptions is a HTMLCollection
Array.from(event.target.selectedOptions).forEach(item => {
// or whatever logic you need
options.push({
value: item.value,
text: `You have selected ${item.text}`
})
})
// update the options attribute to trigger re-rendering
this.options = options
}
}
}
</script>
Later EDIT
jsfiddle here -> https://jsfiddle.net/bpgp11da/

Related

How to autofill textboxes with attributes of the selected object from a dropdown list

In my html page, I want to autofill textboxes with informations(common Name, location,..) of the selected object (shop) from the dropdown list without refreshing the page.
this is the dropdown list:
<select id="shops" class="form-control">
<option value="">Choisir</option>
<option th:each="shop : ${shops}" th:value="${shop.uuid}" th:utext="${shop.uuid}" onClick = "autofillValues()"/>
</select>
and this is the script:
function autofillValues()){
document.getElementById('commonName').value = $('#shop').find(":selected").val().siret;
}
I tried several codes for 2 weeks and I can't find the solution yet.
As mentioned by Vincent, the data would need to be held somewhere on the frontend. This could simply be an array within your code or be pulled from a backend endpoint via an API request.
If you, for example, had an array like this:
[
{
uuid:"49c03f73-c0c5-4bc6-bde4-4a01f66f86c1",
commonName:'Shop 1',
location:'New York, NY, US'
},
{
uuid:"1cb2eeb7-6618-4a7a-8334-72cb0c90bf2a",
commonName:'Shop 2',
location:'Toronto, ON, CA'
}
]
Inside your autofillValues function, you can filter the array (lets assume it's called shopList) by id and populate your elements.
<select id="shops" class="form-control" onchange="autofillValues(value)">
<option value="">Choisir</option>
<option th:each="shop : ${shops}" th:value="${shop.uuid}" th:utext="${shop.uuid}" />
</select>
function autofillValues(id){
let shop = shopList.find(f => f.uuid == id);
if(shop !== null) {
document.getElementById('commonName').value = shop.commonName;
}
}
I replaced the onclick attr on the options with an onchange attr on the select for simplicity
This is a very basic implementation, but here's it working on JSFiddle
You need to store he values somewhere in the front end in order to not to a contact the server. Lets assume that you store them in an array : shops
The when you call the autofillValues function when you select a option from the drop down.
in this function, you wind the appropriate value from the array and then populate the items.
If you are only concerned about the refresh, the you can do an ajax call and return the item that way

Reset Select Menu to default in the on change event

hello i'm trying to reset the select menu to the defaul option immediatly after new item is selected. I never want the select menu to show the selected item. I have this select menu:
<select name="new-effect" id="new-effect">
<option selected value="add">Add New Effect</option>
<option value="waves">Waves</option>
<option value="spiral">Spiral</option>
</select>
which is handled by
$( function() {
$( "#new-effect" ).selectmenu({
change: function( event, data ){
add_new_effect(data.item.value);
}
});
});
It gets the value, but i can't get it to reset. I've tried the following:
$("#new-effect").val("");
$("#new-effect").val("add");
$("#new-effect").prop('selectedIndex',0);
None of them work and they all result in selected item being shown
If you're just trying to reset the select element back to a default value, there's a couple ways to do it. Here's is one way that will work:
https://jsfiddle.net/mswilson4040/gnLkyexa/5/
<select placeholder="Select a value..." id="new-effect">
<option selected value="add" class="default-selection">Add New Effect</option>
<option value="waves">Waves</option>
<option value="spiral">Spiral</option>
</select>
const defaultOption = $('#new-effect').find('.default-selection');
$('#new-effect').change(e => {
const value = $('#new-effect').val();
console.log(value);
$('#new-effect').val(defaultOption.val());
});
Basically, you need to capture the default value that you want to reset everytime. Once you have that, in your change event, obtain the selected value and do what you need to with it. After that is done, you can then just set the select dropdown back to the value you need it to.
The selected attribute in the HTML is fine to have for the initial render, but that will go away once someone changes the value (which is why you can't rely on it for everything).
Add this to your CSS
option:checked {
display:none;
}
If you only need this to happen for a specific list, then change the selector to #new-effect option:checked.
Now for your JS, do this
$("#new-effect").change(function(e) {
e.target.value = 'add';
});
If you have more than one list, you'll want to programatically select the default option instead of hardcoding it like I did here.

Getting dynamically rendered Vue.js dropdown to work with Select2 library

I am new to Vue so pardon me if this is an easy question. I have a page where I dynamically render a select dropdown and dynamically populate its options based on a computed property called filteredWidgets that depends on selections the user made in other dropdowns. The markup is as follows:
<div v-if="filteredWidgets.length > 0">
<select id="widgetSelect" name="widgets">
<option value="">Select up to two Widgets</option>
<option v-for="widget in filteredWidgets" v-bind:value='widget.id'>
#{{widget.name}}
</option>
</select>
</div>
From the Select2 documentation, it states that this is how you convert the select/option elements to become Select2 multiselect elements:
$(document).ready(function() {
$('#widgetSelect').select2();
});
I can get this to work for a page with a non-dynamically rendered select dropdown. Obviously this doesn't work with Vue because the dropdown is rendered dynamically, and it is based on the computed property selectedWidgets. I need to find a way to get select2 to work at the time this dropdown appears/changes. Here is the computed property method filteredWidgets():
filteredWidgets() {
var filteredWidgets = this.availableWidgets.filter(widget => {
return widget.color == selectedColor && widget.size == selectedSize;
});
return filteredWidgets;
}
While the default select dropdown renders as I want it to and contains the filtered widgets I want, I need to figure out how to apply select2() to the widgetSelect dropdown immediately after it is rendered by Vue. What is the correct way to do this?
watch for changes to filteredWidgets, and call .select2().
watch: {
async filteredWidgets() {
await this.$nextTick() // wait for DOM to update
$(this.$refs.widgetSelect).select2()
}
}
You'll need to add a ref to the <select> so you can access the element directly with this.$refs.widgetSelect, instead of doing something like this.$el.querySelector('#widgetSelect'). The id attr is no longer needed, unless you're using it for something else.
<select ref="widgetSelect" name="widgets">

ngOptions selected all options by default and disappearing options on select

I'm having a strange issue I can't seem to troubleshoot with my view. I'm using a directive that generates a treeview of my website. When I select one site, I have two select boxes which populate with the groups in one site and the lists in the site. When the options populate, they are all selected. I've inspected elements and they all have option="selected" Stranger is that, when I click on a single option, all others disappear and only the selected option remains. I've checked the source in Chrome console and yea only the selected option tag remains.
For exmaple the Site Lists select box has multiple options but when I clicked on Old documents, they others all disappeared. In the Site Groups, all groups are already selected
Ctrl:
spApp.controller('sitesCtrl',
function sitesCtrl($scope, $q, $modal, UserService, GroupService, SiteService){
//Options for tree controller directive
$scope.treeOptions = {
nodeChildren: "children",
dirSelectable: true,
injectClasses: {
ul: "a1",
li: "a2",
liSelected: "a7",
iExpanded: "a3",
iCollapsed: "a4",
iLeaf: "a5",
label: "a6",
labelSelected: "a8"
}
}
//Returns siteMap for tree controller directive
$scope.siteMap = SiteService.getSiteMap();
//Returns selected sites information: grous, lists, title, url
$scope.showSelected = function(site){
var siteData = SiteService.getSiteInfo(site);
//sets sites title and url in view
$scope.site = site;
$scope.siteGroups = siteData.groups;
$scope.siteLists = siteData.lists;
}
}
);
View:
<div class="siteGroups">
<label for="siteGroups">Site Groups</label>
<select
multiple
name="siteGroups"
id="siteGroups"
class="siteGroups"
ng-model="siteGroups"
ng-options="g.name for g in siteGroups">
</select>
</div>
<div class="btm1 animated fadeInUp">
<label for="siteLists">Site Lists </label>
<select multiple
id="siteLists"
ng-model="siteLists"
ng-options="l.title for l in siteLists">
</select>
</div>
Service and more of the view
This is happening because the ngOptions in the select lists are bounded to the same array as the ngModel. ngModel needs to be a different array that holds only the selected values.
With siteGroups as an example, what is happening is that the select list options are initialized with siteGroups, and they are all selected because the items are in the ngModel (also the siteGroups array). When you click on one of them, it now removes all other items from ngModel except the one you clicked on. Since ngOptions is bounded to the same list, all the non selected options disappear too.
To fix this, create separate array properties on your scope for the selected values in each list.

AngularStrap Select and ng-options don't work well using dynamic array

I'm using AngularJS with AngularStrap (directive Select, based on Bootstrap-Select made by Silvio Moreto). I have the next problem:
I have an array of car brands. Using ng-options, I put them like options in a select.
By other way, when I select an option (car brand), I get the different models of this car brand, and show them like options in another select.
The problem is when I'm using the AngularStrap directive select, it doesn't work well. The first time i select a car brand, it works fine, but the next selected option (car brand), it shows the models of the car brand selected and the first model of the previous car brand selected.
When I don't use AngularStrap select it works well, therefore i think the problem is in AngularStrap select.
Thanks for your help.
My code is the next:
HTML:
<select ng-model="selectBrand" ng-options="carBrand.id as boatBrand.name for boatBrand in boatBrands" bs-select >
<optionvalue="">CarBrand</option>
</select>
<select ng-model="selectModel" ng-options="carModel.id as carModel.name for boatModel in carModels" bs-select>
<option value="">CarModel</option>
</select>
Controller (JS):
$scope.carBrands = carBrand.query();
$scope.$watch('selectBrand', function() {
$scope.carModels = carModel.query({type_id: $scope.selectBrand});
};
I realize this is old, but I had a similar problem with the Chosen Select plugin and a dynamic list of ng-options. I finally resolved the problem by wrapping my options query inside of a $timeout.
$timeout(function () {
$scope.carModels = carModel.query({type_id: $scope.selectBrand});
});
The only way I was able to use the AngularStrap select support with a select element was to use ng-options and have no option elements as children of the <select>.

Categories

Resources