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.

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

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

3 ответа

Решение

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

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

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

ОБНОВЛЕНИЕ В случае, если вы хотите обеспечить некоторые общие / общие функциональные возможности между контроллерами, лучший способ - это создать, а затем inject отдельный сервис. Он держит код СУХОЙ.

Вот пример проекта (не созданный мной), который иллюстрирует, как использовать один контроллер с двумя представлениями: один для отображения списка элементов и один для редактирования или добавления одного элемента: 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.

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

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

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

Другие вопросы по тегам