it-swarm.com.ru

Как ввести контроллер в другой контроллер в AngularJS

Я новичок в 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

Должен ли я даже пытаться использовать контроллер внутри другого контроллера, или я должен сделать это сервисом?

94
Scottie

Если вы намерены завладеть уже созданным экземпляром контроллера другого компонента, и если вы следуете подходу, основанному на компонентах/директивах, вы всегда можете 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, если она не найдена.

^ - Найдите нужный контроллер, выполнив поиск элемента и его родителей. Скинь ошибку, если не нашел.

^^ - Найдите нужный контроллер, выполнив поиск родителей элемента. Скинь ошибку, если не нашел.

? ^ - Попытка найти требуемый контроллер путем поиска элемента и его родителей или передачи нулевого значения по ссылке fn, если она не найдена.

? ^^ - Попытка найти требуемый контроллер путем поиска родителей элемента или передачи нулевого значения по ссылке fn, если она не найдена.



Старый ответ:

Вам нужно внедрить службу $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 - это ваша модель представления, а во втором случае это сам экземпляр контроллера.

128
PSL

Я хотел бы предложить вопрос, который вы должны задать, как внедрить сервисы в контроллеры. Толстые сервисы с тонкими контроллерами - хорошее эмпирическое правило, иначе говоря, просто используйте контроллеры, чтобы склеить ваш сервис/фабрику (с бизнес-логикой) в ваши представления.

Контроллеры собирают мусор при изменении маршрута, поэтому, например, если вы используете контроллеры для хранения бизнес-логики, представляющей значение, вы потеряете состояние на двух страницах, если пользователь приложения нажмет кнопку браузера назад.

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();
}]);

Вот рабочий демонстрация фабрики введена в два контроллера

Кроме того, я бы предложил иметь читать этот учебник по услугам/фабрики.

33
cheekybastard

Нет необходимости импортировать/вводить ваш контроллер в JS. Вы можете просто вставить свой контроллер/вложенный контроллер через ваш HTML. Это сработало для меня. Подобно :

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