У меня есть базовый контроллер, который отображает мои продукты,
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? Поскольку мой список для удаления продукта довольно жестко запрограммирован.
Из описания кажется, что вы должны использовать услугу. Зайдите в 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();
});
как передать эти продукты с первого контроллера на второй?
В щелчке вы можете вызвать метод, который вызывает трансляцию:
$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 >
Решение без создания Сервиса с использованием $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>
$rootScope
следует избегать в максимально возможной степени.
Вы можете сделать это двумя способами.
Используя $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
};
});
Вы можете увидеть мою скрипку здесь.
Еще более простой способ совместного использования данных между контроллерами - использование вложенных структур данных. Вместо, например,
$scope.customer = {};
мы можем использовать
$scope.data = { customer: {} };
Свойство data
будет унаследовано от родительской области, поэтому мы можем перезаписать его поля, сохраняя доступ с других контроллеров.
angular.module('testAppControllers', [])
.controller('ctrlOne', function ($scope) {
$scope.$broadcast('test');
})
.controller('ctrlTwo', function ($scope) {
$scope.$on('test', function() {
});
});
мы можем хранить данные в сеансе и использовать его в любом месте вне программы.
$window.sessionStorage.setItem("Mydata",data);
Другое место
$scope.data = $window.sessionStorage.getItem("Mydata");
Я видел ответы здесь, и он отвечает на вопрос о совместном использовании данных между контроллерами, но что мне делать, если я хочу, чтобы один контроллер сообщал другому о том, что данные были изменены (без использования широковещательной передачи)? ЛЕГКО! Просто используя знаменитый шаблон посетителя:
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();
}
]);
Таким простым способом один контроллер может обновить другой контроллер, чтобы некоторые данные были обновлены.
Я создал 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
Один способ использования службы 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>
Я не знаю, поможет ли это кому-либо, но на основании ответа 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
};
});
Сделайте factory в своем модуле и добавьте ссылку на контроллер factory и используйте его переменные в контроллере и теперь получите значение данных в другом контроллере, добавив ссылку, где бы вы ни хотели.
Чтобы улучшить решение, предложенное @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
})
Есть три способа сделать это,
a) с помощью службы
b) Использование зависимых отношений между родителями и дочерними элементами между областями контроллера.
c) В Angular 2.0 "Ключевое слово" "будет передавать данные с одного контроллера на другой.
Для получения дополнительной информации см. пример:
FYI Объект $scope имеет $emit, $broadcast, $on А ТАКЖЕ Объект $rootScope имеет одинаковые $emit, $broadcast, $on
Подробнее о шаблоне публикации/подписаться в angular здесь
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
});
При щелчке вы можете вызвать метод, который вызывает широковещательную передачу:
$rootScope.$broadcast('SOME_TAG', 'your value');
and the second controller will listen on this tag like:
$scope.$on('SOME_TAG', function(response) {
// ....
})
using $rootScope:
window.sessionStorage.setItem("Mydata",data);
$scope.data = $window.sessionStorage.getItem("Mydata");
Один способ использования службы 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: ''};
});
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>
Я думаю, что
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')
}