How to target a select option based on data attribute? - javascript

I'm new to JavaScript and jQuery. I'm trying to create something for a website I'm working on, but I can't figure this out.
How can I get jquery to show or hide a select option of a dropdown, based on the selected data attribute of another dropdown?
IE, selecting option 2 in the first dropdown will show only options 1 and 3 in the second menu, and vice versa?
$(document).ready(function() {
$("#make_id").change(function() {
/* basically if data-make is = to selected data-id option, show option,
if it isn't, hide this option. seems, simple, but I can't figure it out... */
})
})
<select id="make_id" >
<option value="make option 1" data-id="18">option 1</option>
<option value="make option 2" data-id="42">option 1</option>
</select>
<select id="model_id" >
<option value="model option 1" data-make="42">option 1</option>
<option value="model option 2" data-make="18">option 2</option>
<option value="model option 3" data-make="42">option 3</option>
</select>

$("#make-id").change(function(e){
var currentMake = $("#make-id").data("id");
$("#model-id option").not("[data-make='"+currentMake+"']").hide();
$("#model-id option").filter("[data-make='"+currentMake+"']").show();
}
In English:
Whenever make-id changes, get the data-id field from it.
Select all the options under model-id then filter for ones that don't have the same data-make value. Hide those.
Select all the options under model-id then filter for the ones that do have the same data-make value. Show those.

TL;DR
I've changed the way your code works a little to make it work better for the way you want it to. Take a look at this fiddle.
So first of all, you can easily define a callback on the change event which can filter the second select box's option visibility. One problem you may come into if you do this is that "hidden" options will still be in the select's value if they were previously selected (as in Franz's answer).
Here's a slightly different approach in which everything is emptied and loaded dynamically from a JSON object that you define initially:
1. Define your JSON object (data model)
This could come from a database as well of course.
var makesAndModels = {
"makes": [
{"option_id": 1, "id": 18, "name": "make 1"},
{"option_id": 2, "id": 42, "name": "make 2"}
],
"models": [
{"option_id": 1, "make_id": 42, "name": "make 2: model 1"},
{"option_id": 2, "make_id": 18, "name": "make 1: model 1"},
{"option_id": 3, "make_id": 42, "name": "make 2: model 2"}
]
};
2. Define methods to populate each select
Your rules are simple:
To populate the makes, you need no conditions
To populate the models, you need a make ID (foreign key)
function populateMakes() {
var $make = $('#make_id');
// Remove all options before starting
$make.empty();
// Loop the makes from the JSON data object
$.each(makesAndModels.makes, function(key, make) {
// Append new options for each make
$('#make_id')
.append(
$('<option></option>')
.data('id', make.id) // Assign the data-id attribute
.attr('value', 'make option ' + make.option_id) // Give it a value
.text(make.name) // Give it a label
);
});
}
The function above is simply emptying the #make_id select box, then looping the makes in the JSON data object and appending a new option element to the makes select for each result, setting the attributes as it goes.
Then to populate the models, we do the same thing for models as we did for makes, except we'll ignore any models that are for a different make.
function populateModels(makeId) {
// Assign the selector to a variable to repeated use/Don't Repeat Yourself
var $model = $('#model_id');
// Remove all models in the select to start
$model.empty();
// Loop the models in the JSON object
$.each(makesAndModels.models, function(key, model) {
// Ignore any models for other makes
if (model.make_id != makeId) {
return;
}
// Append the new model to the select
$model
.append(
$('<option></option>')
.data('make', model.make_id) // Assign its data-make attribute
.attr('value', 'model option ' + model.option_id) // Give it a value
.text(model.name) // Give it a label
);
});
}
3. Simplified HTML
Once you've got that framework, your HTML and event handlers are going to be very simple.
The HTML select boxes don't need any options since they're populated dynamically, although you may want to leave the ones you have there already in place to help with older browsers or browsers with Javascript turned off (cringe):
<!-- These are populated dynamically now! -->
<select id="make_id"></select>
<select id="model_id"></select>
4. Create your jQuery event handler
...and glue it all together:
$(document).ready(function() {
// Populate the makes select box
populateMakes();
// Define what should happen when you change the make_id select
$("#make_id").change(function() {
// Find the currently selected make's ID from data-id
var selectedMake = $(this).find('option:selected').data('id');
populateModels(selectedMake);
});
// Trigger a change to populate the models the first time
$('#make_id').change();
});
The trick above is that once you've populated the makes and defined your event handler for when the makes select box changes, you can to trigger the change event manually - this will cause populateModels() to be called with the first make in the list, and have the models for that make populated too.

$(document).ready(function() {
$("#make_id").change(function() {
if ($(this).val()=='make option 2') $("#model_id").find("option").eq(1).hide();
else $("#model_id").find("option").eq(1).show();
})
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select id="make_id" >
<option value="make option 1" data-id="18">option 1</option>
<option value="make option 2" data-id="42">option 2</option>
</select>
<select id="model_id" >
<option value="model option 1" data-make="42">option 1</option>
<option value="model option 2" data-make="18">option 2</option>
<option value="model option 3" data-make="42">option 3</option>
</select>

Related

How to Modify selected option text & Restore Back text after next option

I want to Modify text contents of dynamically generated drop down list using jQuery. Here is my example:
Drop Down Text look like below:
<select id="s1">
<option data-name="volvo" value="1">1:Volvo</option>
<option data-name="saab" value="2">2:Saab</option>
<option data-name="mercedes" value="3">3:Mercedes</option>
<option data-name="audi" value="4">4:Audi</option>
<option data-name="BMW" value="11">11:BMW</option>
</select>
jQuery:
var previous;
$('#s1').focus(function () {
// Store the current value on focus, before it changes
previous = this.value;
}).change(function() {
//Modify the SelectedOption Display only Number Value
$('#s1').find(':selected').text($('#s1').find(':selected').val());
//Restore the Previous Option : Format 'Number Value : data-name'
alert($("#s1 option[value='"+previous+"']").val());
alert($("#s1 option[value='"+previous+"']").attr('data-name'));
$("#s1 option[value='"+previous+"']").text($("#s1 option[value='"+previous+"']").val() +' '+ $("#s1 option[value='"+previous+"']").attr('data-name'));
});
I also used following attributes :
value: stores number value of that car
data-name: stores the Name of that Car
This is what I want:
Whenever any user select any option, then the selected option text will be modified and removes that Name part: For example: selecting 1:Volvo become 1 only.However if user select another option then the previous option text will be restore back to previous format e.g: 1 becomes 1:Volvo again. That is why i used given attributes to restore format.
I have written a code that works fine if i used alert .But i want to do it without using alert and then it does not work.
Here is my code:
jsfiddle
please help.
You have set data-name and value attributes, so you can easily loop over the options and use those attributes to update the text:
$('#s1').change(function() {
$(this).find('option').each(function(){
$(this).text(
$(this).attr('value')+( $(this).is(':selected') ? '' : ':'+$(this).attr('data-name'))
);
});
});
$('#s1').change(function() {
$(this).find('option').each(function(){
$(this).text(
$(this).attr('value')+( $(this).is(':selected') ? '' : ':'+$(this).attr('data-name'))
);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select id="s1">
<option data-name="volvo" value="1">1:Volvo</option>
<option data-name="saab" value="2">2:Saab</option>
<option data-name="mercedes" value="3">3:Mercedes</option>
<option data-name="audi" value="4">4:Audi</option>
<option data-name="BMW" value="11">11:BMW</option>
</select>
EDIT (comment)
I'd say that with a normal usage, the code above will have no impact on user experience. It will be slower in a mathematics(?) meaning - negligible differences in execution time, as DOM is modified (each <option> is updated) inside $.each() loop, which isn't the best idea. But nothing that usar can notice.
For the OP example, where only 5 options are involved, it's arguable that updating all of them VS updating only 2, won't make any difference in speed. If there would be hundrets of options, then (speaking about user experience) I, as a user, wouldn't be so glad having so many options to pass through, searching the one I need. So the main issue would be there.
But, if there are any concerns about the above script speed, there's another (a better?) way, without using global flags and loops.
It creates a temporary data-last attribute for identifying previously selected <option> and only two options are modified at a time :
$('#s1').change(function() {
$(this).find('option:selected').attr('data-last','Yes').text(this.value)
.siblings('[data-last]').removeAttr('data-last').text(function(){
return this.value+':'+$(this).attr('data-name');
});
});
$('#s1').change(function() {
$(this).find('option:selected').attr('data-last','Yes').text(this.value)
.siblings('[data-last]').removeAttr('data-last').text(function(){
return this.value+':'+$(this).attr('data-name');
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select id="s1">
<option data-name="volvo" value="1">1:Volvo</option>
<option data-name="saab" value="2">2:Saab</option>
<option data-name="mercedes" value="3">3:Mercedes</option>
<option data-name="audi" value="4">4:Audi</option>
<option data-name="BMW" value="11">11:BMW</option>
</select>
And there's a speed comparison between these two methods (200 options) :
JSFiddle

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();

Ng-repeat and auto complete selection with modal window in Angular

I'm doing an application in Angular. It is a Table one row that contain 2 column. Each column contain one select. They are empty. When the user press a button, a modal window shows up and display a grid with all the items (from json) of the first select. When the user click on one rows and press "Confirm", modal window closes filling the first select. In the meanwhile, the second select fill with the subarray of selected item.
In a few words, there are 2 select: you choose the option on the first (by a modal window) and then you choose the item of its subarray in the second select.
Then, the user can add new rows, repeating the select.
I've tried two ways to do this, and they half work. In the FIRST CODE
you can see that, after clicked on modal window, the first select fill it self (even if it is not the first , I don't know why..). And it doesn't not iterate well, because when you choose a item in new line, it modify all the other choises, and I want to prevent this.
<select ng-model="selectedProduct" ng-options="a as a.nome for a in items" ng-change="selectLot(select1)">
<option value="">-- Select Product --</option>
</select>
<select ng-model="selectedLot" ng-options="a as a.value for a in selectedProduct.lots" ng-change="lotSelect(select2)">
<option value="">-- Select Lot --</option>
</select>
The SECOND CODE works better. It iterate well. It change automatically the second item's selection well. But when I press on the modal window, the first selection doesn't automatically fill with the choosen item.
Can you help me? I can't find a solution..... Thank you so much in advice!
The core of the issue is that if you want to have a form that edits elements in an array, you need to have separate models for each of the rows in the array. You can do this by making "selectedProduct" and "selectedLot" into objects that map the array index to the selected value for that row.
I made an updated plunker with a working example, but without looking at it here is a rundown of the changes you would need to make. You need to change your models so they reference something using the array index of the row, and also pass that index into functions that modify the row:
<button class="btn btn-default" ng-click="open($index)">OPEN!!</button>
<select ng-model="selectedProducts[$index]" ng-options="a as a.nome for a in items" ng-change="selectLot(select1, $index)">
<option value="">-- Select Product --</option>
</select>
<select ng-model="selectedLots[$index]" ng-options="a as a.value for a in selectedProducts[$index].lots" ng-change="lotSelect(select2, $index)">
<option value="">-- Select Lot --</option>
</select>
You also want to update the functions in your controller to work with the array indexes:
$scope.selectLot = function(data, index){
$scope.Subarray = [];
for(i=0; i<$scope.items.length; i++){
if(data == $scope.items[i].id){
$scope.Subarray[$index] = $scope.items[i].lots;
$scope.selectedProducts[$index] = $scope.items[i];
break;
}
}
console.log($scope.Subarray);
}
$scope.lotSelect = function(id, $index) {
for(i=0; i<$scope.Subarray[$index].length; i++){
if(id == $scope.Subarray[$index][i].id){
$scope.selectedLots[$index] = $scope.Subarray[$index][i];
break;
}
}
}
And the modal:
$scope.open = function ($index) {
// ...
modalInstance.result.then(function (selectedItem) {
$scope.selectedProducts[$index] = selectedItem;
}, function () {
$log.info('Finestra selezione prodotto chiusa alle ore: ' + new Date());
});
You probably shouldn't be using a SELECT if you are allowing the choice to happen in a modal popup. All you want to do is show the selected item which you can easily do in a number of different ways. Additionally in the first example prodIsChanged(), which is what sets the subarray, is never called. An easier solution may be something like this:
<div>{{mainProduct}}</div>
<select ng-options="a as a.value for a in selectedProduct"></select>
var myApp = myApp.controller('Cntrl', function ($scope,$watch) {
$scope.mainProduct = '';
$scope.selecedProduct = '';
$watch('mainProduct',function(old,new) {
$scope.selectedProduct = ??? // The mainProduct has changed so set the list of sub products as necessary
};
}

Angular: Get the index of the dropdown item

I have the following in my view
<div>
<select ng-model="obj.arr[otherObj.variable]" ng-change="otherObj.variable=SOMETHING">
<option ng-repeat="label in obj.arrs">{{label}}</option>
</select>
</div>
Without the ng-change attribute, this code does what I want when otherObj.variable is one of the indexes of the obj.arr - it selects the correct item in the list.
What I want in addition to this is to set otherObj.variable to the index of the array item that is picked when the dropdown variable is changed. So, if the second value in the dropdown is picked then otherObj.variable should be set to 1. I tried to do this with a
ng-change="otherObj.variable=SOMETHING"
Problem is., I don't know what that SOMETHING should be. Am I doing this right?
EDIT
My requirements are
Select the top option in the dropdown by default
select the appropriate item in the array depending on the value of otherObj.variable (this gets set by some external code so if I come to the page with this value set then I want the correct option selected)
Make sure otherObj.variable is updated if I change the value in the dropdown.
angular.module('selects.demo', [])
.controller('SelectCtrl', function($scope){
$scope.values = [{
id: 1,
label: 'aLabel',
}, {
id: 2,
label: 'bLabel',
}];
$scope.selectedval = $scope.values[0];
});
<script src="https://code.angularjs.org/1.3.15/angular.js"></script>
<div ng-app="selects.demo">
<div ng-controller="SelectCtrl">
<p>Using ngOptions without select as:</p>
<select ng-model="selectedval" ng-options="value.label for value in values"></select>
<p>{{selectedval}}</p>
<p>Using ngOptions with select as statement: (this will return just the id in the model)</p>
<select ng-model="selectedval2" ng-options="value.id as value.label for value in values"></select>
<p>{{selectedval2}}</p>
</div>
</div>
Sorry if my comment was a little cryptic. Select elements like other form elements are actually directives in AngularJS, so they do a lot of stuff for you automatically. You don't need to use an ngChange to populate the ngModel associated with your select element. AngularJS will handle that for you.
Also, you can use ngOptions instead of ngRepeat on select elements to generate the values automatically on options.
Assuming that you have an object with values:
$scope.values = [{
id: 1,
label: 'aLabel',
}, {
id: 2,
label: 'bLabel',
}];
You would write:
<select ng-model="selectedval" ng-options="value.label for value in values"></select>
Now your ngModel is going to be bound to the selected element. It will be set with the value of the object that was chosen. If you add {{selectedval.id}} to your view, it will display the id of the selected element.
If you want to set the value to the first item, in your controller, you would add:
$scope.selectedval = $scope.values[0];
If you want to update some property on $scope.values based on the selected value, you could use something like:
$scope.addActiveProp = function() {
var selected = $scope.values.filter(function(e) { return e == $scope.selectedval; });
selected.active = true;
}
And then run the addActiveProp fn in ngChange on the select.
Please give a try with below code
<select ng-model="obj.arr[otherObj.variable]" ng-change="otherObj.variable=key" ng-options="key as value for (key , value) in obj.arrs"></select>

JavaScript onclick event in a jsp

I am trying to select values on Jsp dynamically from Jsp in a dropdown list based on slection of another dropdown.
For example:I have two drop down1-A,B and drop down2 has values 1 to 10.
So when I select A i want 5 values from dropdown to be selected dynamically based on onclick event.Is it possible??
First, this has nothing to do with JSP. It's client side interaction and you need to use JavaScript to manage this.
If you have dropdown using <select> you need to capture change event for the first dropdown - triggered everythime when the value of the dropdown changes.
To make the code easier to read and avoid cross browsers issues, you may use jQuery to take care of this situation.
Hence, if you have a <select> element with ID set to say dropdown1 you can try this:
jQuery("#dropdown1").change(function () {
var selectedValue = jQuery(this).val();
// Now use to value to do other stufffs
});
However, if you are having a 'dropdown' for the second one it's not possible to select multiple values. One basic option is to convert this dropdown into a list and enable multiple slection using multiple="multiple" (Ref: http://www.w3schools.com/tags/att_select_multiple.asp)
That is, you just need to use <select multiple="multiple">
Now, I am not aware of your requirement and logic to pick up which particular values of the second dropdown for each item of the first dropdown. But, it seems you need to apply your own logic here.
However, let's consider that for value A' of dropdown1 the selected values in dropdown2 will be '1', '2' and '4'; for valueB' of dropdown1 the selected values in dropdown2 will be '2', '5' and '6','8' and '10' you can use code like this:
jQuery( document ).ready( function () {
jQuery("#dropdown1").change(function () {
var selectedValue = jQuery(this).val(),
mappedValues = {
"A": {"1": true, "2": true, "4": true},
"B": {"2": true, "5": true, "6": true, "8": true, "10": true}
},
selectedMappedValues = mappedValues[selectedValue] || {},
dropdown2 = jQuery("#dropdown2"),
dropdown2Options = dropdown2.find('option'),
dropdown2Option;
dropdown2Options.prop('selected', false);
dropdown2Options.each(function () {
dropdown2Option = jQuery(this);
if (selectedMappedValues[dropdown2Option.val()]) {
dropdown2Option.prop('selected', true);
}
});
});
});
Live Example: http://jsfiddle.net/sudipto/uzmbko17/
try this.
this jsp code.
<select id="dropdown1" name="dropdown1" onchange="selectValue()">
<option value="a">A</option>
<option value="b">B</option>
</select>
<select id="dropdown2" name="dropdown2">
<option value="a1">1</option>
<option value="a2">2</option>
<option value="a3">3</option>
<option value="a4">4</option>
<option value="a5">5</option>
<option value="a6">6</option>
<option value="a7">7</option>
<option value="a8">8</option>
<option value="a9">9</option>
<option value="a10">10</option>
</select>
this is javascript function
function selectValue(){
if(document.getElementById("dropdown1").value == a){
document.getElementById("dropdown2").value = a5;
}
}
thats all.thanx.

Categories