Programming

AngularJS에서 격리 된 범위없이 지시문에서 컨트롤러 함수 호출

procodes 2020. 8. 28. 08:22
반응형

AngularJS에서 격리 된 범위없이 지시문에서 컨트롤러 함수 호출


격리 된 범위를 사용하지 않고 지시문 내에서 부모 범위의 함수를 호출하는 방법을 찾을 수없는 것 같습니다. 격리 된 범위를 사용하는 경우 격리 된 영역에서 "&"를 사용하여 부모 범위의 함수에 액세스 할 수 있지만 필요하지 않은 경우 격리 된 범위를 사용하면 결과가 발생한다는 것을 알고 있습니다. 다음 HTML을 고려하십시오.

<button ng-hide="hideButton()" confirm="Are you sure?" confirm-action="doIt()">Do It</button>

이 간단한 예제에서는 JavaScript 확인 ​​대화 상자를 표시하고 확인 대화 상자에서 "확인"을 클릭 한 경우에만 doIt ()을 호출하려고합니다. 격리 된 범위를 사용하면 간단합니다. 지시문은 다음과 같습니다.

.directive('confirm', function () {
    return {
        restrict: 'A',
        scope: {
            confirm: '@',
            confirmAction: '&'
        },
        link: function (scope, element, attrs) {
            element.bind('click', function (e) {
                if (confirm(scope.confirm)) {
                    scope.confirmAction();
                }
            });
        }
    };
})

그러나 문제는 격리 된 범위를 사용하고 있기 때문에 위의 예제에서 ng-hide는 더 이상 부모 범위에 대해 실행되지 않고 격리 된 범위에서 실행 됩니다 (모든 지시문에서 격리 된 범위를 사용하면 해당 요소의 모든 지시문이 격리 된 범위 사용). 다음은 ng-hide가 작동하지 않는 위 예제 의 jsFiddle 입니다. (이 바이올린에서는 입력 상자에 "예"를 입력 할 때 버튼이 숨겨져 야합니다.)

대안은 격리 된 범위를 사용하지 않는 것입니다.이 지시문의 범위를 격리 할 필요가 없기 때문에 실제로 여기에서 원하는 것입니다. 내가 가진 유일한 문제는 격리 된 범위에 전달하지 않으면 부모 범위에서 메서드를 어떻게 호출 합니까?

여기에 격리 된 범위를 사용하지 않고 ng-hide가 잘 작동 하는 jsfiddle 이 있지만 물론 confirmAction () 호출이 작동하지 않으며 작동하는 방법을 모릅니다.

내가 정말로 찾고있는 대답은 격리 된 범위를 사용하지 않고 외부 범위에서 함수를 호출하는 방법입니다. 이 확인 대화를 다른 방식으로 작동시키는 데 관심이 없습니다.이 질문의 요점은 외부 범위를 호출하는 방법을 알아 내고 부모 범위에 대해 다른 지시문이 작동하도록하는 것입니다.

또는 다른 지시문이 부모 범위에 대해 여전히 작동하는 경우 격리 된 범위를 사용하는 솔루션에 대해 듣고 싶지만 이것이 가능하다고 생각하지 않습니다.


지시문은 함수 만 호출하고 속성에 값을 설정하지 않기 때문에 $ parse 대신 $ eval을 사용할 수 있습니다 (분리되지 않은 범위 사용).

scope.$apply(function() {
    scope.$eval(attrs.confirmAction);
});

또는 더 나은 방법은 $ apply를 사용 하면 $ eval ()이 범위에 대해 인수를 계산합니다.

scope.$apply(attrs.confirmAction);

깡깡이


AngularJS에서 $ parse 서비스를 사용하고 싶습니다.

따라서 귀하의 예를 들어 :

.directive('confirm', function ($parse) {
    return {
        restrict: 'A',

        // Child scope, not isolated
        scope : true,
        link: function (scope, element, attrs) {
            element.bind('click', function (e) {
                if (confirm(attrs.confirm)) {
                    scope.$apply(function(){

                        // $parse returns a getter function to be 
                        // executed against an object
                        var fn = $parse(attrs.confirmAction);

                        // In our case, we want to execute the statement in 
                        // confirmAction i.e. 'doIt()' against the scope 
                        // which this directive is bound to, because the 
                        // scope is a child scope, not an isolated scope. 
                        // The prototypical inheritance of scopes will mean 
                        // that it will eventually find a 'doIt' function 
                        // bound against a parent's scope.
                        fn(scope, {$event : e});
                    });
                }
            });
        }
    };
});

$ parse를 사용하여 속성을 설정하는 것과 관련이 있지만 여기에 오면 그 다리를 건너도록하겠습니다.


hideButton부모 범위를 명시 적으로 호출 합니다.

여기 바이올린이 있습니다 : http://jsfiddle.net/pXej2/5/

업데이트 된 HTML은 다음과 같습니다.

<div ng-app="myModule" ng-controller="myController">
    <input ng-model="showIt"></input>
    <button ng-hide="$parent.hideButton()" confirm="Are you sure?" confirm-action="doIt()">Do It</button>
</div>

내가 가진 유일한 문제는 격리 된 범위에서 전달하지 않으면 부모 범위에서 메서드를 어떻게 호출합니까?

Here is a jsfiddle where I am NOT using isolated scope and the ng-hide is working fine, but, of course, the call to confirmAction() doesn't work and I don't know how to make it work.

First a small point: In this case the outer controller's scope is not the parent scope of the directive's scope; the outer controller's scope is the directive's scope. In other words, variable names used in the directive will be looked up directly in the controller's scope.

Next, writing attrs.confirmAction() doesn't work because attrs.confirmAction for this button,

<button ... confirm-action="doIt()">Do It</button>

is the string "doIt()", and you can't call a string, e.g. "doIt()"().

Your question really is:

How do I call a function when I have its name as a string?

In JavaScript, you mostly call functions using dot notation, like this:

some_obj.greet()

But you can also use array notation:

some_obj['greet']

Note how the index value is a string. So, in your directive you can simply do this:

  link: function (scope, element, attrs) {

    element.bind('click', function (e) {

      if (confirm(attrs.confirm)) {
        var func_str = attrs.confirmAction;
        var func_name = func_str.substring(0, func_str.indexOf('(')); // Or func_str.match(/[^(]+/)[0];
        func_name = func_name.trim();

        console.log(func_name); // => doIt
        scope[func_name]();
      }
    });
  }

참고URL : https://stackoverflow.com/questions/17583004/call-a-controller-function-from-a-directive-without-isolated-scope-in-angularjs

반응형