0

I'm trying to do my first attempts with angular.js and I have a problem with restoring the correct content of the website. Content of pages is received via AJAX (now from static data, latter from database). When I place a block with directive ng-repeat inside element with id="content", everything works OK. Result is:

ID: 1 Name: Apple ID: 2 Name: Microsoft

But if I put the element inside the content dynamically using javascript and AJAX, I can not display the correct data. Result is:

ID: {{firm.id}} Name: {{firm.name}}

I tried to use the setTimeout() for subsequent calling $apply(), but it did not help. I tried to find a solution on the web, but I could not find a similar example. Does anyone know where can be the problem? Thank you very much for your help.

Html code:

<div ng-app="myApp">
  <div id="main_controler" ng-controller="mainController">
    <button onclick="get_page('1')">Page one</button>
    <button onclick="get_page('2')">Page two</button><br /><br /><br />

    <div id="content">
      <div ng-repeat="firm in data.firms"  style="width:100%">
        ID: {{firm.id}} Name: {{firm.name}}
      </div>
    </div>
  </div> 
</div>

JavaScript code:

var app = angular.module('myApp', []);

app.controller('mainController', function($scope, $http) {

  $scope.get = function(a_number) {
    var p_url = 'ajax_fce.php?num=' + a_number;

    $http({
      method: 'JSON',
      url: p_url
    }).success(function(data, status) {
       $scope.data = data;
    }).error(function(data, status) {
      alert('Error');
    });
  }
  $scope.get(1);
});


get_template_1 = function() { 
  return '<div ng-repeat="firm in data.firms"  style="width:100%">'+
           'ID: {{firm.id}} Name: {{firm.name}}'+
         '</div> ';
}

get_template_2 = function() { 
  return '<div ng-repeat="person in data.persons"  style="width:100%">'+
           'Name: {{person.name}} Surname: {{person.surname}}'+
         '</div> ';
}

load_template = function(page_id) {
  var p_template =  '';

  if(page_id == 1) { p_template =  get_template_1(); }
  if(page_id == 2) { p_template =  get_template_2(); }

  return p_template;
}


get_page = function(page_id) {
  $('#content').html(load_template(page_id));
  angular.element(document.getElementById('main_controler')).scope().get(page_id);
  angular.element(document.getElementById('main_controler')).scope().$apply();
}

PHP code (AJAX):

$p_return =  ''; 
if ($_GET['num'] == '1') {
   $p_return = '   { "firms": [ { "id": "1", "name": "Apple" },
                    { "id": "2", "name": "Microsoft" } ]}'; }    
 else if ($_GET['num'] == '2') {
   $p_return = '   { "persons": [ { "name": "Steve", "surname": "Jobs" },
                    { "name": "Bill", "surname": "Gates" } ]}';
}
echo $p_return;
Gery
  • 3
  • 4
  • approach with your templates goes against using angular properly and there should not be any native `onclick` inline in your code. Need to spend more time with angular tutorials. Start with the one in docs site. A lot of your code should never need to be used in angular app – charlietfl Dec 15 '13 at 00:20

2 Answers2

2

It is because the get_page function don't compile the template. The easiest way to do this (for me) is: HTML code:

<div ng-app="myApp">
  <div id="main_controler" ng-controller="mainController">
    <button ng-click="get(1)">Page one</button>
    <button ng-click="get(2)">Page two</button><br /><br /><br />

    <div id="content">

      <div ng-show="number==1" ng-repeat="firm in data.firms"  style="width:100%">
        ID: {{firm.id}} Name: {{firm.name}}
      </div>
      <div ng-show="number==2" ng-repeat="person in data.persons"  style="width:100%">
           Name: {{person.name}} Surname: {{person.surname}}
      </div>
    </div>
  </div> 
</div>

The javascript code:

var app = angular.module('myApp', []);

app.controller('mainController', function($scope, $http) {
  $scope.number = 0;
  $scope.get = function(a_number) {
    $scope.number = a_number;
    var p_url = 'ajax_fce.php?num=' + a_number;

    $http({
      method: 'JSON',
      url: p_url
    }).success(function(data, status) {
       $scope.data = data;
    }).error(function(data, status) {
      alert('Error');
    });
  }
  $scope.get(1);
});
csbenjamin
  • 356
  • 2
  • 8
  • Plus plus. Changing `onClick` to `ng-click` definitely seems like a subtle difference to newcomers, but it's *vital* to use `ng-click`. It keeps all your code within the angular framework, so that you don't have to do manual `$apply` calls. – Hylianpuffball Dec 15 '13 at 02:52
  • Thank you very much. I used your code and everything works correctly. You helped me very much. Thanks again. – Gery Dec 15 '13 at 10:16
0

The first answer has a small disadvantage. Html code for the listing of companies and persons remained in the original html. The original intention was to insert it there dynamically. I finally found a solution at:

Compiling dynamic HTML strings from database

I implement it for my case. I only moved templates for html from javascript to server. Server provides html via Ajax now.

That's what I needed before now looks like this:

Html code:

<body ng-app="app">
  <h1>Compile dynamic HTML</h1>
  <div ng-controller="MyController">
    <button ng-click="get(1)">Page one</button>
    <button ng-click="get(2)">Page two</button><br /><br /><br />
  <!--      <textarea ng-model="html"></textarea>  -->
    <div dynamic="html"></div>
  </div>
</body>

Javascript code:

var app = angular.module('app', []);

app.directive('dynamic', function ($compile) {
  return {
    restrict: 'A',
    replace: true,
    link: function (scope, ele, attrs) {
      scope.$watch(attrs.dynamic, function(html) {
        ele.html(html);
        $compile(ele.contents())(scope);
      });
    }
  };
});

app.controller('MyController', function($scope, $http) {
  $scope.get = function(a_number) {

    var p_url = 'ajax_fce.php?num=' + a_number;
    $http({
      method: 'JSON',
      url: p_url
    }).success(function(data, status) {
       $scope.html = data.template;
       $scope.data = data.data;
    }).error(function(data, status) {
      alert('Error');
    });
  }
  $scope.get(1);
});

PHP code:

echo '{"template": "'.get_template($_GET['num']).'", '.
      '"data": '.(get_data($_GET['num'])).'}';  

function get_data($a_template) {
  if ($_GET['num'] == '1') {
    $p_result = '{ "firms": [ { "id": "1", "name": "Apple" },
                    { "id": "2", "name": "Microsoft" } ]}';
  } else if ($_GET['num'] == '2') {
    $p_result = '   { "persons": [ { "name": "Steve", "surname": "Jobs" },
                    { "name": "Bill", "surname": "Gates" } ]}';
  }
  return $p_result;
}

function get_template($a_template) {
  if ($_GET['num'] == '1') {
    $p_result = '<div ng-repeat=\"firm in data.firms\"  style=\"width:100%\"> ID: '.
                                              '{{firm.id}} Name: {{firm.name}}</div>';
  } else if ($_GET['num'] == '2') {
    $p_result =  '<div ng-repeat=\"person in data.persons\"  style=\"width:100%\"> Name: '.
                                 '{{person.name}} Surname: {{person.surname}}</div>';
  }
  return $p_result;
}

I answer to my own question, but I hope that this example can help someone and save him some time.

Community
  • 1
  • 1
Gery
  • 3
  • 4