옵션을 동적으로 변경할 때 IE 선택 문제를 해결하는 방법
모두 동일한 옵션을 가진 선택 세트가 있습니다. 그런 다음 다른 선택에서 선택된 옵션이 선택에 표시되지 않도록 필터를 통해 해당 옵션을 실행합니다. 내가 의미하는 바를 보려면 이 jsFiddle (비 IE 브라우저에서)을 참조하십시오. 기본적으로 동일한 옵션이 선택 항목 중에서 여러 번 선택되는 것을 방지합니다.
이제 내가 한 일은 IE에서 문제가 있습니다. IE에서 해당 바이올린을 엽니 다 (IE9에서만 시도했지만 이전 버전에 동일한 문제가 있다고 생각합니다). 마지막 선택을 AAA로 변경하십시오. 다른 세 사람이 표시되는 내용을 모두 선택하는 방법에 주목하십시오. 그들에 대한 모델은 변경되지 않았지만 IE는 옵션이 변경되면 어떻게 든 질식합니다.
내 질문이 먼저입니다. 일반적으로이 기능에 문제가 있습니까? 이 동일한 코드는 Chrome과 FF에서 정확히 원하는 것을 수행하지만, 내가해서는 안되는 일을하고 있습니까? 둘째, IE에서이 문제를 어떻게 해결할 수 있습니까? 모델을 지우고 재설정하는 몇 가지 시간 제한을 시도했지만 눈에 띄는 것이 뛰어났습니다. 이것에 대한 좋고 깨끗하며 영향이 적은 해결 방법이 있는지 궁금합니다.
어떤 도움이라도 대단히 감사하겠습니다. 감사.
--최신 정보--
이것은 아래 AS Ranjan의 솔루션을 사용하여 버전 1.3.3 에서 Angular 자체에서 수정 되었습니다 . 1.3.3의 새로운 바이올린보기 : http://jsfiddle.net/m2ytyapv/
//dummy code so I can post the edit
나는 지난 밤에 같은 문제를 겪었고 내가 생각할 수있는 모든 것을 던진 후에 IE가 선택을 사용할 때 필터 업데이트를 처리하고 싶지 않다는 결론에 도달했습니다.
내 해결책은 선택 항목을 다음과 같이 변경하는 것입니다.
<select class="selectList" ng-repeat="currId in selectedIds" ng-model="selectedIds[$index]" ng-options="currOption.id as currOption.value for currOption in myObj | myfilter:selectedIds:$index" data-ng-change="fixIE()"></select>
이제 그들은 클래스와 ng-change를 가지고 있습니다. 그런 다음 컨트롤러에서이 재미있는 약간의 코드를 수행하십시오.
$scope.fixIE = function(){
//code to check if IE so the other browsers don't get this ugly hack.
var selectLists = document.querySelectorAll(".selectList");
for(var x = 0;x < selectLists.length; x++){
selectLists[x].parentNode.insertBefore(selectLists[x], selectLists[x]);
}
};
그것이하는 일은 DOM에서 요소를 추출하여 동일한 위치로 교체하는 것입니다. 다음은 작동하는 바이올린 jsFiddle입니다.
내가 시도한 다른 솔루션 중 자바 스크립트가 포함되지 않은 솔루션은 선택 항목의 표시 / 가시성을 전환하는 것과 같은 것입니다. zIndex를 이동했습니다. 확실히 고친 유일한 것은이 코드 조각이었습니다.
내가 수정했습니다.
IE8에서 렌더링을 트리거하려면 옵션 목록을 추가하고 제거해야합니다.
http://kkurni.blogspot.com.au/2013/10/angularjs-ng-option-with-ie8.html
/**
* Fix for IE select menus getting stuck when their underlying list changes.
* Original code: http://kkurni.blogspot.com.au/2013/10/angularjs-ng-option-with-ie8.html
*
* Set the `ie-select-fix` attribute to the model expression that should trigger the list to re-render.
*
* @example <select ng-model="modelValue" ie-select-fix="itemList" ng-options="item.label for item in itemList">
*/
app.directive('ieSelectFix', ['$document',
function($document) {
return {
restrict: 'A',
require: 'ngModel',
link: function(scope, element, attributes, ngModelCtrl) {
var isIE = $document[0] && $document[0].attachEvent;
if (!isIE) return;
var control = element[0];
//to fix IE8 issue with parent and detail controller, we need to depend on the parent controller
scope.$watch(attributes.ieSelectFix, function() {
// setTimeout is needed starting from angular 1.3+
setTimeout(function() {
//this will add and remove the options to trigger the rendering in IE8
var option = document.createElement("option");
control.add(option,null);
control.remove(control.options.length-1);
}, 0);
});
}
}
}
]);
마침내 내 필요에 맞는 솔루션을 찾았습니다. 기본적으로 발생하는 것처럼 보이는 것은 선택한 인덱스의 옵션에 대한 텍스트가 해당 위치에 있던 이전 문자열을 가리키는 것입니다. 이 텍스트를 변경하면 문자열 및 / 또는 참조가 업데이트됩니다. 나는 다음과 같이했다.
angular.forEach($("select"), function (currSelect) {
currSelect.options[currSelect.selectedIndex].text += " ";
});
다음은 업데이트 된 바이올린입니다. http://jsfiddle.net/H48sP/35/
내 앱에는 이러한 선택이있는 지시문이 있으므로 요소 선택 범위를 제한하는 element.find("select")
대신 수행 합니다 $("select")
. 텍스트는 강제로 새로 고쳐 지므로 모든 다이제스트주기가 실행 된 후 올바르게 표시됩니다.
이와 동일한 문제 $timeout
가 발생한 경우 바이올린에 좋아요 를 추가해야 할 수 있으며 문제 가 발생하면 나중에 옵션 텍스트에 추가 된 추가 공간을 제거해야 할 수도 있습니다.
angular.js의 selectDirective 렌더링 기능에서 다음 위치 (**로 굵게 표시)를 몇 줄 추가하면 잘 작동했습니다. angularJS 또는 아래에 주어진 forEach 패치 이외의 다른 가능한 솔루션이 있는지 찾고 있습니다.
if (existingOption.label !== option.label) {
lastElement.text(existingOption.label = option.label);
**lastElement.attr('label', existingOption.label);**
}
과
(element = optionTemplate.clone())
.val(option.id)
.attr('selected', option.selected)
.text(option.label);
**element.attr('label', option.label);**
문제는 HTMLOptionElement의 레이블 속성이 IE에서 레이블이 비어있는 경우 텍스트 속성과 동일하지 않다는 것입니다.
화면이로드 된 후 다음 코드를 추가하고 FF와 IE의 웹 콘솔에서 차이점을 확인하면 확인할 수 있습니다. 레이블이 텍스트로 설정된 마지막 줄의 주석 처리를 제거하면 제대로 작동합니다. 또는 위와 같이 angular.js를 패치하십시오.
// 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;
});
문제는 필터에서 반환 된 옵션의 순서와 관련된 것 같습니다. 마지막 옵션을로 변경하면 A
다른 선택 옵션이 변경됩니다. IE에 문제를 일으키는 것으로 보이는 것은 선택한 옵션이 장소를 변경한다는 것입니다. 첫 번째 선택 상자 C
에서 다음 순서로 옵션 중에서 선택됩니다 A, B, C, D
. 선택한 옵션이 세 번째 옵션 입니다. 네 번째 선택 상자를에서 G
로 A
변경하면 필터가 첫 번째 상자의 옵션을로 변경합니다 B, C, D, G
. 이제 선택한 옵션이 두 번째 옵션입니다., 이로 인해 IE에 문제가 발생합니다. Angular의 버그이거나 IE의 이상한 동작 일 수 있습니다. 선택한 요소가 항상 필터링 된 옵션의 첫 번째 옵션인지 확인하여이 문제를 해결하는 포크를 만들었습니다.
var newOptions = [],selected;
angular.forEach(allOptions, function (currentOption) {
if (!isIdInUse(selectedIds, currentOption.id)){
newOptions.push(currentOption);
}else if(currentOption.id == selectedIds[parseInt(index)]){
selected = currentOption;
}
});
if(selected){newOptions.unshift(selected);}
http://jsfiddle.net/XhxSD/ (이전)
최신 정보:
몇 가지 디버깅을 수행하고 IE에서 문제를 일으키는 줄을 찾았지만 이유를 이해할 수 없습니다. 렌더링 버그 같은 것 같습니다. 옵션을 재정렬 할 필요가없는 또 다른 해결 방법을 만들었습니다. 이것은 선택 요소의 변경 사항을 감시하는 지시문입니다. 변경이 감지되면 옵션을 추가하고 즉시 제거합니다.
.directive('ieSelectFix',function($timeout){
return {
require:'select',
link: function (scope, element) {
var isIE = document.attachEvent;
if(isIE){
$timeout(function(){
var index = element.prop('selectedIndex'), children = element.children().length;
scope.$watch(function(){
if(index !== element.prop('selectedIndex') || children !== element.children().length){
index = element.prop('selectedIndex');
children = element.children().length;
var tmp =angular.element('<option></option>');
element.append(tmp);
tmp.remove();
}
})
});
}
}
}
});
ng-repeats 내부의 요소를 선택하려면 ie-select-fix를 추가하십시오.
<div ng-app="myApp" ng-controller="MyCtrl">
<select ie-select-fix ng-repeat="currId in selectedIds" ng-model="selectedIds[$index]" ng-options="currOption.id as currOption.value for currOption in myObj | myfilter:selectedIds:$index"></select><br>
{{selectedIds}}
</div>
http://jsfiddle.net/VgpyZ/ (신규)
IE에서 select와 동일한 버그를 발견했습니다 ..이 버그는 DOM 노드를 복제 한 결과입니다 ..
(jQuery 스타일)과 같이 SELECT를 인스턴스화하는 경우 :
$select = $template.clone();
그리고 다음을 수행합니다.
$select.html('<option>111</option>');
위에서 설명한 버그가 발생합니다 ..
그러나 인스턴스화하면
$select = $('< div />').html( $template ).html();
버그가 발생하지 않았습니다. :)
오, 나는 다음 조언을 위해 지옥에 갈거야 ...!
나는 이러한 제안을 시도했지만 아무도 나를 위해 일하지 않았습니다.
실제로 Angular를 사용하여 선택 컨트롤을 각각 여러 옵션으로 채웠습니다.
<select class="cssMultipleSelect" multiple="multiple" ...>
때로는 Angular가 이러한 컨트롤을 채우고 새 데이터가 표시되지만 IE에서는 모든 옵션을보기 위해 위아래로 스크롤 할 수 없습니다.
그러나 F12 키를 누르고 너비를 수정 한 다음 원래 너비로 되 돌리면 IE가 다시 활성화되어 값 목록에서 위아래로 스크롤 할 수 있습니다.
그래서 내 해결책은 Angular가 컨트롤을 채운 후 약 1 초 후에 이것을 호출하는 것이 었습니다.
function RefreshMultipleSelectControls()
{
// A dodgy fix to an IE11 issue.
setTimeout(function () {
$(".cssMultipleSelect").width("");
}, 1500);
setTimeout(function () {
$(".cssMultipleSelect").width(298);
}, 1600);
}
(나는 이것이 어리석은 해결책이라고 말했다 ..)
다른 한 가지 : IE11에서는 navigator.appName
이제 NETSCAPE
( MSIE
또는 대신 Microsoft Internet Explorer
) 반환 된다는 점을 기억하십시오 . 따라서 코드가 IE에서 실행 중인지 또는 괜찮은 브라우저에서 실행 중인지 테스트 할 때주의하십시오.
경고를 받았습니다 .. !!
ie9가 색인에 문제가있는 것 같습니다. 두 번째 예제를 사용하여 다음 코드로 변경하십시오.
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/
Mathew Berg 답변 라인에서 AngularJS 지시문을 사용하여 작동하도록 수정했습니다.
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 had to change scope.$watch to scope.$watchCollection to make @kkurni solution above to work for IE9. Just wanted to help others out who were still having issues in IE9 for rendering select options when they change.
The rendering gets updated and synched if you change some attribute. An innocuous change may be to set the selectedIndex
attribute to its own value:
function fixIEselect() {
for (var nForm = 0; nForm < document.forms.length; ++nForm) {
var form = document.forms[nForm];
var children = form.children;
for (var nChild = 0; nChild < children.length; ++nChild) {
var child = children.item(nChild);
if (child.tagName == "SELECT") {
alert("Fixed: " + child.name);
child.selectedIndex = child.selectedIndex; // dummy nop but not
}
}
}
}
fixIEselect();
There is less expensive way to enforce control re-rendering after dynamic options are added. So, instead of inserting/removing dummy element to the dropdown you can reset CSS styles which cause control rendering, e.g.
selElement.style.zoom = selElement.style.zoom ? "" : 1;
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
'Programing' 카테고리의 다른 글
@ Html.LabelFor 템플릿을 어떻게 재정의 할 수 있습니까? (0) | 2020.11.21 |
---|---|
GCC는 루프 내에서 증가하는 사용되지 않는 변수를 어떻게 최적화합니까? (0) | 2020.11.21 |
소스 파일 'Properties \ AssemblyInfo.cs'를 찾을 수 없습니다. (0) | 2020.11.20 |
C #은 부분적으로 해석되거나 실제로 컴파일됩니까? (0) | 2020.11.20 |
응용 프로그램이 백그라운드에있는 동안 DialogFragment를 닫는 적절한 방법 (0) | 2020.11.20 |