I have a set of selects that all have the same options. Then I run those options through a filter so that any options that are selected in a different select don\'t show up
Adding couple of lines the following places (marked in bold as **) in render function of the selectDirective in angular.js worked fine for me. I am looking if there is any other possible solution other than patching angularJS or the forEach given below?
if (existingOption.label !== option.label) {
lastElement.text(existingOption.label = option.label);
**lastElement.attr('label', existingOption.label);**
}
and
(element = optionTemplate.clone())
.val(option.id)
.attr('selected', option.selected)
.text(option.label);
**element.attr('label', option.label);**
The issue was the label attribute of HTMLOptionElement is not the same as the text attribute if label is blank in IE.
This can be seen verified by adding the following code after the screen has loaded and looking at the web console of FF and IE to see the difference. If you uncomment the last line where the label is set to text it works fine. Alternatively patch angular.js as above.
// This is an IE fix for not updating the section of dropdowns which has ng-options with filters
angular.forEach($("select"), function (currSelect) {
console.log("1.text ", currSelect.options[currSelect.selectedIndex].text);
console.log("1.label ", currSelect.options[currSelect.selectedIndex].label);
//console.log("1.innerHTML ", currSelect.options[currSelect.selectedIndex].innerHTML);
//console.log("1.textContent ", currSelect.options[currSelect.selectedIndex].textContent);
//console.log("1.cN.data ", currSelect.options[currSelect.selectedIndex].childNodes[0].data);
//console.log("1.cN.nodeValue ", currSelect.options[currSelect.selectedIndex].childNodes[0].nodeValue);
//console.log("1.cN.textContent ", currSelect.options[currSelect.selectedIndex].childNodes[0].textContent);
//console.log("1.cN.wholeText ", currSelect.options[currSelect.selectedIndex].childNodes[0].wholeText);
//console.log("1. ", currSelect.options[currSelect.selectedIndex], "\n");
//currSelect.options[currSelect.selectedIndex].label = "xyz";
//currSelect.options[currSelect.selectedIndex].label = currSelect.options[currSelect.selectedIndex].text;
});
Oh, I'm going to hell for the following advice...!
I tried these suggestions, but none worked for me.
I was actually using Angular to populate select controls with multiple options in each.
<select class="cssMultipleSelect" multiple="multiple" ...>
Sometimes, Angular would populate these controls, the new data would appear, but in IE, you couldn't scroll up and down to view all of the options.
But, if you hit F12, modified the width, and put it back to its original width, then IE would burst back into life again, and you could scroll up and down in the list of values.
So, my solution was to call this, a second or so after Angular had finished populating the controls:
function RefreshMultipleSelectControls()
{
// A dodgy fix to an IE11 issue.
setTimeout(function () {
$(".cssMultipleSelect").width("");
}, 1500);
setTimeout(function () {
$(".cssMultipleSelect").width(298);
}, 1600);
}
(I told you this was a dodgy fix..)
One other thing: remember that in IE11, navigator.appName
will now return NETSCAPE
(rather than MSIE
or Microsoft Internet Explorer
)... so be careful when you're testing if your code is running on IE, or on a decent browser.
You've been warned..!!
Seems that ie9 have problem with the index. Taking the second example and change it to the following code it worked:
var hwcalcModule = angular.module('ie9select', []);
function AnimalCtrl($scope) {
$scope.categories = [{
name: "Cats",
kinds: ["Lion", "Leopard", "Puma"]
}, {
name: "Dogs",
kinds: ["Chihua-Hua", " Yorkshire Terrier", "Pitbull"]
}];
$scope.animals = [{
category: $scope.categories[1],
kind: $scope.categories[1].kinds[1]
}];
$scope.changeCategory = function (animal) {
console.log(animal.category.name);
var name = animal.category.name;
var index = 0;
angular.forEach($scope.categories, function (currentOption) {
console.log(currentOption.name);
if (name == currentOption.name)
{
console.log(index);
$scope.animals = [{
category: $scope.categories[index],
kind: $scope.categories[index].kinds[0]
}];
}
index++;
});
}
}
http://jsfiddle.net/seoservice/nFp62/10/
On the lines of Mathew Berg answer, I modified it to work using AngularJS directive:
angular.module('select',[]).directive("select", function() {
return {
restrict: "E",
require: "?ngModel",
scope: false,
link: function (scope, element, attrs, ngModel) {
if (!ngModel) {
return;
}
element.bind("change", function() {
//Fix for IE9 where it is not able to properly handle dropdown value change
//The fix is to rip out the dropdown from DOM and add it back at the same location
if (isIE9){
this.parentNode.insertBefore(this, this); //this rips the elements out of the DOM and replace it into the same location.
}
})
}
}
});
This way the fix applies to all select
elements in the project and you do not have to change any existing HTML markup. I also used the following method to detect IE version to set isIE9
variable to true
:
var Browser = {
IsIE: function () {
return navigator.appVersion.indexOf("MSIE") != -1;
},
Navigator: navigator.appVersion,
Version: function() {
var version = 999; // we assume a sane browser
if (navigator.appVersion.indexOf("MSIE") != -1)
// bah, IE again, lets downgrade version number
version = parseFloat(navigator.appVersion.split("MSIE")[1]);
return version;
}
};
var oldIE = false; //Global Variable
var isIE9 = false; //Global Variable
if (Browser.IsIE && Browser.Version() <= 8) {
oldIE = true;
}
if (Browser.IsIE && Browser.Version() == 9) {
isIE9 = true;
}
I have a workaround for the IE picklist issue
Before Fix:http://plnkr.co/edit/NGwG1LUVk3ctGOsX15KI?p=preview
After Fix:http://plnkr.co/edit/a7CGJavo2m2Tc73VR28i?p=preview
$("select").click(function(){
$(this).append('<option></option>');
$(this).find('option:last').remove();
});
I just added dummy option for the dom to rerender the select and removed it. let me know it works for you
I've finally come up with a solution that works for my needs. Basically what appears to be happening is that the text for the option at the selected index is pointing to the old string that used to be in that place. I believe changing this text updates the strings and/or references. I did something like this:
angular.forEach($("select"), function (currSelect) {
currSelect.options[currSelect.selectedIndex].text += " ";
});
Here is the updated fiddle: http://jsfiddle.net/H48sP/35/
In my app, I have a directive where these selects are, and so I do element.find("select")
instead of $("select")
to limit the scope of the element selecting. The text is forced to refresh and so displays correctly after all the digest cycles run.
If you have run into this same issue, you may need to add a $timeout
like in the fiddle, and/or you may need to later remove the extra space that was added to the option text if that becomes a problem.