Наследование контроллера с инъекцией

0

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

Вот что у меня есть: - 2 контроллера, которые на 80% похожи. У меня уже есть фабрика, которая используется для получения данных, которые будут отображаться. - Я использую обозначение controllerAs, с var vm = this - существует смесь варов и функций, которые будут использоваться в представлении и, следовательно, создаются внутри vm и некоторые другие внутренние вары и функции, которые не являются. - поэтому я попытался создать один родительский контроллер со всем этим, а затем использовать инъекцию, чтобы создать эти 2 контроллера, перезаписав только то, что мне нужно, но это не работает, как я ожидал, а также я не уверен, что это правильно делать

Вот упрощенная версия кода.

(function() {

    angular

    .controller('ParentController', ParentController)

    ParentController.$inject = [ '$scope', '$location' ];

    function ParentController($scope, $location) {

        var vm = this; // view model

        var URL = $location.url();      

        var isDataLoaded = false;

        vm.predicate = 'order';
        vm.reverse = false;

        vm.results;     

        vm.isDataReady = isDataReady;
        vm.setOrder = setOrder;

        function isDataReady() {
            return isDataLoaded;
        }

        function setOrder(p) {
            vm.reverse = (p === vm.predicate) ? !vm.reverse : false;
            vm.predicate = p;
        }

        $scope.$on('READ.FINISHED', function() {
            isDataLoaded = true;
        })
    }
})();

-

(function() {

    angular

    .controller('ChildController', ChildController)

    ChildController.$inject = ['$controller', '$scope', 'myFactory'];

    function ChildController($controller, $scope, myFactory) {

        $controller('ParentController', {$scope: $scope});

        var TEMPLATE = 'SCREEN';

        // ************** M A I N **************

        myFactory.getResults(URL, vm);
    }

})();

Сейчас я работаю так, как я ожидал.

Когда я добавляю ChildController с ParentController, действительно ли мне нужно вводить $ scope? Я на самом деле использую vm. Кроме того, мне нужно также ввести $ location? В этом примере, когда я выполняю свой код, я вынужден использовать var URL = $location.url(); снова в моем ChildController, я ожидал унаследовать значение от ParentController.

Так вот, я только получаю значения из $ scope, если я так работаю? как насчет vm? и что относительно этих vars/функций, объявленных вне vm, таких как var isDataLoaded? Я был бы признателен за понимание. Будет ли это правильным путем? Большое спасибо.

EDIT: Хорошо, я узнал, как использовать мой синтаксис ControllerAs с этим. Код в дочернем контроллере будет выглядеть так:

function ChildController($controller, $scope, myFactory) {

        $controller('ParentController as vm', {$scope: $scope});

        var vm = $scope.vm;

        var TEMPLATE = 'SCREEN';

        // ************** M A I N **************

        myFactory.getResults(URL, vm);
    }

Но мне все же нужно найти способ восстановить обычные var/functions внутри родительского контроллера. Есть идеи? Можно ли это сделать чисто?

Теги:
controller

1 ответ

0

Я рекомендую вам реализовать обычный механизм наследования javascript между двумя классами. В конструкторе ChildController вы создадите конструктор ParentController и передадите ему введенные параметры (без использования $controller service). Я создал простой пример (очень далеко от вашей логики, но рассматриваю его как patten). У меня есть два контроллера: ParentController и ChildController, которые унаследованы от первого. Я использовал только ChildController с $scope, $interval и настраиваемым сервисом с именем "myservice" (все они нужны только для примера). Вы можете видеть, что я использовал методы и поля из родительского и дочернего контроллеров. Логика моего приложения очень проста: вы можете добавлять новые элементы в коллекцию (с помощью ParentController) и удалять их (с помощью ChildController) с протоколированием.

В этом случае я рекомендую использовать ChildController как ctrl для привязки данных вместо $scope, потому что это больше в парадигме наследования строк (мы наследуем контроллеры (ctrl) не $scope).

PS Если вы собираетесь использовать наследование очень часто, я рекомендую вам использовать TypeScript - он дает очень простое и гибкое решение этой проблемы в стиле С#.

Controllers.js

function ParentController(myservice, $scope, $interval) {
  this.newOne={};
  this.lastacivity={};
  this.$interval = $interval;
  this.items = myservice();
}

ParentController.prototype.Log = function(item){
  var self = this;
  this.$interval(function(){
      console.log(item);
      self.lastacivity = item;
    }, 100, 1);
}
ParentController.prototype.AddNew = function (Name, Age) {
  var newitem = {
      name: this.newOne.Name,
      age: this.newOne.Age
    }
    this.items.push(newitem);
    this.Log(newitem);
}

function ChildController(myservice, $scope, $interval) {
    //Transfering myservice, $scope, $interval from ChildController to ParentController constructor,
    //also you can pass all what you want: $http, $location etc.
    ParentController.apply(this, [myservice, $scope, $interval]);
}        
ChildController.prototype = Object.create(ParentController.prototype)

//your ChildController own methods
ChildController.prototype.Remove = function (item) {
    this.items.splice(this.items.indexOf(item), 1);
    this.Log(item);
}

script.js

(function(angular) {
  'use strict';
angular.module('scopeExample', []).factory('myservice', function() {
  var items = [
          {name:"Mike",age:21},
          {name:"Kate",age:22},
          {name:"Tom",age:11}
        ];
  return function(){
      return items;
  }
}).controller('ChildController', ['myservice', '$scope', '$interval', ChildController]);
})(window.angular);

HTML

<body ng-app="scopeExample">
  <div ng-controller="ChildController as ctrl">
    <label>Name</label>
    <input type='text' ng-model='ctrl.newOne.Name'/>
    <label>Age</label>
    <input type='text' ng-model='ctrl.newOne.Age'/>
    <input type='button' value='add' ng-click='ctrl.AddNew()' ng-disabled="!(ctrl.newOne.Name && ctrl.newOne.Age)"/>
    <br>
    <br>
    <table>
      <thead>
        <tr>
          <th>Name</th>
          <th>Age</th>
          <th></th>
        </tr>
      </thead>
      <tbody>
        <tr ng-repeat="item in ctrl.items">
          <td>{{item.name}}</td>
          <td>{{item.age}}</td>
          <td>
            <input type='button' value='X' ng-click='ctrl.Remove(item)'/>
          </td>
        </tr>
      </tbody>
    </table>
    <p>{{ctrl.lastacivity | json}}</p>
</div>
</body>

Ещё вопросы

Сообщество Overcoder
Наверх
Меню