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.