Development Tip

모델에 숫자를 사용하는 Angularjs ng-options가 초기 값을 선택하지 않습니다.

yourdevel 2020. 12. 2. 22:05
반응형

모델에 숫자를 사용하는 Angularjs ng-options가 초기 값을 선택하지 않습니다.


ng-options를 a와 함께 사용 <select>하여 숫자 정수 값을 해당 옵션 목록에 바인딩 하려고합니다 . 내 컨트롤러에는 다음과 같은 것이 있습니다.

myApp.controller('MyCtrl', function() {
    var self = this;

    var unitOptionsFromServer = {
        2: "mA",
        3: "A",
        4: "mV",
        5: "V",
        6: "W",
        7: "kW"
    };

    self.unitsOptions = Object.keys(unitOptionsFromServer).map(function (key) {
        return { id: key, text: unitOptionsFromServer[key] };
    });

    self.selectedUnitOrdinal = 4; // Assume this value came from the server.
});

HTML :

<div ng-controller="MyCtrl as ctrl">
    <div>selectedUnitOrdinal: {{ctrl.selectedUnitOrdinal}}</div>
    <select ng-model="ctrl.selectedUnitOrdinal" ng-options="unit.id as unit.text for unit in ctrl.unitsOptions"></select>
</div>

그리고 여기 에 문제를 보여주는 jsFiddle 과 내가 취했지만 만족스럽지 않은 다른 접근 방식이 있습니다.

선택 옵션은이 예제에서 예상 한대로 "mV"대신 빈 값으로 초기화됩니다. 다른 옵션을 선택하면 바인딩이 제대로 작동하는 것 같습니다. selectedUnitOrdinal이 제대로 업데이트됩니다.

초기 모델 값을 숫자 대신 문자열로 설정하면 초기 선택이 작동한다는 것을 알았습니다 (바이올린의 # 3 참조).

ng-options가 숫자 옵션 값으로 잘 작동하기를 바랍니다. 어떻게하면 우아하게 이룰 수 있습니까?


ng-select지시문에 대한 Angular의 문서는 이 문제를 해결하는 방법을 설명합니다. https://code.angularjs.org/1.4.7/docs/api/ng/directive/select (마지막 섹션)를 참조 하십시오 .

convert-to-number지시문을 생성 하여 선택 태그에 적용 할 수 있습니다.

JS :

module.directive('convertToNumber', function() {
  return {
    require: 'ngModel',
    link: function(scope, element, attrs, ngModel) {
      ngModel.$parsers.push(function(val) {
        return val != null ? parseInt(val, 10) : null;
      });
      ngModel.$formatters.push(function(val) {
        return val != null ? '' + val : null;
      });
    }
  };
});

HTML :

<select ng-model="model.id" convert-to-number>
  <option value="0">Zero</option>
  <option value="1">One</option>
  <option value="2">Two</option>
</select>

참고 : 문서의 지시문이 null을 처리하지 않기 때문에 약간 조정해야했습니다.


다소 지저분 할 수도 있지만 ng-options에서 특별한 기능 없이도 결과를 얻을 수 있습니다.

<select ng-model="ctrl.selectedUnitOrdinal" ng-options="+(unit.id) as unit.text for unit in ctrl.unitsOptions"></select>

unit.id를 얻을 때 정수가 아닌 문자열을 반환하기 때문입니다. 자바 스크립트의 객체는 키를 문자열로 저장합니다. 따라서이를 수행하는 유일한 방법은 인용문으로 4를 둘러싸는 방법입니다.

편집하다

<select ng-model="ctrl.selectedUnitOrdinal" ng-options="convertToInt(unit.id) as unit.text for unit in ctrl.unitsOptions"></select>

$scope.convertToInt = function(id){
    return parseInt(id, 10);
};

You can also define filter number, this filter will automatically parse string value to int:

<select ng-model="ctrl.selectedUnitOrdinal" ng-options="unit.id|number as unit.text for unit in ctrl.unitsOptions"></select>


angular.module('filters').filter('number', [function() {
        return function(input) {
            return parseInt(input, 10);
        };
    }]);

Just to add Christophe's answear: easiest way to achive and maintaint it is to make a directive:

JS:

.directive('convertToNumber', function() {
  return {
    require: 'ngModel',
    link: function(scope, element, attrs, ngModel) {
      ngModel.$parsers.push(function(val) {
        //saves integer to model null as null
        return val == null ? null : parseInt(val, 10);
      });
      ngModel.$formatters.push(function(val) {
        //return string for formatter and null as null
        return val == null ? null : '' + val ;
      });
    }
  };
});

Christophe's answear wont work correctly for '0' as it returns false on "val?" test.


I think the other solutions are overly complex for simply establishing the value as an integer. I would use:

<select ng-model="model.id">
    <option ng-value="{{ 0 }}">Zero</option>
    <option ng-value="{{ 1 }}">One</option>
    <option ng-value="{{ 2 }}">Two</option>
</select>

Angular is seeing your id property as a string, add quotes:

self.selectedUnitOrdinal = "4";

Very similarly to tymeJV's answer, simple workaround is to convert the default selection number to a string like this:

self.selectedUnitOrdinal = valueThatCameFromServer.toString();

This way, you don't have to hardcode the number, you can just convert any received value. It's an easy fix without any filters or directives.


<select ng-model="ctrl.selectedUnitOrdinal" ng-options="+(unit.id) as unit.text for unit in ctrl.unitsOptions"></select>

Make id property in unitsOptions as number

self.unitsOptions = Object.keys(unitOptionsFromServer).map(function (key) {
        return { id: +key, text: unitOptionsFromServer[key] };
    });

http://jsfiddle.net/htwc10nx/


While the solution provided by Mathew Berg works it will probably break other selects that use sting-valued select options. This may be a problem if you try to write one universal directive for handling selects (like I did).

A nice workaround is to check if the value is a number (even if it is a string containing a number) and only than do the conversion, like so:

angular.module('<module name>').filter('intToString', [function() {
        return function(key) {
            return (!isNaN(key)) ? parseInt(key) : key;
        };
    }]);

or as a controller method:

$scope.intToString = function(key) {
    return (!isNaN(key)) ? parseInt(key) : key;
};

참고URL : https://stackoverflow.com/questions/28114970/angularjs-ng-options-using-number-for-model-does-not-select-initial-value

반응형