I am trying to build a JavaScript chat system like Facebook and I use a directive to create the chatbox for every user, the chatbox
When I click on online users -- a new chatbox should be opened:
$(elm).on('click','[data-user-id]',function () {
chat.openChatBox( this.dataset.userId , scope ) ; // (chat) :service
}) ;
app.service('chat',['$http','$interval','$compile',function($http,$interval,$compile) {
this.openChatBox = function (id , scope ) {
if($("[data-chatbox-user-id="+id+"]").length === 0){
$http({
method:"POST",
url:"{{ url('users/getUserDataForChat') }}",
data:{
id:id,
}
}).success(function (r) {
var right = chatService.opened.length * 260 + 230 + "px" ;
angular.element('body').append($compile( '<div class="chatBox" name="'+r.name+'" style="right:'+ right +';" chatbox data-chatbox-user-id='+id+' ></div>' )(scope) );
}) ;
}
}
}]);
So, here is what actually happens. The click
event triggers the openChatBox()
function from the service. It searches to see if there is already a chatbox that exists for this user; if not, it will create one.
The problem is with this line of code:
angular.element('body').append($compile( '<div class="chatBox" name="'+r.name+'" style="right:'+ right +';" chatbox data-chatbox-user-id='+id+' ></div>' )(scope) );
I have to pass the scope, but I need to use the directive scope. This is the chatbox
directive :
app.directive("chatbox",[function () {
return {
restrice:'CAE',
scope:true,
template: function (element,attrs) {
return $("#templateChatBox").html() ;
},
link:function (scope,elm,args) {
},controller : ['$scope',function ($scope) {
$scope.textChanged = function (e) {
console.log($scope.name) ;
}
}]
}
}]) ;
So, if the custom directives in angularJS can each use their own scope, why should I pass it to $compile()
? It would be better if the directive could get every things from their controller(scope<-)
, and scope
.
My exact problem is this: the "chat" service open a new
chatbox
-> (passes the scope ) -> and then the chatbox
es will have the same information, because they use the same scope passed on the $compile();
What can I do to fix this?
The scope argument that you pass to the openChatBox
function is only used to bind the inserted element to an outer scope.
chat.openChatBox( this.dataset.userId , scope );
//... and later
angular.element('body').append($compile( '<div class="chatBox" name="'+r.name+'" style="right:'+ right +';" chatbox data-chatbox-user-id='+id+' ></div>' )(scope) );
$compile
produces the template function and then you execute it by passing the scope that the new element should be bound to. The story about that scope literally ends there.
The reason why your directive is sharing the outer scope is that you set scope = true
, which tells the directive to create a new scope which will prototypicaly inherit from its outer scope. (the one you passed to the template function).
If you need your directive to have a separate scope, create an isolated scope by setting scope = {}