0

What I am trying to do is after clicking on a buddy in the buddy list, load a chat dialog template HTML file without disturbing other elements in current DOM just like chatting in facebook.

My problem is that after loading the html template file the scope variables such as {{contact.jid}} are not properly rendered, and the controller for the dialog is not even called.

How can I force a rerender or a call on the controller so that those variables are properly renderred? Or should I not use the jQuery.load function to do this? I can't figure out any other way.

Thank you.

Code of the controllers:

// Controller for the chat dialog
ctrl.controller('ChatCtrl',function($scope){
    $scope.test = "Test"
});

// Controller for the buddy list
// $scope.toggleDialog is called when a buddy is clicked
ctrl.controller('ContactCtrl',function($scope){
    $scope.contacts = window.contactList;
    $scope.toggleDialog = function(to){
        $.("#chatarea").load("chatdialog.html")
    };
});

The controller function of chat dialog is not called after loading chatdialog.html which has an attribute of ng-controller, so the {{test}} variable is not set.

chiu
  • 3
  • 1
  • 3
  • Please share the code that you've tried to load the external markup through. There are a few things that come to mind, but seeing the code and what you've tried will help. – Brocco Apr 07 '14 at 16:55
  • I've updated the question with my code. – chiu Apr 07 '14 at 17:05

3 Answers3

0

You are loading the external HTML via jQuery and Angular has no way of knowing how to use it. There are two ways to solve this issue:

  1. use ngInclude to load the template from the server, angular will load it from the server and compile it for you to use.
  2. continue to use jQuery load the HTML from the server and use the $compile service to teach angular how to use it

I would highly suggest using method #1 to load your external template.

Brocco
  • 62,737
  • 12
  • 70
  • 76
  • But this template should be ng-included only after the user clicked on a buddy. And I tried to dynamically write "ng-include" into DOM after the click but it does not work. – chiu Apr 07 '14 at 17:12
  • It will be loaded later if you don't set the URL until you want to load it. In the example I linked to for ngInclude, open up the browser dev tools, and watch the network traffic. template2.html is not gotten from the server until it is needed. so
    and in ctrl... $scope.loadTemplate = ''; then when needed: $scope.loadTemplate='chatdialog.html';
    – Brocco Apr 07 '14 at 17:18
0

You need to wrap your content that will be compiled inside a directive.

This directive receives the variables and the HTML that will be compiled. You can wrap this directive in the element that you like:

http://plnkr.co/edit/RYVCrlDmgVXT3LszQ9vn?p=preview

For example, given the following html and variables:

// In the controller
$scope.controllerHtml = '<span>{{variables.myVariable}}</span>';
$scope.controllerVariables = {myVariable: 'hello world'};

<!--In the HTML-->
<div compile-me html-to-bind="controllerHtml" variables="controllerVariables"></div>

You will get the following:

<div>
    <span>hello world</span>
</div>
GonchuB
  • 705
  • 5
  • 8
  • Even though this is not the most angularjs-ish solution but I believe this is what I want, thank you. – chiu Apr 07 '14 at 17:44
  • I don't know which one is the most angularjs-ish solution, but this allows for object mapping and/or specific validations to be done before compilation. But yes, maybe there's a more elegant and extensive way to do it. – GonchuB Apr 07 '14 at 18:00
0

I suppose the:

$.("#chatarea").load("chatdialog.html")

is the jQuery .load, or something similar. I would get the template via ngInclude, checking if test is setted or not; html:

<div id="chatarea" ng-if="test">
  <div ng-include="'chatdialog.html'"/>
</div>

controller:

ctrl.controller('ContactCtrl',function($scope){
    $scope.contacts = window.contactList;
    $scope.test = '';
    var callbackFunction = function(data) {
      $scope.test = data.test;
    };
    $scope.toggleDialog = function(to){
      AjaxRequestToGetBuddyInfoAndMessages(to, callbackFunction);
    };
});

Obviously test will be a more complex object, so the ngIf test will be different (and you will need to take into account the fact that:

$scope.test = data.test

if they are objects, they will lose the reference and have an unwanted behaviour).

Polmonite
  • 933
  • 6
  • 13