Search code examples
javascriptangularjsangularjs-directiveangularjs-scope

Multiple directives in angular


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 chatboxes will have the same information, because they use the same scope passed on the $compile();

What can I do to fix this?


Solution

  • 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 = {}