[AngularJS 1.x] ng-options의 내용을 변경할 때 값이 초기화되는 경우

2019. 5. 7. 19:59Programming/AngularJS

반응형

2019/03/12 - [Programming/AngularJS] - [angularJS] ng-change/ng-click 내에서 ng-model로 바인딩 된 값을 변경할 시, UI에 변경된 값이 표시되지 않는 경우
이 글과 비슷한 내용이다. ng-change/ng-click 내에서 ng-model로 바인딩 된 값을 변경할 때의 문제이다.

 

ng-options를 활용하여 select를 작성하는 경우, ng-options내에 선언한 배열이나 객체를 변경하면 값이 초기화된다. 이전에 언급했던 글과 비슷한 현상인데, 렌더링을 다시 하기 때문에 ng-options내의 가장 처음 값이 선택되어버리는 문제이다. 하지만 ng-model값은 변경되지 않으므로, ng-change가 발생하지도 않는다. UI를 클릭해서 이전 값으로 변경했을 때도 실제 ng-model로 바인딩되어있는 값은 변경되지 않기 때문에, ng-change가 발생하지 않는다.

가장 중요한 대목은 UI상에서는 ng-options의 가장 처음 값이 선택된 것처럼 보이지만,실제 ng-model으로 바인딩되어있는 값은 변경되지 않기 때문에 렌더링이 되지 않는다. 실제로 이 문제를 처음 맞딱드리게되면 상당히 짜증나게된다. 이런 경우에는 Select에 DOM id를 설정해주고, 바닐라 자바스크립트로 변경해주는 수밖에 없다.

<select ng-options="option.value as option.label for option in options | filter:cantSelectableOption"
                 ng-model="current_option"
                 ng-change="optionChangeHandler($index)"
                 id="select"/> 

이제 id값을 이용해서 select에 접근할 수 있다.

 

위처럼 id값을 작성하게되면 document.getElementById를 이용해서 돔을 불러올 수 있다. 다만 문제가 있다. angularJS에서 렌더링한 값은 실제 값과는 달리 index 순서이며, label의 값이 각 옵션의 text에 할당되게 된다. 따라서 실제 options의 값이 변경되었을 때 DOM을 조작하기 위해서는, 다음과 같은 절차를 거쳐야 한다.

var index_of_option = 0;
var text_of_option = "";

for(var i=0; i<$scope.options.length; i++) {
  if($scope.options[i].label == document.getElementById("select").text) {
    index_of_option = i;
  }
}
document.getElementById("select").value = index_of_option;

 

위와같은 방식으로 DOM객체를 직접 컨트롤해서 대처할 수 있다.
추가적으로 select 자체를 ng-repeat내에서 사용하는 경우, $index를 사용하여 각 select의 id를 다르게 선언할 수 있다.

<div ng-repeat='select_model in selects'>
 <select ng-options="option.value as option.label for option in options | filter:cantSelectableOption"
                     ng-model="current_option"
                     ng-change="optionChangeHandler($index)"
                     id="select_{{$index}}"/> 
</div>

위와 같은 방법으로 선언하면 select_0, select_1, select_2, ..., select_N과 같은 형태로 id가 할당된다.

 

사실 요약하면 'ng-options로 바인딩 한 배열/객체의 값을 변경한 경우, 바닐라 자바스크립트를 이용해서 DOM을 컨트롤하세요'라는 한 줄로 요약할 수 있는 글이다. 일반적으로 ng-options로 바인딩해놓은 배열을 변경할 일은 거의 없기 때문에, 마주칠 일은 없을 듯 하다. = ㅅ=)

반응형