Передача данных между контроллерами в Angular JS?
У меня есть базовый контроллер, который отображает мои продукты,
App.controller('ProductCtrl',function($scope,$productFactory){
$productFactory.get().success(function(data){
$scope.products = data;
});
});
На мой взгляд, я показываю эти продукты в списке
<ul>
<li ng-repeat="product as products">
{{product.name}}
</li>
</ul
То, что я пытаюсь сделать, - это когда кто-то нажимает на имя продукта, у меня есть другое представление с именем cart где этот продукт добавлен.
<ul class="cart">
<li>
//click one added here
</li>
<li>
//click two added here
</li>
</ul>
Итак, я сомневаюсь, как передать эти продукты с первого контроллера на второй? Я предположил, что тележка также должна быть контроллером.
Я обрабатываю событие click с помощью директивы. Также я чувствую, что должен использовать сервис для достижения вышеуказанных функций, просто не могу понять, как это сделать? потому что корзина будет предопределено, количество добавленных продуктов может составлять 5/10 в зависимости от того, какой пользователь страницы. Поэтому я хотел бы сохранить этот общий.
Обновление:
Я создал службу для трансляции, а во втором контроллере я ее получил. Теперь вопрос в том, как я могу обновить dom? Поскольку мой список для удаления продукта довольно жестко запрограммирован.
Ответы
Ответ 1
Из описания кажется, что вы должны использовать услугу. Зайдите в http://egghead.io/lessons/angularjs-sharing-data-between-controllers и услугу AngularJS, передающую данные между контроллерами, чтобы увидеть некоторые примеры.
Вы можете определить свой сервис продукта как таковой:
app.service('productService', function() {
var productList = [];
var addProduct = function(newObj) {
productList.push(newObj);
};
var getProducts = function(){
return productList;
};
return {
addProduct: addProduct,
getProducts: getProducts
};
});
Зависимость внедряет службу в оба контроллера.
В вашем ProductController
определите некоторое действие, которое добавляет выделенный объект в массив:
app.controller('ProductController', function($scope, productService) {
$scope.callToAddToProductList = function(currObj){
productService.addProduct(currObj);
};
});
В своем CartController
получите продукты из службы:
app.controller('CartController', function($scope, productService) {
$scope.products = productService.getProducts();
});
Ответ 2
как передать эти продукты с первого контроллера на второй?
В щелчке вы можете вызвать метод, который вызывает трансляцию:
$rootScope.$broadcast('SOME_TAG', 'your value');
а второй контроллер будет прослушивать этот тег, например:
$scope.$on('SOME_TAG', function(response) {
// ....
})
Поскольку мы не можем вводить $scope в сервисы, нет ничего похожего на Singleton $scope.
Но мы можем ввести $rootScope
. Поэтому, если вы сохраняете значение в Сервисе, вы можете запустить $rootScope.$broadcast('SOME_TAG', 'your value');
в теле службы. (См. Описание @Charx об услугах)
app.service('productService', function($rootScope) {/*....*/}
Пожалуйста, проверьте хорошую статью о $broadcast, $emit p >
Ответ 3
Решение без создания Сервиса с использованием $rootScope:
Чтобы совместно использовать свойства в приложениях Controllers, вы можете использовать Angular $rootScope. Это еще один вариант для обмена данными, поэтому, чтобы люди знали об этом.
Предпочтительным способом обмена некоторыми функциями в контроллерах является "Сервис", чтобы читать или изменять глобальную собственность, вы можете использовать $anchcope.
var app = angular.module('mymodule',[]);
app.controller('Ctrl1', ['$scope','$rootScope',
function($scope, $rootScope) {
$rootScope.showBanner = true;
}]);
app.controller('Ctrl2', ['$scope','$rootScope',
function($scope, $rootScope) {
$rootScope.showBanner = false;
}]);
Использование $rootScope в шаблоне (свойства Access с $root):
<div ng-controller="Ctrl1">
<div class="banner" ng-show="$root.showBanner"> </div>
</div>
Ответ 4
Вы можете сделать это двумя способами.
-
Используя $rootscope
, но я не рекомендую это. $rootscope
- самая верхняя область видимости. Приложение может иметь только один $rootscope
, который будет
распределенных между всеми компонентами приложения. Следовательно, он действует как
глобальная переменная.
-
Использование сервисов. Вы можете сделать это, разделив службу между двумя контроллерами. Код для обслуживания может выглядеть следующим образом:
app.service('shareDataService', function() {
var myList = [];
var addList = function(newObj) {
myList.push(newObj);
}
var getList = function(){
return myList;
}
return {
addList: addList,
getList: getList
};
});
Вы можете увидеть мою скрипку здесь.
Ответ 5
Еще более простой способ совместного использования данных между контроллерами - использование вложенных структур данных. Вместо, например,
$scope.customer = {};
мы можем использовать
$scope.data = { customer: {} };
Свойство data
будет унаследовано от родительской области, поэтому мы можем перезаписать его поля, сохраняя доступ с других контроллеров.
Ответ 6
angular.module('testAppControllers', [])
.controller('ctrlOne', function ($scope) {
$scope.$broadcast('test');
})
.controller('ctrlTwo', function ($scope) {
$scope.$on('test', function() {
});
});
Ответ 7
Я видел ответы здесь, и он отвечает на вопрос о совместном использовании данных между контроллерами, но что мне делать, если я хочу, чтобы один контроллер сообщал другому о том, что данные были изменены (без использования широковещательной передачи)? ЛЕГКО! Просто используя знаменитый шаблон посетителя:
myApp.service('myService', function() {
var visitors = [];
var registerVisitor = function (visitor) {
visitors.push(visitor);
}
var notifyAll = function() {
for (var index = 0; index < visitors.length; ++index)
visitors[index].visit();
}
var myData = ["some", "list", "of", "data"];
var setData = function (newData) {
myData = newData;
notifyAll();
}
var getData = function () {
return myData;
}
return {
registerVisitor: registerVisitor,
setData: setData,
getData: getData
};
}
myApp.controller('firstController', ['$scope', 'myService',
function firstController($scope, myService) {
var setData = function (data) {
myService.setData(data);
}
}
]);
myApp.controller('secondController', ['$scope', 'myService',
function secondController($scope, myService) {
myService.registerVisitor(this);
this.visit = function () {
$scope.data = myService.getData();
}
$scope.data = myService.getData();
}
]);
Таким простым способом один контроллер может обновить другой контроллер, чтобы некоторые данные были обновлены.
Ответ 8
мы можем хранить данные в сеансе и использовать его в любом месте вне программы.
$window.sessionStorage.setItem("Mydata",data);
Другое место
$scope.data = $window.sessionStorage.getItem("Mydata");
Ответ 9
Я создал factory, который управляет разделяемой областью между шаблоном маршрута маршрута, поэтому вы можете поддерживать общие данные только тогда, когда пользователи перемещаются по тому же пути родительского пути.
.controller('CadastroController', ['$scope', 'RouteSharedScope',
function($scope, routeSharedScope) {
var customerScope = routeSharedScope.scopeFor('/Customer');
//var indexScope = routeSharedScope.scopeFor('/');
}
])
Итак, если пользователь переходит на другой маршрут маршрута, например '/Support', общие данные для пути '/Customer' будут автоматически уничтожены. Но если вместо этого пользователь переходит к "дочерним" путям, например "/Клиент/1" или "Клиент/список", область не будет уничтожена.
Здесь вы можете увидеть образец: http://plnkr.co/edit/OL8of9
Ответ 10
Сделайте factory в своем модуле и добавьте ссылку на контроллер factory и используйте его переменные в контроллере и теперь получите значение данных в другом контроллере, добавив ссылку, где бы вы ни хотели.
Ответ 11
Я не знаю, поможет ли это кому-либо, но на основании ответа Charx (спасибо!) я создал простой сервис кеша. Не стесняйтесь использовать, ремикшировать и делиться:
angular.service('cache', function() {
var _cache, _store, _get, _set, _clear;
_cache = {};
_store = function(data) {
angular.merge(_cache, data);
};
_set = function(data) {
_cache = angular.extend({}, data);
};
_get = function(key) {
if(key == null) {
return _cache;
} else {
return _cache[key];
}
};
_clear = function() {
_cache = {};
};
return {
get: _get,
set: _set,
store: _store,
clear: _clear
};
});
Ответ 12
Один способ использования службы angular:
var app = angular.module("home", []);
app.controller('one', function($scope, ser1){
$scope.inputText = ser1;
});
app.controller('two',function($scope, ser1){
$scope.inputTextTwo = ser1;
});
app.factory('ser1', function(){
return {o: ''};
});
<div ng-app='home'>
<div ng-controller='one'>
Type in text:
<input type='text' ng-model="inputText.o"/>
</div>
<br />
<div ng-controller='two'>
Type in text:
<input type='text' ng-model="inputTextTwo.o"/>
</div>
</div>
https://jsfiddle.net/1w64222q/
Ответ 13
FYI
Объект $scope имеет $emit, $broadcast, $on
А ТАКЖЕ
Объект $rootScope имеет одинаковые $emit, $broadcast, $on
Подробнее о шаблоне публикации/подписаться в angular здесь
Ответ 14
Есть три способа сделать это,
a) с помощью службы
b) Использование зависимых отношений между родителями и дочерними элементами между областями контроллера.
c) В Angular 2.0 "Ключевое слово" "будет передавать данные с одного контроллера на другой.
Для получения дополнительной информации см. пример:
http://www.learnit.net.in/2016/03/angular-js.html
Ответ 15
Чтобы улучшить решение, предложенное @Maxim, используя $broadcast, отправить данные не меняйте
$rootScope.$broadcast('SOME_TAG', 'my variable');
но для прослушивания данных
$scope.$on('SOME_TAG', function(event, args) {
console.log("My variable is", args);// args is value of your variable
})
Ответ 16
var custApp = angular.module("custApp", [])
.controller('FirstController', FirstController)
.controller('SecondController',SecondController)
.service('sharedData', SharedData);
FirstController.$inject = ['sharedData'];
function FirstController(sharedData) {
this.data = sharedData.data;
}
SecondController.$inject['sharedData'];
function SecondController(sharedData) {
this.data = sharedData.data;
}
function SharedData() {
this.data = {
value: 'default Value'
}
}
Первый контроллер
<div ng-controller="FirstController as vm">
<input type=text ng-model="vm.data.value" />
</div>
Второй контроллер
<div ng-controller="SecondController as vm">
Second Controller<br>
{{vm.data.value}}
</div>
Ответ 17
1
using $localStorage
app.controller('ProductController', function($scope, $localStorage) {
$scope.setSelectedProduct = function(selectedObj){
$localStorage.selectedObj= selectedObj;
};
});
app.controller('CartController', function($scope,$localStorage) {
$scope.selectedProducts = $localStorage.selectedObj;
$localStorage.$reset();//to remove
});
2
При щелчке вы можете вызвать метод, который вызывает широковещательную передачу:
$rootScope.$broadcast('SOME_TAG', 'your value');
and the second controller will listen on this tag like:
$scope.$on('SOME_TAG', function(response) {
// ....
})
3
using $rootScope:
4
window.sessionStorage.setItem("Mydata",data);
$scope.data = $window.sessionStorage.getItem("Mydata");
5
Один способ использования службы angular:
var app = angular.module("home", []);
app.controller('one', function($scope, ser1){
$scope.inputText = ser1;
});
app.controller('two',function($scope, ser1){
$scope.inputTextTwo = ser1;
});
app.factory('ser1', function(){
return {o: ''};
});
Ответ 18
Я думаю, что
лучший способ
- использовать $localStorage. (Работает постоянно)
app.controller('ProductController', function($scope, $localStorage) {
$scope.setSelectedProduct = function(selectedObj){
$localStorage.selectedObj= selectedObj;
};
});
Ваш cardController будет
app.controller('CartController', function($scope,$localStorage) {
$scope.selectedProducts = $localStorage.selectedObj;
$localStorage.$reset();//to remove
});
Вы также можете добавить
if($localStorage.selectedObj){
$scope.selectedProducts = $localStorage.selectedObj;
}else{
//redirect to select product using $location.url('/select-product')
}