Search code examples
javascriptdjangoangularjstastypie

Scope not updating changes in the model


I have an expandable form that generates an object with two attributes, a title and description. This object successfully submits to my database as a json object. I'm currently using an Angular (1.3.2) front end that interacts with Tastypie as the interface layer with my Django (1.7) backend. The problem is that I never observe updates to my home page after adding a new object to the db. I need to refresh the page for the object to appear which is not ideal.

home.html

<div class="protocol-list-container">
<div ng-app="protocolApp"
     id="protocol-list">
  <div class="new-protocol-container" ng-controller="protoCtrl">
    <h4>Add New Protocol</h4>
    <button type="button" 
            ng-click="toggle()"
            id="id_new">
      <span class="glyphicon glyphicon-plus"></span>
    </button>
    <div ng-hide="visible" class="protocol-new">
      <form name="newProtocolForm" novalidate>
        <input type="text"
               id="id_new_title"  
               placeholder="Title" 
               ng-model="protocol.title"
               required /><br>
        <input type="text"
               id="id_new_desc" 
               placeholder="Description" 
               ng-model="protocol.description"
               required /><br><br>
        <input type="submit"
               id="id_submit_new_protocol" 
               value="New Protocol" 
               ng-click="submit(protocol)"
               ng-disabled="newProtocolForm.$invalid">
      </form>
      {% verbatim %}
      <pre>form = {{ protocol | json}}</pre>
      {% endverbatim %}
    </div>


    <div class="protocol">
      <h4>My Protocols</h4>
      <li ng-repeat="protocol in protocols"> 
        {% verbatim %}   
        <div><a href="/protocols/{{protocol.id}}"><span ng-bind="protocol.title"></span></a></div>
        {% endverbatim %}
        <div> - <span ng-bind="protocol.description"></span>
      </li>
      <br>
    </div>
  </div>
</div>

app.js

angular.module('protocolApp', [])
.factory('protocolFactory', ['$http', function($http) {

var urlBase = '/api/v1/protocol/';
var protocolFactory = {};

protocolFactory.getProtocols = function() {
  console.log('getProtocols called');
  return $http.get(urlBase);
};

protocolFactory.addProtocol = function(protocol) {
  console.log('addProtocol called');
  return $http.post(urlBase, protocol);
};

return protocolFactory;
}])

.controller('protoCtrl', ['$scope', 'protocolFactory',  
function ($scope, protocolFactory) {
$scope.visible = true;
var self = this;

getProtocols();

function getProtocols() {
  protocolFactory.getProtocols()
    .success(function(data) {
      $scope.protocols = data;
    })
    .error(function(error) {
      console.log('error retrieving protocols');
    });
}      

$scope.toggle = function() {
  $scope.visible = !$scope.visible;
  var self = this;
  var protocol = {};

  self.submit = function() {
    var protocol = {title: self.title, description: self.description};
    console.log('clicked submit with ', self.protocol);

    protocolFactory.addProtocol(self.protocol)
      .success(function(response) {
        console.log('protocol added');
        $scope.protocol = null;
      })
      .error(function(error) {
        console.log('post to api failed');
      });

      // gives the behavior I want, but ultimately crashes chrome 
      // $scope.$watch('protocols', function(newVal, oldVal) {
      //   protocolFactory.getProtocols()
      //     .success(function(data) {
      //       $scope.protocols = data;
      //       console.log('watcher data', data);
      //     });
      //   }, true); 
      };
  };        
}]);

I've done some testing with a $scope.$watch function (commented out), but this either shows the new object and never stops (true removed) or does not update (but tells me that there is an extra object in the data based on the console statement) (true present). Any help would be appreciated.


Solution

  • When the database gets updated, how does the front end know that it should get the latest data unless we tell it to ? You don't have some kind of sockets between the server and front end, looking for events and making the front end to get the latest data...

    So, When you post the data to backend and database got updated, make a call to getProtocols(), in the success callback of submit.

    In your case of using $watch(), you are repeatedly getting the protocols from backend, which updated the scope variable, which again fired the callback repeatedly and browser crashed.