angularjsdomangularjs-directiveangularjs-scopeangularjs-compile

Why isn't my dynamically created element not showing up?


OK So I created a chat widget that isn't hardcoded instead it it is created by a service for example:

$chatWidget.setParent(parent).setUser(user).setMessages(messages).build();

Here is the build function of the $chatWidget service:

var build = function () {
        if (parentElement && myUser && myMessages) {
            parentElement.append('<re-chat></re-chat>');
        }
    }

Here is a simplified version of the chat directive:

    angular
    .module('app')
    .directive('reChat', function ($chatWidget) {
        return {
            restrict: 'E',
            replace: true,
            template: 

    '<div id="chat-widget-container"><div id="chat-widget-header">reUser.name</div>'+
    '<div id="chat-widget-body"<div ng-repeat="message in reMessages"><div>' +
    '<p> {{message.body}} </p></div></div></div>' +
      '<textarea ng-model="messageToSend" id="message-to-send" placeholder ="Type your message" rows="3"></textarea>' +
      '<button class="btn btn-default">Send</button></div>',
            scope: {
                reMessages: '=',
                reParent: '<',
                reUser: '<'
            },
            link: function (scope, element, attrs) {    
            scope.reUser = $chatWidget.getMyUser();
            scope.reMessages = $chatWidget.getMyMessages();
            scope.reParent = $chatWidget.getParent();
        };
    });

HERE IS THE PROBLEM

My re-chat directive appears in the DOM structure but its inner html is completely empty.

I've tried several alternatives including removing the template and doing this:

var html = '[TEMPLATE HERE]' 
element.html(html);
$compile(element.contents())(scope);

or:

var html = '[TEMPLATE HERE]';
element.replaceWith(html);

Both to no avail. So, How can I get my directive's html to show up???

EDIT

The widget appears fine if I hard code it like the following:

<re-chat re-messages="messages" re-my-user="user"></re-chat>

But this is not the behavior I want. I want the directive to be added dynamically.


Solution

  • Try changing your directive to use shared scope and get rid of the link function.

    Then create a new child scope in your service build() method. Attach data for the directive onto that new child scope. Then compile the new directive with the child scope and attach it to DOM.

    var build = function () {
        if (parentElement && myUser && myMessages) {
            var childScope = scope.$new(); //pass true here if you want to
                                           //inherit parent scope properties.
            childScope.reMessages = myMessages;
            parentElement.append($compile('<re-chat></re-chat>')(childScope));
        }
    }