Search code examples
jqueryajaxpromisejsrendertemplating-engine

Updating rendered template with ajax


I have this code to render the template from data I get from my mysql db using ajax.

Code to get the data for template:

setInterval(function() {
function ajax(url) {
    return new Promise(function(resolve, reject) {
        var xhr = new XMLHttpRequest();
        xhr.onload = function() {
        resolve(this.responseText);
        };
        xhr.onerror = reject;
        xhr.open('GET', url);
        xhr.send();
    });
 }

ajax("http://localhost/tuntiseuranta/dbajax.php").then(function(result) {
    var personData = JSON.parse(result);
    var i = 0;
    $.each(personData, function (index, person) {

  //var statusid = Math.random()*statuses.length|0;
  var statusid = personData[i].status;
  var status = getStatus(statusid);
  console.log(status);
  var fullName = personData[i].firstname + " " + personData[i].lastname;
  // hashing needed so urls stay stable but don't publish employee names to adorable.io
  var hash = Math.abs((person + '4a_j.rvs4m9kttqgzh5uBtsw5kh%').hashCode()).toString(36)
  var person = {
    name: fullName,
    status: statusid,
    statusClass: status.class,
    statusLabel: status.label,
    hash: hash
  }
  if (status.verbose) {
    person.verbose = status.verbose[Math.random()*status.verbose.length|0];
  }
  var html = $.templates('#personTmpl').render(person);
  $('.js-persons').append(html);
  i++;
})

}).catch(function() {
    console.log("ajax error");
});
}, 5000);

Displaying the template in the webpage:

  <!-- template for one person -->
  <script id="personTmpl" type="text/x-jsrender">
    <div class="person person-{{:statusClass}}" data-toggle="modal" data-target="#personStatusModal" data-status-id="{{:status}}" data-person="{{:name}}">
      <div class="media">
        <div class="person__image pull-right">
          <img class="media-object" src="https://api.adorable.io/avatars/120/{{:hash}}" alt="{{:name}}">
        </div>
        <div class="media-body">
          <h4 class="media-heading">{{:name}}</h4>
          <div class="person__status">
            <span class="label label-{{:statusClass}}">{{if statusLabel}}{{:statusLabel}}{{/if}}{{if statusLabel && verbose}}: {{/if}}
            {{if verbose}}<span class="verbose">{{:verbose}}</span>{{/if}}
          </div>
        </div>
      </div>
    </div>
  </script>

The problem is that this way the templating-engine renders new template instead updating the data in the old template every time.

Any suggestions how I can make it update the already rendered template instead rendering a new one?


Solution

  • It might be better to only do the insertion into the DOM after looping through the array, rather than on each item. (Better perf).

    You could increment the html string, and insert at the end:

    ajax("http://localhost/tuntiseuranta/dbajax.php").then(function(result) {
      var personData = JSON.parse(result);
      var i = 0;
      var html = "";
      $.each(personData, function (index) {
        ...
        var person = {
          ...
        }
        ...
        html += $.templates('#personTmpl').render(person);
        i++;
      });
      $('.js-persons').html(html);
    })
    ...
    

    Or you could create and array of people, and use the fact the render() method 'understands' arrays:

    ajax("http://localhost/tuntiseuranta/dbajax.php").then(function(result) {
      var personData = JSON.parse(result);
      var i = 0;
      var people = [];
      $.each(personData, function (index) {
        ...
        var person = {
          ...
        }
        ...
        people.push(person)
        i++;
      });
      $('.js-persons').html($.templates('#personTmpl').render(people));
    })
    ...
    

    Either way, the previous content will get replaced by the new...

    If your personData is going to include mostly the same person items on successive requests, then you could consider using JsViews and having incremental rendering so that the unchanged person items do not re-render at all. See some suggestions and links I made in another answer here.