Update array element in filtered view

20 views
Skip to first unread message

Brian McElhany

unread,
Apr 25, 2014, 5:15:41 PM4/25/14
to ang...@googlegroups.com
Hi all,

I'm just starting out with Angular and I'm running into an issue that I think should have an easy solution, but I'm having a hard time getting my head around how it should work.

In a nutshell, I have a list of categories (id, name) and a list of tasks (id, name, category_id). Clicking on a category link should filter the task list by that category. This is working fine. In addition, I'd like to be able to drag a task on top of a category label to re-categorize that task and have the UI updated accordingly (e.g. click on Category2 to see a list of Category 2's tasks, drag one of those tasks to the Category 3 label, that task should disappear from the current Category 2 filtered view and should appear when clicking on Category 3).

To set this all up, I've got a controller which handles the filtering and has a changeCategory() method that should find the task we're dealing with and change its category. I also have two directives: one to make an element (task) draggable and another to make an element (category) droppable.

In my "real" app, when I drop a task on top of a category, I make an ajax call to update the database and this works perfectly. The problem is that the UI doesn't reflect that the task's category has changed (as highlighted above). I've put together a simplified example of how I've got things set up: JSBin

If anyone could help point me in the right direction, I would be forever grateful :) Thanks!

Sander Elias

unread,
Apr 26, 2014, 12:12:34 AM4/26/14
to ang...@googlegroups.com
Hi Brian,

You are changing things outside angular. You have to tell angular to update it's stuff. You do that with an scope.$apply

Here is an article that explains it a bit more: http://jimhoskins.com/2012/12/17/angularjs-and-apply.html

Regards
Sander


Brian McElhany

unread,
Apr 26, 2014, 10:14:34 AM4/26/14
to ang...@googlegroups.com
Ok, I think I've got this squared away...posting here in case it might help someone else.

Sander's recommendation to wrap the call to my controllers changeCategory() method in a "scope.$apply()" definitely needed to be done. However, even though I could see that my controller's method was being successfully called, the UI wasn't updating correctly: I'd drag a task from one category to a new category, but that task wouldn't show up in the new category (or disappear from the old category).

I think this was because in my controller's method, I was trying to find the task I was dropping (based on its ID) by using a filter:

var task = $filter('filter')($scope.tasks, {id: task_id}, true);

I remember reading that any time you use a filter on an array, a new copy is made of that array containing the filtered data. I think by doing this, the task I was finding (and updating) belonged to a different (new) array than was being used for my bound task list. So, instead of using a filter to find my task, I did it the old fashioned way, using a loop:

for(var i=0; i<$scope.tasks.length; i++) {
   var task = $scope.tasks[i];
   if(task.id == task_id){
      task.category_id = category_id;
   }
}

This seems to be working perfectly! It seems like there should be a more elegant way of doing this but it is behaving as expected. Here's a new bin showing the result.

If anyone has any ideas regarding a cleaner way of accomplishing this, I'd be curious to hear about it. This gives me enough to work with, though.

Thanks!
Reply all
Reply to author
Forward
0 new messages