For some reason that is too long to explain I am trying to modify the behaviour of a select multiple, what I want to achieve is to allow the user to select multiple elements without the need to hold the ctrl/cmd key. this is the html:
<select multiple="multiple" class="form-control">
<option ng-repeat="option in options" ng-click="selectItem(option)" ng-selected="option.selected" value="{{option.id}}">{{option.name}}</option>
</select>
and this is my selectItem function:
$scope.selectItem = (option) => {
let index = $scope.selectedElements.indexOf(option.id);
(index === -1) ? $scope.selectedElements.push(option.id) : $scope.selectedElements.splice(index, 1);
$scope.options.forEach((element, index) => {
element.selected = $scope.selectedElements.indexOf(element.id) !== -1 ? true : false;
});
}
this is partially working: the $scope.selectedElements array is updated and also the $scope.options has the selected property correctly set to true or false. However the select only shows as highlighted the last element I clicked on.
Am I missing something?
Related
I have a Angular5 <select> bound to array of customers. See below:
<select class="form-control" [ngModel]="record.customer_id" (ngModelChange)="setCustomer($event)" name="customer_id">
<option *ngFor="let x of customers" [ngValue]="x.id">{{x.name}}</option>
</select>
In setCustomer function I get an customer's id as 'event'.
Property record.customer_id is type of number, not object. Is there any way how to get a whole customer entity in setCustomer method and also preserve binding to record.customer_id ?
I found on Angular docu a way [compareWith] so I tried:
<select class="form-control" [compareWith]="compareCustomer" [ngModel]="record.customer_id" (ngModelChange)="setCustomer($event)" name="customer_id">
<option *ngFor="let x of customers" [ngValue]="x">{{x.name}}</option>
</select>
and
compareCustomer(c1: customer, c2: number) : boolean {
if (c1 == null || c1 == undefined) {
return false;
}
if (c1.id == c2) {
return true;
}
return false;
}
Does not work. When I select any option, setCustomer is executed, record.customer_id gets selected id. However, after select loses focus, selected option is reset to blank.
There is a workaround (iteration in customers array and manual match by id) that I want to avoid:
setCustomer(event) {
this.record.customer_id = Number.parseInt(event);
customers.forEach(c => {
if (c.id === this.record.customer_id) {
// some logic with selected customer
}
});
}
Any advice?
Thanks!
Instead of bind customer_id, bind the whole object:
<select class="form-control" [ngModel]="record" (ngModelChange)="setCustomer($event)" name="customer_id">
<option *ngFor="let x of customers" [ngValue]="x">{{x.name}}</option>
</select>
I got a bunch of selects:
<select name="paraquien" class="selectpicker form-control paraquien" id="paraquien" onchange="mostrarPreguntas();">
<option value=""><?=__('¿Para quién es el plan?')?><span class="glyphicon glyphicon-triangle-bottom"></span></option>
<option value="1"><?=__('Para mi')?> <span class="glyphicon glyphicon-triangle-bottom"></span></option>
<option value="2"><?=__('Para regalar')?><span class="glyphicon glyphicon-triangle-bottom"></span></option>
</select>
and I would like to know if all of them have been selected, and in that case trigger an event. I've tried this far:
jQuery('.paraquien option:selected')
Getting this result array:
[
<option value="1">Para mi </option>,
<option value="1">Hombre</option>,
<option value="3">Estudiante</option>,
<option value>Su situación sentimental</option>,
<option value>¿Tiene hijos?</option>
]
You can see every option selected has a value attribute set, what I would like to know is how to get just the options which value has been already set, in the same selector mentioned before.
Any Idea?
You can use filter() to check for select elements where the value is still ''. Try this:
var $unchosenSelects = $('.paraquien').filter(function() {
return $(this).val() == '';
});
if ($unchosenSelects.length) {
// there was at least one select within nothing chosen...
}
Similarly you could use map() to get all the values in an array, then $.inArray to check for empty strings:
var chosenValues = $('.paraquien').map(function() {
return $(this).val();
});
if ($.inArray(chosenValues, '') != -1) {
// there was at least one select within nothing chosen...
}
I am looking for a simple .js solution. I have two dropdown buttons - code:
<select name="parent_dropdown" id="parent">
<option value="option_01">parent_option_01</option>
<option value="option_02">parent_option_02</option>
</select>
<br />
<select name="child_dropdown" id="child">
<option value="opt01">child_option_01</option>
<option value="opt02">child_option_02</option>
<option value="opt03">child_option_03</option>
<option value="opt04">child_option_04</option>
</select>
Now I need to accomplish this:
When option_01 in #parent is chosen ---> make available only child_option_01 and child_option_02 in #child dropdown
When option_02 in #parent is chosen ---> make available only child_option_03 and child_option_04 in #child dropdown
I tried some solutions I found online but so far no luck. I have a very basic .js knowledge.
Link to FIddle: http://jsfiddle.net/q5kKz/343/
Help will be appreciated.
Taking the next step with your fiddle, this will do (almost) what you want:
$('#parent').change(function() {
$("option[value='opt01']")[$(this).val() == "option_01" ? 'show' : 'hide']("fast");
}).change();
Notice the attribute selector: "option[value='opt01']" - that says "any options with value of opt01".
You should probably expand that selector to be "#child option[value='opt01']"
Using a "basic" programming method, you could do this for multiple options:
$('#parent').change(function() {
$("option[value='opt01']")[$(this).val() == "option_01" ? 'show' : 'hide']("fast");
$("option[value='opt02']")[$(this).val() == "option_01" ? 'show' : 'hide']("fast");
// Adding multiple options here. This is a bad method for maintainability
}).change();
A better way to go would be to assign some sort of other attributes to the options that should show depending on which parent is selected. One example is using a class that matches the parent value desired - which would require modifying your child list like so:
<select name="child_dropdown" id="child">
<option value="opt01" class="option_01">child_option_01</option>
<option value="opt02" class="option_01">child_option_02</option>
<option value="opt03" class="option_02">child_option_03</option>
<!-- The below option would show whenever the parent is on option 2 OR 3 -->
<option value="opt04" class="option_02 option_03">child_option_04</option>
</select>
But then your script could be much more usefully constructed like so, and wouldn't need to be changed if you added / changed options:
$('#parent').change(function() {
var val = $(this).val();
$("#child option")[$(this).hasClass(val) ? 'show' : 'hide']("fast");
}).change();
This still leaves the problem of the list option hiding, and the select can still be set to a "hidden" value. This would need to be addressed somehow. Something like the below:
$('#parent').change(function() {
var val = $(this).val();
$("#child option")[$(this).hasClass(val) ? 'show' : 'hide']("fast");
var child_val = $('#child').val();
// If the selected option is not visible...
if ($('#child').find(":selected").not(":visible")) {
// Set it to the first option that has the proper parent class
$("#child").val($("#child option." + val + ":first").val());
};
}).change();
With newer versions of jQuery you could do something like:
var group1 = $("#child").find("option[value='opt01'], option[value='opt02']");
var group2 = $("#child").find("option[value='opt03'], option[value='opt04']");
$('#parent').change(function() {
var selected = $("#parent").find(":selected").text();
if (selected == "parent_option_01") {
group1.prop("disabled", false);
group2.prop("disabled", true);
} else {
group1.prop("disabled", true);
group2.prop("disabled", false);
}
}).change();
The other people may have it right. But when you want to make changes you have to change a bunch of JS code. I think this is a better approach. In our child HTML we add a data attribute to show what values of parent will make this child option show. This way if we ever need to add more elements or change what ones make the children appear we can just change the HTML and it leaves our javascript a lot cleaner.
http://jsfiddle.net/q5kKz/348/
var parent = $("#parent");
var child = $("#child");
var val;
$('#parent').change(function() {
//Get value of parent
val = $("#parent").val();
//cycle through children and find which data show matches the parent
child.children().each(function(){
var c = $(this);
//Jquery's .data wasn't working for some reason
if(c.attr("data-show") === val){
c.show()
}else{
c.hide()
}
})
}).change();
In the HTML
<select name="parent_dropdown" id="parent">
<option value="option_01">parent_option_01</option>
<option value="option_02">parent_option_02</option>
</select>
<br />
<select name="child_dropdown" id="child">
<option value="opt01" data-show="option_01">child_option_01</option>
<option value="opt02" data-show="option_01">child_option_02</option>
<option value="opt03" data-show="option_02">child_option_03</option>
<option value="opt04" data-show="option_02">child_option_04</option>
</select>
We have two dropdowns that according to your selection it changes part of the string in some div containers. The purpose of this is to return URLs to give to clients.
This is a sample of the code
<select name="lstLanguage" id="lstLanguage">
<OPTION VALUE="">-- Generic default ---</OPTION>
<OPTION ID="Arabic" VALUE="AR">Arabic</OPTION>
<OPTION ID="German" VALUE="D">German</OPTION>
</select>
<select name="lstTemplate" id="lstTemplate">
<OPTION VALUE="">-- Generic default ---</OPTION>
<OPTION VALUE="1">Member</OPTION>
<OPTION VALUE="2">NonMember</OPTION>
</select>
<div id='Ind_URL'>http://example.com/Registration.asp?Language_Code=?Role=</div>
<div id='Ind_W_URL'>http://example.com/Registration.asp?Language_Code=?Role=</div>
<div id='Login_URL'>http://example.com/?Language_Code=</div>
And this is the jQuery we currently have, which was provided by irama.
$(function(){
divIDs = [
'Ind_URL',
'Ind_W_URL',
'Login_URL',
];
$('#lstTemplate').bind('change', function(){
role = $(this).find('option:selected').val();
updateURLDivs(langCode=null, role);
});
$('#lstLanguage').bind('change', function(){
langCode = $(this).find('option:selected').val();
updateURLDivs(langCode, role=null);
});
updateURLDivs = function (langCode, role) {
for (i in divIDs) {
currentDiv = $('#'+divIDs[i]);
if (langCode !== null) {
currentDiv.data('Language_Code', langCode);
}
if (role !== null) {
currentDiv.data('role', role);
}
// Cache original div contents, so that the select menu can be changed more than once.
if (typeof currentDiv.data('contents') == 'undefined') {
divContents = currentDiv .html();
currentDiv .data('contents', divContents);
} else {
divContents = currentDiv .data('contents');
}
currentDiv.empty().append(
divContents
.replace('role=','role='+currentDiv.data('role'))
.replace('Language_Code=','Language_Code='+currentDiv.data('Language_Code'))
);
}
}
});
This is working fine, but this morning we found a few issues
It is currently updating both parameters, no matter if you change one or both. We need it to update if you change the template, just the template and if you change the language just the language.
If nothing is selected we need it to replace it with a blank not with undefined as it is currently doing
If we change the Template it also needs to replace Registration.asp to PersonImport.asp from the URLs
This is how it should work
The div containers need to have the default URLs in them
If I change the language (lstLanguage) it should just change the Language_Code on the DIV containers. Then if I select the language option with no value ("Generic default") the Language_Code should be blank ''
If I change the template (lstTemplate) it should change the Role on the DIV containers. Also should change Registration.asp to PersonImport.asp. Then if I select the template option with no value ("Generic Default) the Role should be blank '' and PersonImport.asp should go back to Registration.asp.
I'm not a good coder on this, but it would be great if any of you can give me a hand with this.
Thanks in advance
Federico
I have create a fiddle with a lot of improvement in your code. Take a look.
Working demo
I have 2 select boxes on a page with a variable number of options in them.
For instance:
<fieldset>
<label for="fizzwizzle">Select a Fizzwizzle</label>
<select name="fizzwizzle" id="fizzwizzle" size="10">
<option>Fizzwizzle_01</option>
<option>Fizzwizzle_02</option>
<option>Fizzwizzle_03</option>
<option>Fizzwizzle_04</option>
</select>
</fieldset>
<fieldset>
<label for="fizzbaggot">Select a Fizzbaggot</label>
<select name="fizzbaggot" id="fizzbaggot" size="10">
<option>Fizzbaggot_01</option>
</select>
</fieldset>
I would like to verify that both of these select boxes have a selected option. My initial thought is to simply use JQuery but I can't seem to figure out how to do that. My attempts so far have been futile but I have the following code that I think should work with the missing link.
function verify_selectboxen_selection() {
var allSelected = true;
$('select').each(function() {
/* if select box doesn't have a selected option */
allSelected = false;
break;
});
if (!allSelected) {
alert('You must select a Job and a Disposition File.');
}
return allSelected;
}
Seems simple enough. Thoughts?
In jQuery you can use the :selected selector to get the total options selected. This number out to match the number of select's themselves:
if ($("select").length === $("option:selected").length) {
// they match
}
I would like to verify that both of these select boxes have a selected option
It's not possible for a (non-multiple) select box not to have a selected option! If you don't declare selected on one of the options, the browser will automatically select the first option.
So: return true; :-)
If you want to have an ‘unselected’ initial state, you'd have to include a no-option option for it, usually the first one:
<select name="fizzbaggot">
<option value="" selected="selected">(Select a fizzbaggot)</option>
<option>foo</option>
<option>baz</option>
<option>bar</option>
</select>
Then you can check whether a different option to that one has been selected, either by saying:
$('select').each(function() {
if ($(this).val()!=='')
allSelected= false;
});
Or, if you might want to use the empty string as a valid value, you can just look at the index of the selected option:
$('select').each(function() {
if (this.selectedIndex===0)
allSelected= false;
});
You can use the :selected selector for this.
var unselected = []
$('select').each(function(){
if (0 == $(this).find('option:selected').length) {
unselected.push(this.id);
}
});
if (unselected.length != 0) {
// unselected contains the ids of non-selected select boxes
}
Or you could check their values with val(). This presumes that you have a default option with no value (ie empty string value).
var unselected = []
$('select').each(function(){
if ('' == $(this).val()) {
unselected.push(this.id);
}
});
if (unselected.length != 0) {
// unselected contains the ids of non-selected select boxes
}
function checkSelects() {
return $("select :selected").length == $("select").length;
}
alert(checkSelects());