Could someone, please, show me what I need to do to render in a directive new elements stored in an array in a service. In the example below, an alert from the service shows that each new element is added to the elements array, but how to make the directive show these new elements on the page?
I tried to read everything about compile
function in a directive, but could not understand how to make my example work.
Here is a jsfiddle. All I need is to render new messages inside the directive after they are added to the message array in the service.
The Chat
service is injected into directive as a chat
variable, and in the directive template I want to repeat every message from the service:
'<ul>' +
'<li ng-repeat="message in chat.messages">' +
'<strong>{{message.name}}</strong> {{message.text}}' +
'</li>' +
'</ul>'
Sample code is on jsfiddle and below:
HTML:
<div ng-app="myApp">
<my-simple-chat title="AngularJS Chat"></my-simple-chat>
</div>
JavaScript:
angular.module('myApp', [])
.factory('Chat', function () {
var messages = [];
function sendMessage(name, text) {
messages.push(
{
name: name,
text: text
});
alert("Sending message from factory: " + name + ", " + text + " : " + messages.length);
};
return {
messages: messages,
sendMessage: sendMessage
};
})
.directive('mySimpleChat', ['Chat', function (chat) {
var tmpl = '<div><h2>{{title}}</h2>' +
'<input type="text" ng-model="name" placeholder="Type your name"/>' +
'<hr />' +
'<form ng-submit="sendMessage()">' +
'<input type="text" ng-model="text" required placeholder="Type a new message..."/>' +
'<input type="submit" id="submit" value="Send"/>' +
'</form>' +
'<ul>' +
'<li ng-repeat="message in chat.messages">' +
'<strong>{{message.name}}</strong> {{message.text}}' +
'</li>' +
'</ul>' +
'<div>';
return {
restrict: 'E',
replace: true,
scope: { title: '@title' },
template: tmpl,
controller: ['$scope', '$element', '$attrs', '$transclude',
function ($scope, $element, $attrs, $transclude) {
$scope.name = 'MyName';
$scope.text = '';
$scope.sendMessage = function () {
chat.sendMessage($scope.name, $scope.text);
$scope.text = '';
};
}],
};
}]);
You are using ngRepeat
on chat.messages
but never assigning chat
to be part of $scope
.
controller: ['$scope', '$element', '$attrs', '$transclude',
function ($scope, $element, $attrs, $transclude) {
$scope.name = 'MyName';
$scope.text = '';
$scope.chat = chat; //<--this so you can use ngRepeat
$scope.sendMessage = function () {
chat.sendMessage($scope.name, $scope.text);
$scope.text = '';
};
}],
Looks like writing a question on SO is 90% way to its answer... All I needed to do was to add a link function to the directive:
link: function ($scope, element, attributes) {
$scope.messages = chat.messages;
}
and remove chat.
from ng.repeat
:
'<ul>' +
'<li ng-repeat="message in messages">' +
'<strong>{{message.name}}</strong> {{message.text}}' +
'</li>' +
'</ul>'
I am not sure that this is the right way to do the task, but it just works. In docs I have read that I have to use compile
function if I use ng-repeat
in a template, so I am still confused somewhat.
An updated jsfiddle.
You can create a bridge like this:
<li ng-repeat="message in messages()">
$scope.messages = function () {
return chat.messages;
}