Angular - использование одного контроллера для множества когерентных представлений по нескольким HTTP-запросам

У меня есть простой сценарий Angular JS. Я показываю список экспертов в одном представлении, и этот список содержит действия по редактированию эксперта, которые будут выполняться в другом представлении. Эти представления поступают с сервера и не находятся в одном файле. Они не загружаются вместе.

<!-- experts.html -->
<div ng-controller='expertController'>
    <!-- showing the list of experts here -->
</div>

И в другом файле на сервере у меня есть:

<!-- expert.html -->
<div ng-controller='expertController'>
    <!-- a form to edit/add an expert -->
</div>

И мой контроллер:

app.controller('expertController', function ($scope) {
    $scope.getExperts = function () {
        _.get('/expert/getexperts/', null, function (data) {
            $scope.$apply(function () {
                $scope.experts = data;
            });
        });
    };

    $scope.editExpert = function (index) {
        _.get('/expert/getexpert/', { id: $scope.experts[index].Id }, function (data) {
                $scope.$apply(function () {
                    $scope.expert = data;
                });
         });
    };
});

Однако в форме редактирования данные не будут отображаться. Я проверил области с помощью Batarang, но объект expert не будет показан.

Проблема заключается в том, что я использую один контроллер для двух (и, возможно, более двух) представлений. Однако, поскольку я прочитал некоторые другие вопросы о SO, кажется, что наилучшей практикой является наличие одного контроллера для HTML-представления.

Однако, я думаю, что более последовательный и последовательный, чтобы выполнить все операции CRUD с помощью expertController, наряду с другими действиями, связанными с expert. Я думаю, что немного уродливо иметь expertEditController для формы редактирования и expertListController для списка HTML.

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

Ответ 1

Конечно, вы можете использовать много views с тем же controller. Например: для редактирования и добавления новых элементов.

Но вы должны помнить, что каждый раз, когда изображение загружается, инициализируется контроллер и новый, новый $scope.

В вашем случае было бы лучше просто использовать два отдельных контроллера (один для experts и один для expert) и использовать - необязательно - некоторую службу для обмена данными между ними и, возможно, предоставить некоторый механизм кэширования.

UPDATE. Если вы хотите предоставить некоторые общие/общие функции между контроллерами, лучший способ - создать, а затем inject отдельную службу. Он сохраняет код DRY.

Ответ 2

Здесь пример проекта (не созданный мной), который иллюстрирует, как использовать один контроллер с двумя представлениями: один для отображения списка элементов и один для редактирования или добавления отдельного элемента: http://embed.plnkr.co/jAK31F/

Основной принцип, используемый в контроллере, - проверить, прошел ли идентификатор одного элемента и запустить применимую логику для этой ситуации:

controllers.controller('MainController', function( $scope, $location, $routeParams, ItemService)  {
  if ($routeParams.itemid) {
    // do stuff for single item
    if ($routeParams.itemid == 0) {
      // do stuff for adding item
    } else {
      // do stuff for editing item
    }
  } else {
    // do stuff for listing multiple items
  }
});

Различные виды настраиваются в таких маршрутах:

app.config(['$routeProvider', function ($routeProvider) {
        // routes
        $routeProvider.
        when('/', {
            templateUrl: 'item_list.html',
            controller: 'MainController'
        }).
        when('/:itemid', {
            templateUrl: 'item_single.html',
            controller: 'MainController'
        });
    }]);

Таким образом, URL-адрес, например baseurl/, откроет представление списка, а URL-адрес, например baseurl/1, откроет подробный вид элемента с идентификатором 1.

В связи с тем, что это лучшая практика или нет, в большинстве случаев я не думаю, что этот метод дает преимущество перед использованием двух контроллеров: один для списка и один для одного элемента. По моему опыту, контроллер для просмотра нескольких элементов имеет разные проблемы, чем один для редактирования одного элемента. Любая общая логика может быть помещена в службу, как предложено в более ранних ответах.

Ответ 3

Фактически, когда мы используем тот же контроллер для другого вида, он будет перезагружать этот контроллер всякий раз, когда будет загружен вид. В этот момент область потеряет данные. Чтобы избежать этого, я использовал $rootScope вместо $scope. Я не знаю, правильный или нет этот подход, но он работает.

$rootScope.expert вместо $scope.expert.