angularJS : 부모 범위에서 자식 범위 함수를 호출하는 방법


95

부모 범위에서 자식 범위에 정의 된 메서드를 어떻게 호출 할 수 있습니까?

function ParentCntl() {
    // I want to call the $scope.get here
}

function ChildCntl($scope) {
    $scope.get = function() {
        return "LOL";    
    }
}

http://jsfiddle.net/wUPdW/


2
최선의 방법은 서비스를 정의하고 해당 서비스를 두 컨트롤러에 삽입하는 것입니다. 또는 rootscope를 사용하십시오.
tymeJV

답변:


145

$broadcast부모에서 자식으로 사용할 수 있습니다 .

function ParentCntl($scope) {

    $scope.msg = "";
    $scope.get = function(){
        $scope.$broadcast ('someEvent');
        return  $scope.msg;        
    }
}

function ChildCntl($scope) {               
    $scope.$on('someEvent', function(e) {  
        $scope.$parent.msg = $scope.get();            
    });

    $scope.get = function(){
        return "LOL";    
    }
}

작업 바이올린 : http://jsfiddle.net/wUPdW/2/

업데이트 : 덜 결합되고 더 테스트 가능한 다른 버전이 있습니다.

function ParentCntl($scope) {
    $scope.msg = "";
    $scope.get = function(){
        $scope.$broadcast ('someEvent');
        return  $scope.msg;        
    }

    $scope.$on('pingBack', function(e,data) {  
        $scope.msg = data;        
    });
}

function ChildCntl($scope) {               
    $scope.$on('someEvent', function(e) {  
        $scope.$emit("pingBack", $scope.get());        
    });

    $scope.get = function(){
        return "LOL";    
    }
}

바이올린 : http://jsfiddle.net/uypo360u/


꽤 괜찮은데! 그러나 발신자 범위가 어디에 있는지 (내 말은 in $scope.$parent또는 in $scope.$parent.$parent등) 모르면 어떻게됩니까? 아, 예 : params에 콜백을 전달하십시오! :)
user2173353 jul.

@ user2173353 당신 말이 맞습니다. 한 가지 더 방법이 있습니다 : $emit아이에서 부모로. 나는 내 대답을 업데이트하는 시간이 생각 ...
Cherniv

이 경우 자식 컨트롤러가 somwhere 인 글로벌 리스너를 호출하는 것이 좋은 생각입니까? 반 패턴이 아니고 나중에 테스트하기가 어렵습니까? 주사 나 smth를 사용하지 않습니까?
calmbird 2014-08-30

@calmbird, 각 항목은 신중하게 사용해야합니다. 일부는 유사한 경우에 서비스를 사용하는 것을 선호합니다. 어쨌든, 난 (성가신없이 더 우아한 버전을 추가 $parent)
Cherniv

9
이 접근 방식 은 더 깔끔합니다. 에서 콜백을 전달 $broadcast하면 pingBack모두 제거 할 수 있습니다 .
호화

34

다른 해결책을 제안하겠습니다.

var app = angular.module("myNoteApp", []);


app.controller("ParentCntl", function($scope) {
    $scope.obj = {};
});

app.controller("ChildCntl", function($scope) {
    $scope.obj.get = function() {
            return "LOL";    
    };
});

적은 코드와 프로토 타입 상속을 사용합니다.

별안간 밀다


누군가이 접근 방식이 위에서 언급 한 이벤트 중심 접근 방식보다 더 나은지 설명 할 수 있습니까? 그렇다면 그 이유는 무엇입니까? 하위 컨트롤러가있는 다중 레벨 계층 구조가있는 경우 어떻게됩니까? obj.get이 자식 컨트롤러 내의 자식 컨트롤러 내에 정의되어있는 경우 컨트롤러가 동일한 함수 이름을 정의하지 않는 한이 기능이 작동합니까? 미리 감사드립니다.
ZvKa

1
전적으로 사실이 아닌 내가 말한 것을 바로 잡도록하겠습니다. 당신이 말한 것이 맞습니다 : 범위 상속은 한 방향에만 적용됩니다 .... 자식-> 부모. 여기서 실제로 일어나는 일은 $ scope.get을 자식 범위에 정의하면 'get'이 자식 범위에서만 정의된다는 것입니다 (때로는 기본 정의라고도 함). 그러나 $ scope.obj.get을 정의하면 하위 범위는 계층 구조의 상위 범위에 정의 된 obj를 찾습니다.
Canttouchit

3
자식이 자체 격리 범위를 가지고 있다면 어떻게 작동합니까?
Dinesh 2015

2
문제는 격리 된 범위를 언급하는 것이 아니었지만 격리 된 범위가있는 경우 격리 범위 바인딩을 사용할 수 있습니다. 이모, 방송이 좀 지저분 해요.
Canttouchit

2
템플릿이 아닌 부모의 컨트롤러 에서 자식 컨트롤러의 기능에 액세스해야하는 경우이 예제가 가능하지 않다고 생각합니다 . 이 예제 $scope.obj.get()는 유효한 함수가 될 때까지 폴링을 계속한다고 가정하는 템플릿의 양방향 바인딩 때문에 작동 합니다.
danyim

11

자녀가 초기화 할 때 부모에 자녀의 기능을 등록합니다. 템플릿에서 명확성을 위해 "as"표기법을 사용했습니다.

주형

<div ng-controller="ParentCntl as p">
  <div ng-controller="ChildCntl as c" ng-init="p.init(c.get)"></div>
</div>

컨트롤러

...
function ParentCntl() {
  var p = this;
  p.init = function(fnToRegister) {
    p.childGet = fnToRegister;
  };
 // call p.childGet when you want
}

function ChildCntl() {
  var c = this;
  c.get = function() {
    return "LOL";    
  };
}

"하지만", 당신은 "ng-init 이 방법으로 사용하면 안된다 !"라고 말합니다. 네,하지만

  1. 그 문서는 이유를 설명하지 않습니다.
  2. 문서 작성자가 모든 가능한 사용 사례를 고려했다고 생각하지 않습니다.

나는 이것이 그것을 위해 좋은 사용이라고 말한다. 저를 비하하고 싶다면 이유를 적어주세요! :)

이 접근 방식은 구성 요소를 더 모듈 식으로 유지하기 때문에 좋아합니다. 유일한 바인딩은 템플릿에 있으며

  • 자식 컨트롤러는 기능을 추가 할 개체에 대해 알 필요가 없습니다 (@canttouchit의 답변에서와 같이).
  • 부모 컨트롤은 get 함수가있는 다른 자식 컨트롤과 함께 사용할 수 있습니다.
  • 브로드 캐스팅이 필요하지 않습니다. 이벤트 네임 스페이스를 엄격하게 제어하지 않는 한 큰 앱에서는 매우 추하게됩니다.

이 접근 방식은 지시문을 사용한 모듈화에 대한 Tero의 아이디어에 더 가깝게 접근 합니다 (그의 모듈화 된 예제에서contestants 템플릿에서 부모에서 "자식"지시문으로 전달됨).

실제로 또 다른 해결책은를 ChildCntl지시문으로 구현하는 것을 고려 하고 &바인딩을 사용 하여 init메서드 를 등록하는 것입니다.


1
나는 이것이 오래된 게시물이라는 것을 알고 있지만 이것은 자녀가 파괴 된 후에도 부모가 자녀에 대한 참조를 유지할 수 있기 때문에 나쁜 생각처럼 보입니다.
Amy Blankenship

이것은 방송 이벤트보다 훨씬 더 깨끗한 솔루션입니다. 완벽하지는 않지만 더 좋습니다. 정리가 실제로 문제이지만.
mcv

-1

자식 개체를 만들 수 있습니다.

var app = angular.module("myApp", []);


app.controller("ParentCntl", function($scope) {
    $scope.child= {};
    $scope.get = function(){
      return $scope.child.get(); // you can call it. it will return 'LOL'
    }
   // or  you can call it directly like $scope.child.get() once it loaded.
});

app.controller("ChildCntl", function($scope) {
    $scope.obj.get = function() {
            return "LOL";    
    };
});

여기서 아이는 get 메소드의 목적지를 증명하고 있습니다.

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