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.