각도 지시문이 지시문 속성에 지정된 표현식의 함수에 인수를 전달할 수 있습니까?


160

callback격리 범위와 함께 지정된 특성 을 사용하는 양식 지시문이 있습니다 .

scope: { callback: '&' }

그것은 내부 앉는 ng-repeatI 안으로 통과 발현되도록이 포함 id콜백 함수의 인수로서 오브젝트 :

<directive ng-repeat = "item in stuff" callback = "callback(item.id)"/>

지시문을 마치면 $scope.callback()컨트롤러 함수에서 호출 합니다. 대부분의 경우 이것은 괜찮으며, 내가하고 싶은 전부이지만 때로는 directive자체 내부에서 다른 인수를 추가하고 싶습니다 .

이것을 허용 할 각도 표현이 있습니까 : $scope.callback(arg2), 그 결과 callback로 호출되는 arguments = [item.id, arg2]?

그렇지 않은 경우,이를 수행하는 가장 쉬운 방법은 무엇입니까?

나는 이것이 효과가 있음을 발견했다.

<directive 
  ng-repeat = "item in stuff" 
  callback = "callback" 
  callback-arg="item.id"/>

scope { callback: '=', callbackArg: '=' }

지시어 호출

$scope.callback.apply(null, [$scope.callbackArg].concat([arg2, arg3]) );

그러나 특히 깔끔하지 않다고 생각하며 격리 범위에 추가 물건을 넣는 것과 관련이 있습니다.

더 좋은 방법이 있습니까?

플 런커 놀이터는 여기 (콘솔을 열어 둔 상태).


"callback ="이름 지정 속성이 잘못되었습니다. 실제로는 콜백 자체가 아니라 콜백 평가입니다.
Dmitri Zaitsev

@DmitriZaitsev JavaScript 함수로 평가되는 콜백 각도 표현식입니다. 나는 그것이 JavaScript 함수 자체가 아니라는 것이 상당히 분명하다고 생각합니다. 그것은 단지 선호 사항이지만 모든 속성에 "-expression"을 붙일 필요는 없습니다. 이것은 ngAPI 와 일치 합니다. 예를 들어 ng-click="someFunction()"함수 실행으로 평가되는 표현식입니다.
Ed Hinchliffe

"콜백"이라는 각도 표현은 본 적이 없습니다. 이름이있을 때 항상 호출되도록 전달하는 함수입니다. 예제에서 "콜백"이라는 함수를 사용하여 상황을 더욱 혼란스럽게 만들 수도 있습니다.
Dmitri Zaitsev

당신이 혼란 스러울 지 모르겠습니다. 내 예제에서는 지시문 정의 객체 $scope.callbackcallback="someFunction"속성과 속성 으로 설정됩니다 scope: { callback: '=' }. $scope.callback 이다 나중에 호출되는 함수. 실제 속성 은 분명히 문자열입니다-항상 HTML의 경우입니다.
Ed Hinchliffe

속성과 함수의 이름을 동일하게 "콜백"이라고합니다. 이것이 혼란을위한 레시피입니다. 정말 피하기 쉽습니다.
Dmitri Zaitsev

답변:


215

@ lex82에서 언급 한 것처럼 콜백을 선언하면

callback = "callback(item.id, arg2)"

객체 맵을 사용하여 지시문 범위에서 콜백 메소드를 호출 할 수 있으며 바인딩을 올바르게 수행합니다. 처럼

scope.callback({arg2:"some value"});

$ 구문 분석이 필요하지 않습니다. 내 바이올린 (콘솔 로그) 참조 http://jsfiddle.net/k7czc/2/

업데이트 : 설명서 에 작은 예가 있습니다 .

& 또는 & attr-상위 범위의 컨텍스트에서 표현식을 실행하는 방법을 제공합니다. attr 이름이 지정되지 않으면 속성 이름이 로컬 이름과 동일한 것으로 간주됩니다. 범위의 위젯 정의 {localFn : '& myAttr'}를 지정하면 격리 범위 특성 localFn은 count = count + value 표현식의 함수 랩퍼를 가리 킵니다. 표현식을 통해 격리 된 범위에서 상위 범위로 데이터를 전달하는 것이 바람직한 경우가 종종 있는데, 이는 로컬 변수 이름 및 값의 맵을 표현식 랩퍼 fn에 전달하여 수행 할 수 있습니다. 예를 들어, 표현식이 increment (amount) 인 경우 localFn을 localFn ({amount : 22})로 호출하여 금액 값을 지정할 수 있습니다.


4
아주 좋아요! 이것은 어디에나 문서화되어 있습니까?
ach

12
지시어 정의에서 때로는 전달할 매개 변수가 무엇인지 모르기 때문에 이것이 좋은 해결책이라고 생각하지 않습니다.
OMGPOP

이것은 좋은 해결책이며 그것에 대해 감사합니다.하지만 대답에는 약간의 조수가 필요하다고 생각합니다. lex82는 누구이며 무엇을 언급 했습니까?
Wtower

재미있는 접근법. ANY 매개 변수 (또는 여러 개)가있는 함수를 전달하려면 어떻게해야합니까? 함수와 매개 변수에 대해 전혀 모르며 지시문 내부의 일부 이벤트에서 실행해야합니다. 어떻게해야합니까? 예를 들어 지시문에서 onchangefunc = 'myCtrlFunc (dynamicVariableHere)'
trainoasis

58

다른 답변에는 아무런 문제가 없지만 지시문 속성에 함수를 전달할 때 다음 기술을 사용합니다.

HTML에 지시문을 포함시킬 때는 괄호를 사용하지 마십시오.

<my-directive callback="someFunction" />

그런 다음 지시문의 링크 또는 컨트롤러에서 함수를 "포장 해제"하십시오. 다음은 예입니다.

app.directive("myDirective", function() {

    return {
        restrict: "E",
        scope: {
            callback: "&"                              
        },
        template: "<div ng-click='callback(data)'></div>", // call function this way...
        link: function(scope, element, attrs) {
            // unwrap the function
            scope.callback = scope.callback(); 

            scope.data = "data from somewhere";

            element.bind("click",function() {
                scope.$apply(function() {
                    callback(data);                        // ...or this way
                });
            });
        }
    }
}]);    

"unwrapping"단계를 통해보다 자연스러운 구문을 사용하여 함수를 호출 할 수 있습니다. 또한 함수를 전달할 수있는 다른 지시문에 중첩 된 경우에도 지시문이 올바르게 작동합니다. 언 래핑을 수행하지 않은 경우 다음과 같은 시나리오가있는 경우 :

<outer-directive callback="someFunction" >
    <middle-directive callback="callback" >
        <inner-directive callback="callback" />
    </middle-directive>
</outer-directive>

그런 다음 내부 지시문에서 다음과 같이 끝납니다.

callback()()()(data); 

다른 중첩 시나리오에서는 실패합니다.

이 기술을 Dan Wahlin ( http://weblogs.asp.net/dwahlin/creating-custom-angularjs-directives-part-3-isolate-scope-and-function-parameters) 의 훌륭한 기사에서 수정했습니다 .

함수를보다 자연스럽게 호출하고 프로젝트에서 발생한 중첩 문제를 해결하기 위해 래핑 해제 단계를 추가했습니다.


2
좋은 접근 방법이지만 this지시문의 범위를 사용하기 때문에 콜백 메소드 내부에서 포인터 를 사용할 수 없습니다 . Typescript를 사용하고 있으며 콜백은 다음과 같습니다.public validateFirstName(firstName: string, fieldName: string): ng.IPromise<boolean> { var deferred = this.mQService.defer<boolean>(); ... .then(() => deferred.resolve(true)) .catch((msg) => { deferred.reject(false); }); return deferred.promise; }
ndee

1
참고 : 중첩 된 지시문이 있고 콜백을 위쪽으로 전파하려는 경우 트리거하는 콜백뿐만 아니라 각 지시문에서 랩 해제해야합니다.
Episodex

43

지시문 ( myDirective)에서 :

...
directive.scope = {  
    boundFunction: '&',
    model: '=',
};
...
return directive;

지시문 템플릿에서 :

<div 
data-ng-repeat="item in model"  
data-ng-click='boundFunction({param: item})'>
{{item.myValue}}
</div>

소스에서 :

<my-directive 
model='myData' 
bound-function='myFunction(param)'>
</my-directive>

... 여기서 myFunction컨트롤러에 정의되어 있습니다.

참고 param지시어 템플릿 바인딩에 깔끔하게에 param소스, 그리고으로 설정됩니다 item.


link지시문 의 속성 내에서 ( "내부") 호출하려면 매우 비슷한 방법을 사용하십시오.

...
directive.link = function(isolatedScope) {
    isolatedScope.boundFunction({param: "foo"});
};
...
return directive;

소스가있는 동안 : bound-function = 'myFunction (obj1.param, obj2.param)'> 그렇다면 어떻게 진행합니까?
Ankit Pandey

15

예, 더 좋은 방법 이 있습니다. 지시문에서 $ parse 서비스 를 사용 하여 부모 범위의 컨텍스트에서 표현식을 평가하는 동안 표현식의 특정 식별자를 지시문 내에서만 볼 수있는 값에 바인딩 할 수 있습니다.

$parse(attributes.callback)(scope.$parent, { arg2: yourSecondArgument });

지시문의 속성에 액세스 할 수있는 지시문의 링크 함수에이 행을 추가하십시오.

그러면 callback = "callback(item.id, arg2)"arg2가 지시문 내의 $ parse 서비스에 의해 yourSecondArgument에 바인딩되므로 콜백 속성을 설정할 수 있습니다 . 지시문은 정확하게이 메커니즘을 사용하여 지시문에 전달 된 표현식 내부의 식별자 ng-click를 통해 클릭 이벤트에 액세스 할 수있게합니다 $event.

callback이 솔루션으로 격리 된 범위의 구성원 을 만들 필요는 없습니다 .


3
를 사용 scope.$parent하면 지시어가 "누수"됩니다. 잘 디자인 된 캡슐화 된 구성 요소가 아닌 외부 세계를 너무 많이 "인식"합니다.
Dmitri Zaitsev

3
글쎄, 그것은 부모 범위를 가지고 있지만 범위의 특정 필드에 액세스하지 않는다는 것을 알고 있으므로 이것이 용납 될 수 있다고 생각합니다.
lex82

0

나를 위해 다음과 같이 일했습니다.

지시문에서 다음과 같이 선언하십시오.

.directive('myDirective', function() {
    return {
        restrict: 'E',
        replace: true,
        scope: {
            myFunction: '=',
        },
        templateUrl: 'myDirective.html'
    };
})  

지시문 템플릿에서 다음과 같은 방식으로 사용하십시오.

<select ng-change="myFunction(selectedAmount)">

그런 다음 지시문을 사용할 때 다음과 같이 함수를 전달하십시오.

<data-my-directive
    data-my-function="setSelectedAmount">
</data-my-directive>

선언에 의해 함수를 전달하면 지시문에서 호출되고 매개 변수가 채워집니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.