AngularJS-자식 범위에 대한 액세스


110

다음 컨트롤러가있는 경우 :

function parent($scope, service) {
    $scope.a = 'foo';

    $scope.save = function() {
        service.save({
            a:  $scope.a,
            b:  $scope.b
        });
    }
}

function child($scope) {
    $scope.b = 'bar';
}

parent읽을 수있는 적절한 방법 bchild무엇입니까? bin 을 정의 할 필요가 있다면, 그것이 관련이있는 것이 아닌 무언가를 설명하는 속성 parent이라고 가정하면 의미 론적으로 잘못 되지 않습니까?bchildparent

업데이트 : 어린이가 두 명 이상이 있다면, 그것에 대해 더 생각 b이에 대한 충돌 만들 것입니다 parent어떤에서 b검색 할 수 있습니다. 내 질문이 남아 있습니다. 올바른 액세스 방법 bparent무엇입니까?


1
또한 다음을 읽어보십시오 : stackoverflow.com/questions/14049480/… angularJS의 범위 및 상속에 대한 매우 훌륭하고 심층적 인 개요.
Martijn

답변:


162

AngularJS의 스코프는 프로토 타입 상속을 사용합니다. 자식 스코프에서 속성을 찾을 때 인터프리터는 자식에서 시작하여 프로토 타입 체인을 찾고 그 반대가 아니라 속성을 찾을 때까지 부모로 계속합니다.

문제에 대한 Vojta의 의견 확인 https://groups.google.com/d/msg/angular/LDNz_TQQiNE/ygYrSvdI0A0J

간단히 말해서 : 부모 범위에서 자식 범위에 액세스 할 수 없습니다.

솔루션 :

  1. 부모에서 속성을 정의하고 자식에서 액세스합니다 (위 링크 참조).
  2. 서비스를 사용하여 상태 공유
  3. 이벤트를 통해 데이터를 전달합니다. $emit루트 범위까지 이벤트를 부모에게 위쪽으로 보내고 $broadcast아래쪽으로 이벤트를 전달합니다. 이것은 의미 상 올바른 것을 유지하는 데 도움이 될 수 있습니다.

8
또한 $ emit와 $ broadcast의 차이점은 $ emit는 취소 가능하고 $ broadcast는 불가능하다는 것입니다.
Azri Jamil

하위 범위를 얻고 싶은 한 곳은 단위 테스트 지시문입니다. transcluded 지시문이있는 경우 범위는 요소를 컴파일하는 데 사용되는 범위의 하위입니다. 테스트를 위해 컴파일 된 지침의 범위에 액세스하는 것은 어렵습니다.
pmc jul

감사. 또 다른 옵션이 될 수 localStorage와 같은 종속성으로 ngStorage.
아카 쉬

81

jm-의 대답이이 경우를 처리하는 가장 좋은 방법이지만 향후 참조를 위해 범위의 $$ childHead, $$ childTail, $$ nextSibling 및 $$ prevSibling 멤버를 사용하여 하위 범위에 액세스 할 수 있습니다. 이들은 문서화되어 있지 않으므로 예고없이 변경 될 수 있지만 실제로 범위를 통과해야하는 경우 존재합니다 .

// get $$childHead first and then iterate that scope's $$nextSiblings
for(var cs = scope.$$childHead; cs; cs = cs.$$nextSibling) {
    // cs is child scope
}

깡깡이


49

이것을 시도 할 수 있습니다.

$scope.child = {} //declare it in parent controller (scope)

그런 다음 자식 컨트롤러 (범위)에서 다음을 추가합니다.

var parentScope = $scope.$parent;
parentScope.child = $scope;

이제 부모는 자식의 범위에 액세스 할 수 있습니다.


1
매우 깨끗하고 간단합니다. 여기에 추가하려면 바인딩이 없으므로 parentScope.child가 그 순간에 자식 범위를 보유하고 있으므로 위와 같이 선언 할 때만 인식하십시오. 이를 해결하기 위해 $ scope. $ watch (function () {parentScope.child = $ scope}); 모든 다이제스트 후에 새 범위를 상위 항목으로 푸시합니다. 부모 쪽에서 html의 시각적 개체에 대해 자식 범위를 사용하는 경우 자식 변수에 감시를 추가하고 다음과 같이 범위를 업데이트하도록 지시해야합니다. $ scope. $ watch ( 'child', function ( ) {$ scope. $ evalAsync ();}); . 이것이 누군가 시간을 절약하기를 바랍니다!
IfTrue 2015 년

2
@IfTrue 나는 $ watch ()가 필요하지 않다고 생각합니다. 이들은 객체이며 참조로 전달됩니다.
Swanidhi

2
@Swanidhi = 나는 당신이 의미하는 바를 알고 있고 나도 그렇게 생각했지만 댓글을 쓸 당시 실험을 할 때는 작동하지 않았습니다. 이 작업에서 방출 / 방송으로 전환 한 것이 가치있는 일입니다.
IfTrue 2015 년

1
Type Script에서 어떻게하나요?
ATHER

나를위한 베스트 답변 !! 자바 스크립트가 참조로 처리 객체의 좋은 예
카스 가우 탐

4

한 가지 가능한 해결 방법은 init 함수를 사용하여 부모 컨트롤러에 자식 컨트롤러를 삽입하는 것입니다.

가능한 구현 :

<div ng-controller="ParentController as parentCtrl">
   ...

    <div ng-controller="ChildController as childCtrl" 
         ng-init="ChildCtrl.init()">
       ...
    </div>
</div>

어디에서 ChildController당신은 :

app.controller('ChildController',
    ['$scope', '$rootScope', function ($scope, $rootScope) {
    this.init = function() {
         $scope.parentCtrl.childCtrl = $scope.childCtrl;
         $scope.childCtrl.test = 'aaaa';
    };

}])

이제에서 다음 ParentController을 사용할 수 있습니다.

app.controller('ParentController',
    ['$scope', '$rootScope', 'service', function ($scope, $rootScope, service) {

    this.save = function() {
        service.save({
            a:  $scope.parentCtrl.ChildCtrl.test
        });
     };

}])

중요 :
제대로 작동하려면 지시문을 사용 하고 html에서했던 것처럼 ng-controller각 컨트롤러의 이름을 바꿔야합니다 as.

팁 : 프로세스 중에
크롬 플러그인 ng-inspector를 사용하십시오 . 나무를 이해하는 데 도움이 될 것입니다.


3

$ emit$ broadcast 사용 (위의 주석에서 walv에 의해 언급 됨)

이벤트를 위쪽으로 시작하려면 (자식에서 부모로)

$scope.$emit('myTestEvent', 'Data to send');

이벤트를 아래쪽으로 시작하려면 (부모에서 자식으로)

$scope.$broadcast('myTestEvent', {
  someProp: 'Sending you some data'
});

마지막으로 들어

$scope.$on('myTestEvent', function (event, data) {
  console.log(data);
});

자세한 내용은 : -https : //toddmotto.com/all-about-angulars-emit-broadcast-on-publish-subscribing/

즐겨 :)


1

예, 자식 컨트롤러의 변수를 부모 컨트롤러의 변수에 할당 할 수 있습니다. 이것은 가능한 한 가지 방법입니다.

개요 : 아래 코드의 주요 목적은 자식 컨트롤러의 $ scope.variable을 부모 컨트롤러의 $ scope.assign에 할당하는 것입니다.

설명 : 두 개의 컨트롤러가 있습니다. html에서 부모 컨트롤러가 자식 컨트롤러를 포함하고 있음을 알 수 있습니다. 즉, 상위 컨트롤러가 하위 컨트롤러보다 먼저 실행됩니다. 따라서 먼저 setValue ()가 정의되고 컨트롤이 자식 컨트롤러로 이동합니다. $ scope.variable은 "하위"로 할당됩니다. 그런 다음이 자식 범위는 부모 컨트롤러의 기능에 인수로 전달됩니다. 여기서 $ scope.assign은 값을 "child"로 가져옵니다.

<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<script type="text/javascript">
    var app = angular.module('myApp',[]);

    app.controller('child',function($scope){
        $scope.variable = "child";
        $scope.$parent.setValue($scope);
    });

    app.controller('parent',function($scope){
        $scope.setValue = function(childscope) {
            $scope.assign = childscope.variable;
        }
    });

</script>
<body ng-app="myApp">
 <div ng-controller="parent">
    <p>this is parent: {{assign}}</p>
    <div ng-controller="child">
        <p>this is {{variable}}</p>
    </div>
 </div>
</body>
</html>
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.