지시문에서 컨트롤러로 AngularJS 범위 변수를 전달하는 가장 쉬운 방법은 무엇입니까?


답변:


150

2014/8/25에 편집 : 여기 에서 분기했습니다.

감사합니다 @anvarik.

다음은 JSFiddle 입니다. 어디서 포크했는지 잊었습니다. 그러나 이것은 =와 @의 차이점을 보여주는 좋은 예입니다.

<div ng-controller="MyCtrl">
    <h2>Parent Scope</h2>
    <input ng-model="foo"> <i>// Update to see how parent scope interacts with component scope</i>    
    <br><br>
    <!-- attribute-foo binds to a DOM attribute which is always
    a string. That is why we are wrapping it in curly braces so
    that it can be interpolated. -->
    <my-component attribute-foo="{{foo}}" binding-foo="foo"
        isolated-expression-foo="updateFoo(newFoo)" >
        <h2>Attribute</h2>
        <div>
            <strong>get:</strong> {{isolatedAttributeFoo}}
        </div>
        <div>
            <strong>set:</strong> <input ng-model="isolatedAttributeFoo">
            <i>// This does not update the parent scope.</i>
        </div>
        <h2>Binding</h2>
        <div>
            <strong>get:</strong> {{isolatedBindingFoo}}
        </div>
        <div>
            <strong>set:</strong> <input ng-model="isolatedBindingFoo">
            <i>// This does update the parent scope.</i>
        </div>
        <h2>Expression</h2>    
        <div>
            <input ng-model="isolatedFoo">
            <button class="btn" ng-click="isolatedExpressionFoo({newFoo:isolatedFoo})">Submit</button>
            <i>// And this calls a function on the parent scope.</i>
        </div>
    </my-component>
</div>
var myModule = angular.module('myModule', [])
    .directive('myComponent', function () {
        return {
            restrict:'E',
            scope:{
                /* NOTE: Normally I would set my attributes and bindings
                to be the same name but I wanted to delineate between
                parent and isolated scope. */                
                isolatedAttributeFoo:'@attributeFoo',
                isolatedBindingFoo:'=bindingFoo',
                isolatedExpressionFoo:'&'
            }        
        };
    })
    .controller('MyCtrl', ['$scope', function ($scope) {
        $scope.foo = 'Hello!';
        $scope.updateFoo = function (newFoo) {
            $scope.foo = newFoo;
        }
    }]);

29
훌륭한 설명과 예! 문서가 왜 그렇게 복잡한 지 궁금한가요? ... 아니면 제가 그다지 훌륭한 프로그래머가 아닌 건가요?
kshep92 2013 년

2
이 바이올린은에서와 같이 작동하지만 각도 버전을 최신 버전으로 변경하면 (즉, 1.0.1에서 1.2.1로) 더 이상 작동하지 않습니다. 구문에 대해 뭔가 변경된 것 같습니다.
eremzeit 2014

2
마지막으로 말이되는 명확한 예입니다. 2 시간의 두통이 10 초 만에 해결되었습니다.
크리스

4
방법이 지시어에서 컨트롤러로가 아니라 컨트롤러에서 지시어로 값을 전달하는 방법을 설명하는 동안 모든 사람들이이 답변에 투표하는 방법은 무엇입니까?
Tiberiu C.

2
isolatedBindingFoo : '= bindingFoo'는 지시문에서 컨트롤러로 데이터를 전달할 수 있습니다. 또는 서비스를 사용할 수 있습니다. 다른 사람에게 반대표를 던지기 전에 이해가 안되는 경우 먼저 물어볼 수 있습니다.
maxisam 2015

70

angular가 변수를 평가할 때까지 기다리십시오.

나는 이것을 많이 다루었 고 "="스코프에서 정의 된 변수로도 작동하지 못했습니다 . 상황에 따른 세 가지 해결책이 있습니다.


솔루션 # 1


변수가 지시문에 전달되었을 때 아직 각도로 평가되지 않았 음을 발견 했습니다 . 즉, 평가를 기다리지 않는 한 링크 또는 앱 컨트롤러 함수 내부에서 액세스하여 템플릿에서 사용할 수 있습니다.

귀하의 경우 변수가 변화하고 , 또는 요청을 통해 가져온, 당신은 사용해야 $observe또는 $watch:

app.directive('yourDirective', function () {
    return {
        restrict: 'A',
        // NB: no isolated scope!!
        link: function (scope, element, attrs) {
            // observe changes in attribute - could also be scope.$watch
            attrs.$observe('yourDirective', function (value) {
                if (value) {
                    console.log(value);
                    // pass value to app controller
                    scope.variable = value;
                }
            });
        },
        // the variable is available in directive controller,
        // and can be fetched as done in link function
        controller: ['$scope', '$element', '$attrs',
            function ($scope, $element, $attrs) {
                // observe changes in attribute - could also be scope.$watch
                $attrs.$observe('yourDirective', function (value) {
                    if (value) {
                        console.log(value);
                        // pass value to app controller
                        $scope.variable = value;
                    }
                });
            }
        ]
    };
})
.controller('MyCtrl', ['$scope', function ($scope) {
    // variable passed to app controller
    $scope.$watch('variable', function (value) {
        if (value) {
            console.log(value);
        }
    });
}]);

그리고 여기에 html이 있습니다 (괄호를 기억하세요!) :

<div ng-controller="MyCtrl">
    <div your-directive="{{ someObject.someVariable }}"></div>
    <!-- use ng-bind in stead of {{ }}, when you can to avoids FOUC -->
    <div ng-bind="variable"></div>
</div>

함수를 "="사용하는 경우 범위에서 변수를 로 설정해서는 안됩니다 $observe. 또한 개체를 문자열로 전달하므로 개체를 전달하는 경우 솔루션 # 2 또는 scope.$watch(attrs.yourDirective, fn)(또는 변수가 변경되지 않으면 # 3 )을 사용합니다.


솔루션 # 2


귀하의 경우 변수가 예를 들어 다른 컨트롤러에서 만든 , 그러나 다만 각도가 응용 프로그램 컨트롤러로 전송하기 전에 평가를 할 때까지 기다릴 필요가, 우리가 사용할 수있는 $timeout(가) 때까지 기다려야 $apply실행하고있다. 또한이를 사용 $emit하여 부모 범위 앱 컨트롤러로 보내야합니다 (지시문의 격리 된 범위로 인해).

app.directive('yourDirective', ['$timeout', function ($timeout) {
    return {
        restrict: 'A',
        // NB: isolated scope!!
        scope: {
            yourDirective: '='
        },
        link: function (scope, element, attrs) {
            // wait until after $apply
            $timeout(function(){
                console.log(scope.yourDirective);
                // use scope.$emit to pass it to controller
                scope.$emit('notification', scope.yourDirective);
            });
        },
        // the variable is available in directive controller,
        // and can be fetched as done in link function
        controller: [ '$scope', function ($scope) {
            // wait until after $apply
            $timeout(function(){
                console.log($scope.yourDirective);
                // use $scope.$emit to pass it to controller
                $scope.$emit('notification', scope.yourDirective);
            });
        }]
    };
}])
.controller('MyCtrl', ['$scope', function ($scope) {
    // variable passed to app controller
    $scope.$on('notification', function (evt, value) {
        console.log(value);
        $scope.variable = value;
    });
}]);

그리고 다음은 html입니다 (괄호 없음!) :

<div ng-controller="MyCtrl">
    <div your-directive="someObject.someVariable"></div>
    <!-- use ng-bind in stead of {{ }}, when you can to avoids FOUC -->
    <div ng-bind="variable"></div>
</div>

솔루션 # 3


귀하의 경우 변수가 변경되지 당신이 당신의 지시에 평가해야합니다, 당신은 사용할 수있는 $eval기능 :

app.directive('yourDirective', function () {
    return {
        restrict: 'A',
        // NB: no isolated scope!!
        link: function (scope, element, attrs) {
            // executes the expression on the current scope returning the result
            // and adds it to the scope
            scope.variable = scope.$eval(attrs.yourDirective);
            console.log(scope.variable);

        },
        // the variable is available in directive controller,
        // and can be fetched as done in link function
        controller: ['$scope', '$element', '$attrs',
            function ($scope, $element, $attrs) {
                // executes the expression on the current scope returning the result
                // and adds it to the scope
                scope.variable = scope.$eval($attrs.yourDirective);
                console.log($scope.variable);
            }
         ]
    };
})
.controller('MyCtrl', ['$scope', function ($scope) {
    // variable passed to app controller
    $scope.$watch('variable', function (value) {
        if (value) {
            console.log(value);
        }
    });
}]);

그리고 여기에 html이 있습니다 (괄호를 기억하세요!) :

<div ng-controller="MyCtrl">
    <div your-directive="{{ someObject.someVariable }}"></div>
    <!-- use ng-bind instead of {{ }}, when you can to avoids FOUC -->
    <div ng-bind="variable"></div>
</div>

또한이 답변을 살펴보십시오 : https://stackoverflow.com/a/12372494/1008519

FOUC (스타일이 지정되지 않은 콘텐츠 플래시) 문제에 대한 참조 : http://deansofer.com/posts/view/14/AngularJs-Tips-and-Tricks-UPDATED

관심있는 분들을 위해 : 각도 수명주기에 대한 기사가 있습니다.


1
때로는 ng-if="someObject.someVariable"지시문 (또는 지시문을 속성으로 사용하는 요소)에 대한 간단한 것으로 충분합니다. 지시문 someObject.someVariable은 정의 된 후에 만 시작 됩니다.
marapet 2015-08-06
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.