I am using knockout options binding and select2 plugin on a select list. Initially i do not want to select any option by default instead i want to show a text something like 'Select country..' and this text should be selected initially. For this i used knockout optionsCaption binding. It works fine, but if i apply select2 plugin on the select list the initial default text is not selected. Here my code:
HTML
<select data-bind="options: array, optionsCaption: 'All'" size="1">
</select>
JS
$('select').select2();
function VM(){
this.array =
['Afghanostan', 'Albania', 'Algeria', 'Argentina'];
}
ko.applyBindings(new VM());
I have created a JSFIDDLE also.
How to solve this issue ?
Try this code
$('select').select2({
placeholder: "ALL"
});
<select data-bind="options: array" size="1" style="width: 200px;">
<option><option>
</select>
See this link http://jsbin.com/ivetel/19/edit
It has to do with the fact that "All" has a value of "". From select2's source:
initSelection: function () {
var selected;
if (this.opts.element.val() === "") {
this.close();
this.setPlaceholder();
} else {
var self = this;
this.opts.initSelection.call(null, this.opts.element, function(selected){
if (selected !== undefined && selected !== null) {
self.updateSelection(selected);
self.close();
self.setPlaceholder();
}
});
}
}
As you can see, it shortcircuits if element.val() === ''. You would need to modify the source of select2 to work with an empty-value option.
Related
How to make a select option not disappear when selected if filtered out and not be displayed on other select dropdowns.
For example
if i have some array of objects, and i make
<select ng-options = "here we go through each object "></select>
My idea is to make filter function that would not display any item that's in the array i'm filling if I selected this item before. So that would be my array of items that should be unavailable in another dropdowns. Is there some example way how can i accomplish that? I have an idea that my filter would look something like this:
for(var i=0;i<$scope.removedIds.length;i++){
if(tab.tabID===$scope.removedIds[i].tabID)
return false;
}
return tab;
and this would be used in ng-options for ex: ng-options="tab.ID as tab.name for tab in tables | filter: "
and in my function ng-change i would be adding to $scope.removedIds next values that should not be available in next select dropdowns. But I think it would not work because values would be filter out in different select dropdowns.
Example
I guess that you have three dropdowns with same datasource, a simple solution would look like:
<div>
<select ng-model="selectedItem1" ng-options="item1 for item1 in options1"></select>
<select ng-model="selectedItem2" ng-options="item2 for item2 in options2"></select>
<select ng-model="selectedItem3" ng-options="item3 for item3 in options3"></select>
</div>
In the corresponding controller, and using angularjs watchers, add these lines:
$scope.options1 = ["opt1","opt2","opt3"];
$scope.options2 = angular.copy($scope.options1);
$scope.options3 = angular.copy($scope.options1);
$scope.$watch("selectedItem1", function(nv, ov) {
if (nv != ov) {
$scope.options2.splice($scope.options2.indexOf(nv),1);
$scope.options3.splice($scope.options3.indexOf(nv),1);
}
});
$scope.$watch("selectedItem2", function(nv, ov) {
if (nv != ov) {
$scope.options1.splice($scope.options1.indexOf(nv),1);
$scope.options3.splice($scope.options3.indexOf(nv),1);
}
});
$scope.$watch("selectedItem3", function(nv, ov) {
if (nv != ov) {
$scope.options1.splice($scope.options1.indexOf(nv),1);
$scope.options2.splice($scope.options2.indexOf(nv),1);
}
});
I have upgraded select2 into version 4. When I open select2 and enter the search text, the list filters based on what I type.
Here is the HTML
<select style="width: 100%;" id="fruit" multiple required>
<option value="1">Apple</option>
<option value="2">Pear</option>
<option value="3">Watermelon</option>
<option value="4">Melon</option>
<option value="5">Pineapple</option>
<option value="6">Orange</option>
<option value="7">Kiwi</option>
<option value="8">Banana</option>
<option value="9">Papaya</option>
<option value="10">Tangerine</option>
</select>
This is for JS
$(document).on('ready', function() {
function matchCustom(params, data) {
if ($.trim(params.term) === '') {
return data;
}
if (typeof data.text === 'undefined') {
return null;
}
var terms = params.term.split(" ");
for (var i=0; i < terms.length; i++){
if (data.text.toLowerCase().indexOf(terms[i].toLowerCase()) === -1) {
return null;
}
}
return data;
}
$('select').select2({
matcher: matchCustom,
closeOnSelect: false,
multiple: true
});
var last_search = '';
$('select').on('select2:open', function () {
if (last_search != "") {
$('#fruit').select2('search', last_search);
$('.select2-search__field').val(last_search);
}
});
$(document).on('keyup', '.select2-search__field', function () {
var text = $('.select2-search__field').val();
last_search = text;
});
});
Initial display
When I type, this is the design
After I selected what I want, the list is still open and the search text is not disappear. It's not a problem. However, when I click on another place (which caused my select2 list to disappear) and click again at the select2 field, this is what happened.
The last search value is "ap". The list only included the value that have "ap" in the words. But, the Searching text is exist. The "ap" value doesn't appear in the search text as expected. This code $('.select2-search__field').val(last_search); doesn't work as expected.
I also try to remove this code $('#fruit').select2('search', last_search); that is located inside the select2 open event. I got another problem when I opened select2 field for the second time.
The "ap" value is the last search before I close the select2 list. When I reopened, the "ap" value shows up in the search text which is correct. But, the list is not filtered according to what I search.
The outcome that I want after I reopened select2 field is the search value appears and the list only filters what I search. I have been searching for this for hours. Is there anything that I am missing?
So I have a dropdown menu. The id for this dropdown menu is "courses". This dropdown also has an additional attribute, onclick="displayField();
The dropdown has 2 options.
2 and 3.
Now, I want everything with the class rsform-block-cotecours1 to be hidden depending on which option is chosen.
Here is the JavaScript for that:
function displayField()
{
if(document.getElementById("courses").text == '2';)
document.getElementsByClassName('rsform-block-cotecours1').style.display="none";
if(document.getElementById("courses").text == '3';)
document.getElementsByClassName('rsform-block-cotecours1').style.display="";
}
window.addEvent('domready', function() {
displayField();
});
However, this doesn't work, and I don't know why.
Is this what you are looking for?
Fiddle: fiddle
<select id="courses" onchange="ddlChange()">
<option value="2">2</option>
<option value="3">3</option>
</select>
JavaScript
function ddlChange() {
if (document.getElementById("courses").value =="2"){
document.getElementsByClassName('rsform-block-cotecours1')[0].style.display="none";
alert(document.getElementById("courses").value );
}
if (document.getElementById("courses").value == "3"){
document.getElementsByClassName('rsform-block-cotecours1')[0].style.display="block";
alert(document.getElementById("courses").value );
}
}
Change the code to following and test
function displayField()
{
if(document.getElementById("courses").value == '2';)
document.getElementsByClassName('rsform-block-cotecours1')[0].style.display="none";
if(document.getElementById("courses").value == '3';)
document.getElementsByClassName('rsform-block-cotecours1')[0].style.display="";
}
window.addEvent('domready', function() {
displayField();
});
in case you want to access the ext and not the value of dropdown list in javascript, then use following code to access the text of selected option from drop down
var courseElement = document.getElementById("courses");
var text = "";
if (courseElement.selectedIndex != -1)
{
text = courseElement.options[courseElement.selectedIndex].text;
}
I have two selections, the seconds options options are dependent on the first selection.
Both of the selection boxes NEED to have a class attached to them, so I can not use the options attribute. The only way I have found to do this is using the foreach method.
I need to track both of the selected values at any time, but the second selection does not update its value when repopulated with new data. Please see the fiddle.
Another requirement is if the original option passed in through the viewmodel creation for the second selection is there, I would like that to be the default when populated. e.g in the fiddle when changing from WPA-PSK to none and then back I would like the default selection to be MIX(passed in) rather than AES.
Fiddle: Link to Fiddle
function ViewModel(security) {
var self = this;
self.authenticationMode = ko.observable(security.authenticationMode);
self.encryptionType = ko.observable(security.encryptionType);
self.authenticationModes = ko.observableArray([{translationText: "None", mode: "NONE", translationClass: "T_WPA-PSK"},
{translationText: "Open", mode: "OPEN", translationClass: "T_WPA-PSK"},
{translationText: "WPA-PSK", mode: "WPA-PSK", translationClass: "T_WPA-PSK"}]);
self.encryptionTypes = ko.computed(function () {
console.log(self.authenticationMode());
if (self.authenticationMode() === 'OPEN')
return [{translationText: "WEP", type: 'WEP', translationClass: "T_WEP"}];
if (self.authenticationMode() === 'WPA-PSK')
return [{translationText: "AES", type: 'AES', translationClass: "T_AES"},
{translationText: "MIX", type: 'MIX', translationClass: "T_MIX"}];
return [];
});
}
ko.applyBindings(new ViewModel({authenticationMode: 'WPA-PSK', encryptionType: 'MIX'}));
<select data-bind="value: authenticationMode, foreach: authenticationModes">
<option data-bind="text: translationText, value: mode, attr: { class: translationClass }"></option>
</select>
<select data-bind="value: encryptionType, foreach: encryptionTypes">
<option data-bind="text: translationText, value: type, attr: { class: translationClass }"></option>
</select>
<p>Selected Authentication: <b data-bind="text:authenticationMode"></b></p>
<p>Selected Encryption Type: <b data-bind="text:encryptionType"></b></p>
Fiddle Using Options - Another way I found using options to set the class with optionsAfterRender method.
Updated your fiddle:
http://jsfiddle.net/fS8qp/7/
Both requirements are met by adding the following in your viewmodel:
self.defaultEncryptionType = security.encryptionType;
self.authenticationMode.subscribe(function () {
self.encryptionType(self.defaultEncryptionType); // This will select the passed in encryptionType, if it exists in the current list of options
self.encryptionType.valueHasMutated(); // This will trigger an update of the observable
});
I want to add 'change' events to 4 select boxes. I have done it using bind().
But I want to call different functions on change of each select box.
Say function1() on change event of SelectBox1...
How should I do it?
I am new to javascript & jquery, so please help.
Thank you
Suppose your HTML like this:
HTML
<select id="selectBox1">
</select>
<select id="selectBox2">
</select>
<select id="selectBox3">
</select>
<select id="selectBox4">
</select>
jQuery
$('select[id^=selectBox]').on('change', function() {
// to get the id of current selectBox
var selectId = this.id;
if(selectId == 'selectBox1') {
function1();
} else if(selecId == 'selectBox2') {
function2();
}
// and so on
});
Some more
$('select[id^=selectBox]').on('change', function() {
// to get the selected value
var value = $.trim( this.value ); // $.trim() used to remove space
// from beginning and end
// you may not use
// to get selected option text
var optText = $('option:selected', this).text()
// to get the selectedIndex
var selIndex = this.selectedIndex;
// OR
var selIndex = $(this).prop('selectedIndex');
});
Note
Here, select[id^=selectBox] get select boxes, whose id start with selectBox. You may have something different id.
.change() used for bind the event to those select box.
Read more about
jQuery selectors
jQuery Events
$.trim()
.prop()
you can set an specific attribute for each select so:
<select id="selectBox1" val='1'>
</select>
<select id="selectBox2" val='2'>
</select>
<select id="selectBox3" val='3'>
</select>
<select id="selectBox4" val='4'>
</select>
and then bind onchange event like this:
$("select").change(function(){
var val = $(this).attr("val");
if (val == '1')
{
//logic for first select change
}
else if (val == '2')
{
//logic for second select change
}
else if (val == '3')
{
//logic for third select change
}
// and so on...
});
hope that helps.