AngularJS에서 양방향 필터링을 수행하는 방법은 무엇입니까?


124

AngularJS가 할 수있는 흥미로운 작업 중 하나는 특정 데이터 바인딩 표현식에 필터를 적용하는 것입니다. 이는 예를 들어 문화 별 통화 또는 모델 속성의 날짜 형식 지정을 적용하는 편리한 방법입니다. 스코프에 대해 계산 된 속성을 갖는 것도 좋습니다. 문제는 이러한 기능 중 어느 것도 양방향 데이터 바인딩 시나리오에서 작동하지 않는다는 것입니다. 범위에서 뷰로의 단방향 데이터 바인딩 만 가능합니다. 이것은 다른 훌륭한 도서관에서 눈부신 누락으로 보입니다-아니면 내가 뭔가를 놓치고 있습니까?

KnockoutJS 에서는 읽기 / 쓰기 계산 된 속성을 만들 수 있습니다.이 속성을 사용하면 한 쌍의 함수를 지정할 수 있습니다. 하나는 속성 값을 가져 오기 위해 호출되고 다른 하나는 속성이 설정 될 때 호출됩니다. 이를 통해 예를 들어 문화 인식 입력을 구현할 수있었습니다. 사용자가 "$ 1.24"를 입력하고이를 ViewModel의 float로 파싱하고 ViewModel의 변경 사항이 입력에 반영되도록했습니다.

이것과 비슷한 것을 찾을 수있는 가장 가까운 것은 $scope.$watch(propertyName, functionOrNGExpression);This를 사용하면 속성이 $scope변경 될 때 함수를 호출 할 수 있다는 것 입니다. 그러나 이것은 예를 들어 문화 인식 입력 문제를 해결하지 못합니다. 메서드 자체 에서 $watched속성 을 수정하려고 할 때 문제를 확인 $watch합니다.

$scope.$watch("property", function (newValue, oldValue) {
    $scope.outputMessage = "oldValue: " + oldValue + " newValue: " + newValue;
    $scope.property = Globalize.parseFloat(newValue);
});

( http://jsfiddle.net/gyZH8/2/ )

사용자가 입력을 시작하면 입력 요소가 매우 혼란스러워집니다. 속성을 구문 분석되지 않은 값과 구문 분석 된 값에 대한 두 개의 속성으로 분할하여 개선했습니다.

$scope.visibleProperty= 0.0;
$scope.hiddenProperty = 0.0;
$scope.$watch("visibleProperty", function (newValue, oldValue) {
    $scope.outputMessage = "oldValue: " + oldValue + " newValue: " + newValue;
    $scope.hiddenProperty = Globalize.parseFloat(newValue);
});

( http://jsfiddle.net/XkPNv/1/ )

이것은 첫 번째 버전에 비해 개선되었지만 조금 더 장황하며, 여전히 parsedValue범위 의 속성 변경 문제가 있음을 알 수 있습니다 (두 번째 입력에 무언가를 입력하면 parsedValue직접 변경 됩니다. 상단 입력은 그렇지 않습니다. 최신 정보). 이는 컨트롤러 작업 또는 데이터 서비스에서 데이터를로드 할 때 발생할 수 있습니다.

AngularJS를 사용하여이 시나리오를 구현하는 더 쉬운 방법이 있습니까? 문서에서 일부 기능이 누락 되었습니까?

답변:


231

이것에 대한 매우 우아한 해결책이 있음이 밝혀졌지만 잘 문서화되어 있지 않습니다.

표시를위한 형식화 모델 값은 |연산자 및 각도 formatter. 포맷터 목록뿐만 아니라 파서 목록도있는 ngModel이 있습니다.

1. ng-model양방향 데이터 바인딩을 만드는 데 사용

<input type="text" ng-model="foo.bar"></input>

2. 동일한 요소에 적용되고 ngModel컨트롤러에 따라 달라지는 각도 모듈에 지시문을 만듭니다.

module.directive('lowercase', function() {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function(scope, element, attr, ngModel) {
            ...
        }
    };
});

3. link메서드 내에서 사용자 지정 변환기를 ngModel컨트롤러에 추가합니다.

function fromUser(text) {
    return (text || '').toUpperCase();
}

function toUser(text) {
    return (text || '').toLowerCase();
}
ngModel.$parsers.push(fromUser);
ngModel.$formatters.push(toUser);

4. 이미있는 동일한 요소에 새 지시문을 추가합니다. ngModel

<input type="text" lowercase ng-model="foo.bar"></input>

다음 은 모델 에서 텍스트를 소문자로 변환 하고 다시 대문자로 변환 하는 작업 예제 입니다.input

모델 컨트롤러에 대한 API 문서는 또한 간단한 설명과 사용 가능한 다른 방법의 개요를 가지고있다.


연결 함수에서 네 번째 매개 변수의 이름으로 "ngModel"을 사용한 이유가 있습니까? 기본적으로 ngModel 속성과 관련이없는 지시문의 일반 컨트롤러가 아닙니까? (아직 내가 완전히 잘못 될 수 있도록 여기에 각 학습.)
드류 밀러

7
"require : 'ngModel'"때문에 연결 함수의 네 번째 매개 변수는 ngModel 지시어의 컨트롤러가됩니다. 즉, ngModelController 의 인스턴스 인 foo.bar의 컨트롤러가 됩니다 . 네 번째 매개 변수의 이름은 원하는대로 지정할 수 있습니다. (이름을 지정합니다 ngModelCtrl.)
Mark Rajcok

8
이 기술은 사용자 정의 유효성 검사 섹션의 docs.angularjs.org/guide/forms에 문서화되어 있습니다.
Nikhil Dabas 2013

1
제공된 바이올린의 @Mark Rajcok에서 데이터로드-모두 소문자를 클릭하는 동안 모델 값이 모두 대문자로 표시 될 것으로 예상했지만 모델 값은 작습니다. pls 수 있습니다. 방법 CAPS 항상 모델을 만드는 이유 등을 설명
Rajkamal Subramanian에게

1
@rajkamal, loadData2 ()가 $scope직접 수정 하기 때문에 사용자가 텍스트 상자와 상호 작용할 때까지 모델이 설정됩니다. 이 시점에서 모든 파서는 모델 값에 영향을 미칠 수 있습니다. 파서 외에도 컨트롤러에 $ watch를 추가하여 모델 값을 변환 할 수 있습니다.
Mark Rajcok 2013
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.