Andrew Cooper
Andrew Cooper

Reputation: 747

Angular $scope variable breaking on update

In my Menu controller I have a function to save a Menu. The $scope.menu variable holds the object that represents my menu data. The saveMenu function sends an Ajax call off to a REST API endpoint and then receives the updated menu back as a response. The problem is that when I assign $scope.menu to the response all my data bindings in the HTML template break. Suddenly all the menu data disappears.

The controller code.

$scope.saveMenu = function() {
  var menu = $scope.createJsonMenuRequest();
  var method = "PUT";
  var url =  FoodUrls.foodAPI + "menus/" + menu.id;

  var req = {
    method: method,
    url: url,
    headers: {
      "Content-Type": "application/json"
    },
    data: angular.toJson(menu)
  };

  $http(req).success(function(data) {
    $scope.menu = $.extend(true, {}, data);
  });    
};

The createJsonMenuRequest function simply goes through the menu and removes some properties from the copy that the API doesn't like.

Why does the binding to the HTML template break?

Updated

Before the assignment statement in the success function, the $scope.menu looks something like this.

{
   name: "My Menu",
   sections: [
      { $$hashKey: "object:17", id: 1, name: "blarg"}
   ]
}

Afterwards it looks like this...

{
   name: "My Menu",
   sections: [
      { id: 1, name: "blarg-edited"}
   ]
}

It loses the $$hashKeys that Angular is putting in there when the menu is originally created. Not sure what the significance of that is.

Upvotes: 0

Views: 217

Answers (2)

Jason
Jason

Reputation: 33

I can't comment yet, so I'll just put this here.

How far did you debug?

I'd look at $scope.menu before the update, and then again after in your success method.

What's your data / template look like?

And just for my own curiosity, why the deep $.extend ? Could be totally valid, I've just never used it in this way.

Saw your update, the $hashkey shouldn't be an issue, if you don't want it, you angular.copy(data) or simply put a track by in your ng-repeat :

data-ng-repeat="item in menuItems track by $index"

Upvotes: 0

abiwer
abiwer

Reputation: 121

I would not recommend using jQuery's extend functions against any property on an angular $scope. $scope is a complicated object with lots of pointers to specific properties and such. I would recommend using angular.merge, as it should do a better job of merging the objects correctly without breaking the scope.

https://docs.angularjs.org/api/ng/function/angular.merge

Upvotes: 1

Related Questions