programing

옵션을 동적으로 변경할 때 IE 선택 문제를 수정하는 방법

sourcetip 2023. 4. 2. 20:45
반응형

옵션을 동적으로 변경할 때 IE 선택 문제를 수정하는 방법

모두 같은 옵션을 선택할 수 있는 선택사항이 있습니다.그런 다음 다른 선택에서 선택한 옵션이 선택 항목에 나타나지 않도록 필터를 통해 이러한 옵션을 실행합니다.jsFiddle(IE 이외의 브라우저)을 참조해 주세요.기본적으로 선택 항목 중에서 동일한 옵션이 여러 번 선택되는 것을 방지하고 있습니다.

제가 한 일은 IE에 문제가 있습니다.IE에서 해당 바이올린을 엽니다(IE9에서만 시도했지만 이전 버전에서도 같은 문제가 있을 수 있습니다).마지막 선택을 AAA로 변경합니다.다른 3명이 모두 선택한 경우 표시되는 내용이 어떻게 변경되었는지 확인하십시오.이 모델의 모델은 변경되지 않았지만 IE는 옵션이 변경되었을 때 어떤 이유로든 쐐기를 박습니다.

첫 번째 질문은 이 기능에 대해 전반적으로 문제가 있습니까?이 코드는 Chrome과 FF에서 내가 원하는 대로 작동하는데, 내가 해서는 안 될 일을 하고 있는 걸까요?둘째, IE에서는 어떻게 하면 이 문제를 해결할 수 있을까요?모델을 클리어하고 리셋하는 타임아웃을 시도했지만 눈에 띄는 것이 눈에 띄었다.이 문제에 대한 효과적이고 깔끔한 해결 방법이 있는지 궁금합니다.

어떤 도움이라도 주시면 감사하겠습니다.감사해요.

--갱신--

이것은 아래 A. S. 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이 있습니다.

javascript를 사용하지 않은 다른 솔루션으로는 선택 항목 표시/가시성 전환 등이 있습니다.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예를 들어 바이올린을 켜거나 나중에 문제가 발생하면 옵션텍스트에 추가된 여분의 공간을 삭제해야 할 수 있습니다.

select Direct in angular.js의 렌더링 기능에서 다음 부분(굵은 글씨로 **로 표시)을 몇 줄 추가하면 문제가 없습니다.각진 패치 외에 다른 방법이 없는지 알아보고 있습니다.아래에 제시된 JS 또는 for?

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

문제는 IE에서 라벨이 공백일 경우 HTMLOptionElement의 라벨 속성이 텍스트 속성과 동일하지 않다는 것입니다.

이는 화면 로드 후 다음 코드를 추가하여 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는 음음음음 is is 、 ' is 、 is is 、 ' is is is is is is is is is 。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에서 셀렉트 버그와 같은 버그를 발견했습니다.이 버그는 DOM 노드를 복제한 결과입니다.

SELECT like(jQuery 타를를) :

$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에서는, 「IE11」이라고 하는 에 주의해 주세요.navigator.appName에서 will will will 、 will will 。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의 답변 라인에서 Angular를 사용하여 작동하도록 수정했습니다.JS 지시:

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.
            }
        })
      }
   }
});

이 방법으로 수정은 모든 사용자에게 적용됩니다.select기존 HTML 마크업을 변경할 필요가 없습니다.또한 설정할 IE 버전을 검출하기 위해 다음 방법을 사용했습니다.isIE9에 가변적인.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;
}

범위를 바꿔야 했어요.$watch to scope.$watch Collection은 위의 @kurni 솔루션을 IE9용으로 만듭니다.IE9에서 선택 옵션을 변경할 때 렌더링하는 데 문제가 있는 다른 사용자를 돕고 싶을 뿐입니다.

일부 속성을 변경하면 렌더링이 업데이트되고 동기화됩니다.무해한 변경은 다음과 같은 설정을 하는 것일 수 있습니다.selectedIndex자신의 값에 기인합니다.

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

다이내믹 옵션이 추가된 후 제어 재렌더링을 시행하는 방법은 비용이 적게 듭니다.따라서 더미 요소를 드롭다운에 삽입/삭제하는 대신 컨트롤 렌더링을 일으키는 CSS 스타일을 리셋할 수 있습니다.

selElement.style.zoom = selElement.style.zoom ? "" : 1;

IE 픽리스트 문제에 대한 해결 방법이 있습니다.

수정 전 : http://plnkr.co/edit/NGwG1LUVk3ctGOsX15KI?p=preview

수정 후 : http://plnkr.co/edit/a7CGJavo2m2Tc73VR28i?p=preview

$("select").click(function(){
  $(this).append('<option></option>');
   $(this).find('option:last').remove();

});

방금 돔에서 선택 항목을 다시 렌더링하는 더미 옵션을 추가하고 삭제했습니다.너에게 효과가 있다는 것을 내게 알려줘

언급URL : https://stackoverflow.com/questions/12942681/how-to-fix-ie-select-issue-when-dynamically-changing-options

반응형