Угловая: Как передавать в эфир на фабрике?

68
9

У меня есть список элементов, и при каждом добавлении нового элемента мне нужно получить сообщение (добавив элемент!) В навигационную панель.

Функция addItem() (ng-click на кнопке Добавить элемент) находится в ItemFactory, и оттуда я, похоже, не могу ее транслировать.

<!doctype html>
<html>
<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
</head>

<body ng-app="MyApp" ng-controller="MainCtrl">
<div>{{ text }}

<nav class="navbar navbar-inverse" ng-controller="NavCtrl">
<div class="container">
<div class="navbar-header">
<a class="navbar-brand" href="#">List of items | {{ alertItemAdded }}</a>
</div>
<form class="navbar-form navbar-right" role="search">
<div class="form-group">
<input type="text" class="form-control" ng-model="newItem" placeholder="Add an item">
</div>
<button type="submit" class="btn btn-primary" ng-click="addItem(newItem)">Add Item</button>
</form>
</div>
</nav>

<div class="container" ng-controller="ContentCtrl">
<div class="row">
<div class="col-xs-12">
<form class="form-inline">
<div class="form-group">
<input type="text" class="form-control" ng-model="newItem" placeholder="Add an item">
</div>
<button type="submit" class="btn btn-primary" ng-click="addItem(newItem)">Add Item</button>
</form>
<br />
<br />
</div>
</div>

<div class="row">
<div class="col-xs-12">
<div ng-repeat="item in items">

<form class="form-inline">
<div class="form-group">
<div>{{ item }}</div>
</div>
<button type="button" class="btn btn-default btn-s" ng-click="removeItem($index)">Remove Item</button>
</form>

</div>
</div>
</div>
</div>
</div>
</body>
</html>

angular.module('MyApp',[]);

angular.module('MyApp').controller('MainCtrl', function($scope, ItemFactory){

$scope.text = "Text from the Main Controller";

$scope.addItem = function(newItem){
ItemFactory.addItem(newItem);
}

});

angular.module('MyApp').controller('NavCtrl', function($scope){

// $on
$scope.$on('itemAdded', function(event, data){
$scope.alertItemAdded = data;
});

});

angular.module('MyApp').controller('ContentCtrl', function($scope, ItemFactory){

$scope.items = ItemFactory.getItem();

$scope.removeItem = function($index){
ItemFactory.removeItem($index);
}

});

angular.module('MyApp').factory('ItemFactory', function(){

var items = [
'Item 1',
'Item 2',
'Item 3'
];

return {
getItem : function() {
return items;
},
addItem : function(item){
items.push(item);
// $broadcast
$scope.$broadcast('itemAdded', 'Item added!');
},
removeItem : function($index){
items.splice($index, 1);
}
};

});

спросил(а) 2015-05-20T17:28:00+03:00 5 лет, 1 месяц назад
1
Решение
54

Вы можете ввести $ rootScope на свой завод и использовать оттуда $ broadcast.

angular.module('MyApp').factory('ItemFactory', ["$rootScope", function($rootScope){

var items = [
'Item 1',
'Item 2',
'Item 3'
];

return {
getItem : function() {
return items;
},
addItem : function(item){
items.push(item);
// $broadcast
$rootScope.$broadcast('itemAdded', 'Item added!');
},
removeItem : function($index){
items.splice($index, 1);
}
};

}]);

ответил(а) 2015-05-20T17:30:00+03:00 5 лет, 1 месяц назад
54

Вот вам чистое решение.

Смотрите, как работает этот плункер

Позвольте мне объяснить, как все это работает.

Ваше сообщение выглядит так:

<span ng-if="alertItemAdded.recentAdd">Item added !</span>

Он будет отображаться только тогда, когда "alterITemAdded.recenAdd" истинно. Вы будете использовать это, чтобы сообщение исчезло, если вам нужно.

Теперь вы выглядите следующим образом:

angular.module('MyApp').service('ItemService', function(){

var service = {};

//I'll always wrap my data in a sub object.
service.notification = {};

service.notification.recentAdd=false;

service.items = {};

service.items.list = [
'Item 1',
'Item 2',
'Item 3'
];

service.items.addItem = function(item){
service.items.list.push(item);
service.notification.recentAdd=true;
console.log(service);
}

service.items.removeItem = function($index){
service.items.list.splice($index, 1);
}

return service;

});

Я использую сервис вместо фабрики. Но почти нет разницы, это просто вопрос вкуса.

Вот ваши контроллеры

angular.module('MyApp').controller('MainCtrl', function($scope, ItemService){

$scope.text = "Text from the Main Controller";

});

angular.module('MyApp').controller('NavCtrl', function($scope, ItemService){

//IMPORTANT POINT : I bind it the sub object. Not to the value. To access the value i'll use $scope.alterItemAdded.recentAdd
$scope.alertItemAdded = ItemService.notification;
//I don't have to redeclare the function. I just bind it to the service function.
$scope.addItem = ItemService.items.addItem;
});

angular.module('MyApp').controller('ContentCtrl', function($scope, ItemService){

$scope.items = ItemService.items.list;

$scope.addItem = ItemService.items.addItem;

$scope.removeItem = function($index){
ItemService.items.removeItem($index);
}

});

Важная точка:

Я всегда привязываю свои вары к субобъекту. Зачем? На самом деле, если я сделал $ scope.alertItemAdded = ItemService.notifications.recentAdd

Когда я делаю что-то подобное в моей службе

 service.notifications.recentAdd = true;

Он создаст новую переменную и добавит ссылку в service.notifications.recentAdd. $ Scope.alertItemAdded привязывался к предыдущей ссылке и не видел обновления.

Делая это:

$scope.alterItemAdded = ItemService.notification

И используя значение в предложении ng-if или что-то еще. Я препятствую перерыв ссылки. Если я сделаю это на службе

service.notification.recentAdd = true

Я создам новый var с новой ссылкой для "recentAdd", но я сохраняю ту же ссылку для "уведомления". Связывание в контроллере будет сохранено, и значение recentAdd будет обновлено в представлении.

Если у вас есть еще вопрос, не стесняйтесь спрашивать.

ответил(а) 2015-05-20T18:17:00+03:00 5 лет, 1 месяц назад
-4

Вы не вводили $ scope на завод, и на самом деле вы не можете использовать $ rootScope

ответил(а) 2015-05-20T17:32:00+03:00 5 лет, 1 месяц назад
-6

$broadcast сверху вниз, поэтому вы должны использовать $rootScope для выполнения $broadcast для всех элементов $scope под ним.

    Внедрить $rootScope на ваш завод

    $ rootScope. $ broadcast ('itemAdded,' Item added! ')

ответил(а) 2015-05-20T17:31:00+03:00 5 лет, 1 месяц назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема