AngularJS의 다른 컨트롤러에 컨트롤러를 어떻게 삽입합니까?


97

저는 Angular를 처음 사용하고 작업 방법을 알아 내려고 노력하고 있습니다.

AngularJS를 사용하여 다른 컨트롤러에서 사용할 컨트롤러를 어떻게 삽입 할 수 있습니까?

다음 스 니펫이 있습니다.

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

app.controller('TestCtrl1', ['$scope', function ($scope) {
    $scope.myMethod = function () {
        console.log("TestCtrl1 - myMethod");
    }
}]);

app.controller('TestCtrl2', ['$scope', 'TestCtrl1', function ($scope, TestCtrl1) {
    TestCtrl1.myMethod();
}]);

이것을 실행하면 오류가 발생합니다.

Error: [$injector:unpr] Unknown provider: TestCtrl1Provider <- TestCtrl1
http://errors.angularjs.org/1.2.21/$injector/unpr?p0=TestCtrl1Provider%20%3C-%20TestCtrl1

다른 컨트롤러 내부에서 컨트롤러를 사용하려고해야합니까, 아니면 서비스로 만들어야합니까?


2
컨트롤러를 서로 삽입 할 수 없습니다. 예, TestCtrl1대신 서비스로 변경해야 합니다.
Sly_cardinal

정확히, 서비스 사용
Miguel Mota

3
뷰에 바인딩하는 컨트롤러의 속성을 업데이트해야한다면 어떨까요? 이 속성은 다른 컨트롤러에서 발생하는 이벤트의 영향을받습니다.
Ankit Tanna

답변:


129

다른 구성 요소의 이미 인스턴스화 된 컨트롤러를 확보하려는 의도이고 구성 요소 / 지시문 기반 접근 방식을 따르는 경우 항상 require특정 계층을 따르는 다른 구성 요소의 컨트롤러 (구성 요소 인스턴스) 를 사용할 수 있습니다 .

예를 들면 :

//some container component that provides a wizard and transcludes the page components displayed in a wizard
myModule.component('wizardContainer', {
  ...,
  controller : function WizardController() {
    this.disableNext = function() { 
      //disable next step... some implementation to disable the next button hosted by the wizard
    }
  },
  ...
});

//some child component
myModule.component('onboardingStep', {
 ...,
 controller : function OnboadingStepController(){

    this.$onInit = function() {
      //.... you can access this.container.disableNext() function
    }

    this.onChange = function(val) {
      //..say some value has been changed and it is not valid i do not want wizard to enable next button so i call container's disable method i.e
      if(notIsValid(val)){
        this.container.disableNext();
      }
    }
 },
 ...,
 require : {
    container: '^^wizardContainer' //Require a wizard component's controller which exist in its parent hierarchy.
 },
 ...
});

이제 위 구성 요소의 사용법은 다음과 같습니다.

<wizard-container ....>
<!--some stuff-->
...
<!-- some where there is this page that displays initial step via child component -->

<on-boarding-step ...>
 <!--- some stuff-->
</on-boarding-step>
...
<!--some stuff-->
</wizard-container>

당신이 설정할 수있는 여러 가지 방법이 있습니다 필요는 .

(접두사 없음)-현재 요소에서 필요한 컨트롤러를 찾습니다. 찾을 수없는 경우 오류가 발생합니다.

? -필요한 컨트롤러를 찾거나 찾을 수없는 경우 링크 fn에 null을 전달합니다.

^-요소와 상위 요소를 검색하여 필요한 컨트롤러를 찾습니다. 찾을 수없는 경우 오류가 발생합니다.

^^-요소의 부모를 검색하여 필요한 컨트롤러를 찾습니다. 찾을 수없는 경우 오류가 발생합니다.

? ^-요소와 부모를 검색하여 필요한 컨트롤러를 찾으려고 시도하거나 찾을 수없는 경우 링크 fn에 null을 전달합니다.

? ^^-요소의 부모를 검색하여 필요한 컨트롤러를 찾거나 찾을 수없는 경우 링크 fn에 null을 전달합니다.



이전 답변 :

$controller다른 컨트롤러 내에서 컨트롤러를 인스턴스화 하려면 서비스 를 삽입해야합니다 . 그러나 이로 인해 일부 디자인 문제가 발생할 수 있습니다. 언제든지 단일 책임을 따르는 재사용 가능한 서비스를 만들고 필요에 따라 컨트롤러에 삽입 할 수 있습니다.

예:

app.controller('TestCtrl2', ['$scope', '$controller', function ($scope, $controller) {
   var testCtrl1ViewModel = $scope.$new(); //You need to supply a scope while instantiating.
   //Provide the scope, you can also do $scope.$new(true) in order to create an isolated scope.
   //In this case it is the child scope of this scope.
   $controller('TestCtrl1',{$scope : testCtrl1ViewModel });
   testCtrl1ViewModel.myMethod(); //And call the method on the newScope.
}]);

어떤 경우에도 컨트롤러 인스턴스가 아닌에 TestCtrl1.myMethod()메서드를 연결했기 때문에 호출 할 수 없습니다 $scope.

컨트롤러를 공유하는 경우 항상 다음을 수행하는 것이 좋습니다.

.controller('TestCtrl1', ['$log', function ($log) {
    this.myMethod = function () {
        $log.debug("TestCtrl1 - myMethod");
    }
}]);

소비하는 동안 다음을 수행하십시오.

.controller('TestCtrl2', ['$scope', '$controller', function ($scope, $controller) {
     var testCtrl1ViewModel = $controller('TestCtrl1');
     testCtrl1ViewModel.myMethod();
}]);

첫 번째 경우에는 실제로 $scope뷰 모델이고 두 번째 경우에는 컨트롤러 인스턴스 자체입니다.


4
그리고 그것은 컨트롤러가 제공하는 기능에 달려 있습니다. 컴포넌트간에 공유해야하는 뷰 모델처럼 만들고 있다면 괜찮습니다.하지만 서비스 제공 업체의 기능에 더 가깝다면 저는 서비스를 만드는 것입니다. .
PSL

해야 var testCtrl1ViewModel = $scope.$new();var testCtrl1ViewModel = $rootScope.$new();? 참조 : docs.angularjs.org/guide/controller @PSL
leonsPAPA 2015

위의 예에서는 지시어 컨트롤러의 컨테이너에 액세스하고 있지만이 작업을 수행 할 수 없습니다. 지시문 자체의 링크 함수에있는 네 번째 매개 변수를 통해 필요한 컨트롤러에 액세스 할 수 있습니다. 그러나 위의 예와 같이 지시어 컨트롤러에 바인딩되어 있지 않습니다. 이 문제가있는 다른 사람이 있습니까?
Sammi

33

나는 당신이 물어야 할 질문은 컨트롤러에 서비스를 주입하는 방법입니다. 스키니 컨트롤러를 사용한 팻 서비스는 경험상 좋은 규칙입니다. 즉, 컨트롤러를 사용하여 서비스 / 팩토리 (비즈니스 로직 포함)를 뷰에 붙입니다.

컨트롤러는 경로 변경시 가비지 수집을받습니다. 예를 들어 컨트롤러를 사용하여 값을 렌더링하는 비즈니스 로직을 보유하는 경우 앱 사용자가 브라우저 뒤로 버튼을 클릭하면 두 페이지에서 상태가 손실됩니다.

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

app.factory('methodFactory', function () {
    return { myMethod: function () {
            console.log("methodFactory - myMethod");
    };
};

app.controller('TestCtrl1', ['$scope', 'methodFactory', function ($scope,methodFactory) {  //Comma was missing here.Now it is corrected.
    $scope.mymethod1 = methodFactory.myMethod();
}]);

app.controller('TestCtrl2', ['$scope', 'methodFactory', function ($scope, methodFactory) {
    $scope.mymethod2 = methodFactory.myMethod();
}]);

다음은 두 개의 컨트롤러에 주입 된 공장 의 작동 데모입니다.

또한 서비스 / 공장에 대한이 튜토리얼을 읽어 보는 것이 좋습니다 .


13

JS에서 컨트롤러를 가져 오거나 삽입 할 필요가 없습니다. HTML을 통해 컨트롤러 / 중첩 된 컨트롤러를 삽입 할 수 있습니다. 처럼 :

<div ng-controller="TestCtrl1">
    <div ng-controller="TestCtrl2">
      <!-- your code--> 
    </div> 
</div>

2
사실 ...하지만 모든 공통 요소를 서비스에 넣고 각 컨트롤러에 서비스를 주입하는 것이 더 좋습니다.
Neel

-1
<div ng-controller="TestCtrl1">
    <div ng-controller="TestCtrl2">
      <!-- your code--> 
    </div> 
</div>

이것은 TestCtrl2에 자체 지시문이있는 제 경우에 가장 잘 작동합니다.

var testCtrl2 = $controller('TestCtrl2')

이것은 scopeProvider 주입 오류라는 오류를 제공합니다.

   var testCtrl1ViewModel = $scope.$new();
   $controller('TestCtrl1',{$scope : testCtrl1ViewModel });
   testCtrl1ViewModel.myMethod(); 

'TestCtrl1'에 지시문이 있으면 실제로 작동하지 않습니다. 해당 지시문은 실제로 여기에서 만든 것과 다른 범위를 갖습니다. 'TestCtrl1'의 두 인스턴스로 끝납니다.


-1

최고의 솔루션 :-

angular.module("myapp").controller("frstCtrl",function($scope){$scope.name="Atul Singh";}).controller("secondCtrl",function($scope){angular.extend(this, $controller('frstCtrl', {$scope:$scope}));console.log($scope);})

// 여기에서 실행하지 않고 첫 번째 컨트롤러 호출을 받았습니다.


-1

다음 $rootScope과 같이 두 번째 컨트롤러에서 첫 번째 컨트롤러의 함수 / 메소드를 호출하는 데 사용할 수도 있습니다 .

.controller('ctrl1', function($rootScope, $scope) {
     $rootScope.methodOf2ndCtrl();
     //Your code here. 
})

.controller('ctrl2', function($rootScope, $scope) {
     $rootScope.methodOf2ndCtrl = function() {
     //Your code here. 
}
})

1
Downvote : 이것은 잘못된 코딩 일뿐입니다. 함수를 전역 적으로 만드는 것입니다. 이것이 코딩하려는 방법이라면 Angular를 완전히 삭제하는 것이 좋습니다 ... 대부분의 다른 답변에서 제안한 서비스를 사용하십시오.
HammerNL 2016 년

이것은 권장되지 않습니다. $ rootScope는 코드를 서투르게 만들고 장기적으로 문제를 유발합니다.
Harshit 바지

-2

코딩에 typescript를 사용하십시오. 객체 지향적이고 엄격하게 입력되고 코드를 유지하기 쉽기 때문입니다.

typecipt에 대한 자세한 내용은 여기를 클릭하십시오.

다음은 Typescript를 사용하여 두 컨트롤러간에 데이터를 공유하기 위해 만든 간단한 예제입니다.

module Demo {
//create only one module for single Applicaiton
angular.module('app', []);
//Create a searvie to share the data
export class CommonService {
    sharedData: any;
    constructor() {
        this.sharedData = "send this data to Controller";
    }
}
//add Service to module app
angular.module('app').service('CommonService', CommonService);

//Create One controller for one purpose
export class FirstController {
    dataInCtrl1: any;
    //Don't forget to inject service to access data from service
    static $inject = ['CommonService']
    constructor(private commonService: CommonService) { }
    public getDataFromService() {
        this.dataInCtrl1 = this.commonService.sharedData;
    }
}
//add controller to module app
angular.module('app').controller('FirstController', FirstController);
export class SecondController {
    dataInCtrl2: any;
    static $inject = ['CommonService']
    constructor(private commonService: CommonService) { }
    public getDataFromService() {
        this.dataInCtrl2 = this.commonService.sharedData;
    }
}
angular.module('app').controller('SecondController', SecondController);

}

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