Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Array as Model for Service Breaks when Empty

I have two routes: one has a custom component that repeats the data in an array and allows the user to add and remove items, the other route only displays the model. The model is stored in a service. The model JSON data looks like this:

[
    {name: "one"},
    {name: "two"},
    {name: "three"}
]

The components are all using ng-model and assigning this to a variable vm. Following all the best practices from John Papa style guide.

If I empty the array either by using slice(), pop(), or setting the array length to 0, it breaks. You can still add data to it, but if you navigate to the other route, the model will show as an empty array. And if you navigate back again, the array is still empty.

If I make my model an object with a key and the array as the value, everything works as expected. So my question is, is this just a limitation or am I doing something wrong?

{
    myarray: [
        {name: "one"},
        {name: "two"},
        {name: "three"}
    ]
}

Here is the working example using the object containing the array.

And here is the non working example just using the array.

You'll see on the one that does not work, you'll empty the array and then add to it, it will not persist data across the routes.

like image 961
Collin Thomas Avatar asked Oct 03 '17 13:10

Collin Thomas


1 Answers

you'll empty the array and then add to it, it will not persist data across the routes

1st Problem: in getAsync() method.

When your model is empty you call callAtInterval() every 100 milliseconds and you never resolve your promise (infinite loop).

function getAsync() {         
        function callAtInterval() {
            if (!_.isEmpty(genericHttpModel.model)){
                $interval.cancel(promise);
                deferred.resolve(get());
            }                
        }
        var deferred = $q.defer();
        var promise = $interval(callAtInterval, 100);
        return deferred.promise;
    }

Therefore when user goes to home (root) route:

 genericHttpService.getAsync().then(function(model){
      vm.model = model; // <-- never called 
    });

So remove if (!_.isEmpty(genericHttpModel.model)) statement

function callAtInterval() {                
     $interval.cancel(promise);
     deferred.resolve(get());
    }                
}

2nd problem: in add method:

 function add() {
       if (modelEmpty()) {
         initModelAndAddOne();
       } else {
        vm.model.push({});
      }
    }

In initModelAndAddOne you reset original instance of vm.model with:

 vm.model = [];

Your model is already empty, why to redefine it with =[], make it simple:

 function add() {
   vm.model.push({});
  }

Working Example Plunker


working example using the object containing the array.

So why it works:

  • 1st off _.isEmpty(genericHttpModel.model) will always return false because object contains field names a.e: genericHttpModel.model = {names:[]}
  • 2nd - vm.model = [] resets names field only and not service object
like image 178
Maxim Shoustin Avatar answered Oct 06 '22 07:10

Maxim Shoustin