1

I've got a simple CRUD app running on a Linux server with Apache and MySQL. The database operations are done by PHP scripts. The crud operations are working fine, the server is on a different machine than the developing machine.

Everything is almost fine, but when I try to list the items in the database after an create, update or delete operation, the list sometimes updates and sometimes it doesn't.

Here's the code.

index.html:

    <body ng-controller="GetScenesCtrl">

    <ul>
      <li ng-repeat="scene in scenes">
        <em><a href="#/getscene/{{scene.scene_id}}">{{scene.scene_name}}</a></em>
      </li>
    </ul>

service:

    angular.module('writServices', ['ngResource'])
      .factory('Scenes', function($resource){
        return $resource('/:id/:nimi/:sisalto/:pics', {}, {
          query: {
            url:'php/getscenes.php',
             method:'GET', 
             isArray:true
          }
    });

    App.service('ScenesService', function ($rootScope, Scenes) {      
      var scenes = [];

      this.setScenes = function() {
        scenes = Scenes.query();
        $rootScope.$broadcast('updscenes', scenes);
      };
      this.getScenes = function() {
        scenes = Scenes.query();
        return scenes;
      };        
    });

controller:

    App.controller('GetScenesCtrl', function($scope, Scenes, ScenesService) {

      $scope.scenes = Scenes.query(); 
      //$scope.scenes = ScenesService.setScenes();
      //$scope.scenes = ScenesService.getScenes();    

      //$scope.$on('updscenes', function(event, scenes) {
      //    $scope.scenes = scenes;
      //}); 

      $scope.updateScenes = function() {
            $scope.scenes = Scenes.query();  
      };

    });

Ok, so when index.html first time loads I use the Scenes.query() method to initialize the list. The updateScenes() -method is called after an CRUD -operation to update the scope. This call is from another Controller. Like this:

    App.controller('AddSceneCtrl', function($scope, Scenes, ScenesService) { 

    $scope.addScene = function(scene) {

     Scenes.add({         
                     nimi : scene.name,
                     sisalto : scene.content
                    });

        $scope.updateScenes();  
        //$scope.scenes = ScenesService.getScenes();    
        //ScenesService.setScenes();                      
    } 

    });

Another way of updating the scope I've tried was the broadcasting way, and both ways work similarly leaving the list sometimes unupdated. Why is this? There must be a better way, the Angular way, of doing this. I'm rather newbie with Angular, so there must be something I've missed here.

Stone

3
  • 1
    The code you posted only seems to query, it doesn't show any updating. However, I think what happens is that the update is asynchronous, so if you fetch the data immediately after an update it will probably hit a different thread on the server and the result can actually be returned before the original update has completed. The $save() method takes a callback function which you can use to tell when the save has completed. Commented Aug 16, 2013 at 14:27
  • Yes, I added another controller to the post. I thought it could have something to do with the timings. Unfortunately I'm such a noobie that I don't understand how I would do The $save() method takes a callback function which you can use to. So if you could elaborate how I would do that? Commented Aug 16, 2013 at 14:32
  • bresleveloper.blogspot.co.il/2013/08/… Commented Aug 16, 2013 at 14:33

1 Answer 1

2

To followup on the comment from @Duncan, here's a quote from the documentation:

It is important to realize that invoking a $resource object method immediately returns an empty reference (object or array depending on isArray). Once the data is returned from the server the existing reference is populated with the actual data. This is a useful trick since usually the resource is assigned to a model which is then rendered by the view. Having an empty object results in no rendering, once the data arrives from the server then the object is populated with the data and the view automatically re-renders itself showing the new data. This means that in most case one never has to write a callback function for the action methods.

The action methods on the class object or instance object can be invoked with the following parameters:

HTTP GET "class" actions: Resource.action([parameters], [success], [error])
non-GET "class" actions: Resource.action([parameters], postData, [success], [error])
non-GET instance actions: instance.$action([parameters], [success], [error])

Success callback is called with (value, responseHeaders) arguments. Error callback is called with (httpResponse) argument.

So, you should do:

Scenes.add(
    {         
        nimi : scene.name,
        sisalto : scene.content
    }, 
    function() { // this function is invoked when the add is successful
        $scope.updateScenes();
    });

Or simply

Scenes.add(
    {         
        nimi : scene.name,
        sisalto : scene.content
    }, 
    $scope.updateScenes);
Sign up to request clarification or add additional context in comments.

2 Comments

Ok, seems to work! Thank You. One more minor question though: why does $scope.updateScenes work but not $scope.updateScenes()?
The second snippet above is similar to the first one. It passes the updateScenes function to the add() method. The add() method calls this updateScenes function when a successful response has been received. Replacing updateScene by updateScenes() in the second snippet above would call the updateScene function, and pass the result of this function (which is probably undefined) to the add() function.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.