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.