programing

커스텀 디렉티브의 ng-change 구현 방법

abcjava 2023. 4. 6. 20:43
반응형

커스텀 디렉티브의 ng-change 구현 방법

이런 템플릿이 있는 지시가 있어요

<div>
    <div ng-repeat="item in items" ng-click="updateModel(item)">
<div>

내 지시사항은 다음과 같이 선언됩니다.

return {
    templateUrl: '...',
    restrict: 'E',
    require: '^ngModel',
    scope: {
        items: '=',
        ngModel: '=',
        ngChange: '&'
    },
    link: function postLink(scope, element, attrs) 
    {
        scope.updateModel = function(item)
        {
             scope.ngModel = item;
             scope.ngChange();
        }
    }
}

나는 가지고 싶다ng-change항목이 클릭되고 값이 지정되면 호출됩니다.foo는 이미 변경되었습니다.

즉, 내 지시가 다음과 같이 구현되는 경우:

<my-directive items=items ng-model="foo" ng-change="bar(foo)"></my-directive>

전화할 수 있을 것 같습니다.bar가치가 있을 때foo가 갱신되었습니다.

상기의 코드와 함께,ngChange호출은 성공했지만 오래된 값으로 호출됩니다.foo새로 갱신된 값 대신.

문제를 해결하는 한 가지 방법은 전화하는 것입니다.ngChange미래의 어느 시점에서 실행할 타임아웃 내의 값foo는 이미 변경되었습니다.그러나 이 솔루션에서는 실행 순서를 제어할 수 없기 때문에 보다 우아한 솔루션이 필요하다고 생각합니다.

감시자가 필요할 수도 있어요foo하지만 이 솔루션에서는 실제적인 영향을 주지 않습니다.ngChange그 방법, 그리고 나는 시청자들이 기억력을 많이 소비한다고 들었다.

어떻게 할 수 있을까요?ngChange타임아웃이나 워처 없이 동기적으로 실행됩니까?

예: http://plnkr.co/edit/8H6QDO8OYiOyOx8efhyJ?p=preview

필요한 경우ngModel그냥 전화하면 돼$setViewValue에서ngModelController은 암묵적으로 평가됩니다.ng-change링크 함수의 네 번째 파라미터는 ngModelCtrl이어야 합니다.다음 코드는ng-change당신의 지시를 위해 일하세요.

link : function(scope, element, attrs, ngModelCtrl){
    scope.updateModel = function(item) {
        ngModelCtrl.$setViewValue(item);
    }
}

솔루션이 작동하려면 myDirective의 격리 범위에서 ngChange 및 ngModel을 삭제하십시오.

다음은 http://plnkr.co/edit/UefUzOo88MwOMkpgeX07?p=preview의 장점입니다.

dr;dr

제 경험상 ngModelCtrl에서 상속받으면 됩니다.ng-change메서드를 사용하면 식이 자동으로 평가됩니다.ngModelCtrl.$setViewValue

angular.module("myApp").directive("myDirective", function(){
  return {
    require:"^ngModel", // this is important, 
    scope:{
      ... // put the variables you need here but DO NOT have a variable named ngModel or ngChange 
    }, 
    link: function(scope, elt, attrs, ctrl){ // ctrl here is the ngModelCtrl
      scope.setValue = function(value){
        ctrl.$setViewValue(value); // this line will automatically eval your ng-change
      };
    }
  };
});

더 정확히 말하면

ng-change평가됩니다.ngModelCtrl.$commitViewValue() ngModel의 오브젝트 참조가 변경된 경우.방법$commitViewValue()에 의해 자동으로 호출됩니다.$setViewValue(value, trigger)trigger 인수를 사용하지 않거나 ngModelOptions를 사전 설정하지 않은 경우.

제가 지정한 것은ng-change의 참조가 자동적으로 트리거 되는 경우, 자동적으로 트리거 됩니다.$viewValue변경되었다.이 경우ngModel는 입니다.string또는int,그것에 대해 염려하실 필요는 없어요.만약 당신이ngModel오브젝트이며, 그 속성 중 일부를 변경하는 것 뿐입니다.$setViewValue는 하지 않습니다.ngChange.

투고 시작부터 코드 예를 들면

scope.setValue = function(value){
    ctrl.$setViewValue(value); // this line will automatically evalyour ng-change
};
scope.updateValue = function(prop1Value){
    var vv = ctrl.$viewValue;
    vv.prop1 = prop1Value;
    ctrl.$setViewValue(vv); // this line won't eval the ng-change expression
};

몇 가지 조사를 한 결과, 최선의 접근법은 다음과 같은 방법을 사용하는 것 같습니다.$timeout(callback, 0).

합니다.$digest이치노

그래서 제 경우, 해결책은

$timeout(scope.ngChange, 0);

이렇게 하면 콜백의 시그니처가 무엇이든 상관없습니다.콜백은 부모 범위에서 정의한 대로 실행됩니다.

이러한 변경이 적용된 플렁커는 다음과 같습니다. http://plnkr.co/edit/9MGptJpSQslk8g8tD2bZ?p=preview

Samuli Ulmanen과 lucienBertin의 답변은 Angular에서 조금 더 읽기는 하지만 그것을 증명합니다.JS 문서에서는 이 처리 방법에 대한 추가 조언을 제공합니다(https://docs.angularjs.org/api/ng/type/ngModel.NgModelController) 참조).

특히 $setViewValue(myObj)에 객체를 전달하는 경우.각진JS 문서 상태:

표준 입력과 함께 사용할 경우 뷰 값은 항상 문자열이 됩니다(경우에 따라 입력의 Date 개체와 같은 다른 유형으로 구문 분석됩니다.그러나 사용자 지정 컨트롤이 개체를 이 메서드에 전달할 수도 있습니다.이 경우 $setViewValue에 전달하기 전에 오브젝트의 복사본을 만들어야 합니다.이는 ngModel이 객체의 상세 감시를 수행하지 않고 ID 변경만 찾기 때문입니다.객체의 속성만 변경하면 ngModel은 객체가 변경되었음을 인식하지 못하고 $pars 및 $validators 파이프라인을 호출하지 않습니다.따라서 $setViewValue로 전달된 복사본의 속성을 변경하지 마십시오.그렇지 않으면 스코프의 모델 값이 잘못 변경될 수 있습니다.

구체적인 경우 모델이 모멘트 날짜 객체이기 때문에 setViewValue를 호출하기 전에 먼저 객체를 복제해야 합니다.방법을 이 좋다: i한한 method method method i i i i i i i i i i i i i i i i i i i i i i i i 。var b = moment(a);

link : function(scope, elements, attrs, ctrl) {
    scope.updateModel = function (value) {
        if (ctrl.$viewValue == value) {
            var copyOfObject = moment(value);
            ctrl.$setViewValue(copyOfObject);
        }
        else
        {
            ctrl.$setViewValue(value);
        }
    };
}

는 기본 것은 모델이 업데이트되지 않는 입니다. 즉, 기본 모델은 업데이트되지 않고 나중에 이 발생한다는 것입니다.scope.updateModel실행이 완료되었습니다. 경우,ngChange에 대한 내용을 세부 .ngChange이미 적용된 모델 업데이트에 의존하는 것이 아니라

은, 「」, 「」를 호출했을 에, 로컬 할 수 .ngChange. 값을 ""에서 할 수 있는 수 ng-change★★★★★★ 。

예를 들어 다음과 같습니다.

scope.updateModel = function(item)
{
    scope.ngModel = item;
    scope.ngChange({newValue: item});
}

HTML에서:

<my-directive ng-model="foo" items=items ng-change="bar(newValue)"></my-directive>

참조: http://plnkr.co/edit/4CQBEV1S2wFFwKWbWec3?p=preview

언급URL : https://stackoverflow.com/questions/24754005/how-to-implement-an-ng-change-for-a-custom-directive

반응형