2016-09-26 5 views
5

私たちのアプリケーションには、かなり大きくなる可能性のあるタスクのリストがあります。メインのタスクリストにはサイドバーがあり、タスクを選択するとサイドバーで編集できます。サイドバーでは、別のコントローラを使用します(リストを表示するTasksCtrlではなくTasksSidebarCtrl)。選択したタスクがコピーされ、リストにマージされます。この通信はTasksServiceで処理されます。トラックを使用している間にng-repeat配列の強制スプライス

インデックス内のタスクあたりのウォッチャ数が膨大なので、別のアプローチをとることにしました。

1回のバインディングを使用すると、ウォッチャーの数が大幅に減りました(実際には、ウォッチャーを作成するサイドバーでタスクのステータスを編集/変更するサブメニューのみです)が、task.id(これは私が必要とするフィルタの数とDOMの変更頻度を考慮して必要なものです)スプライスを使用してタスクを削除して新しい更新タスクに置き換えることはありません。トラックのポイント。

トラックバイとワンタイムバインディングの両方を使用してこのタスク項目whistの更新を強制的に強制する方法はありますか?

タスク-index.htmlを(私は読みやすさを支援するためのフィルタを削除しました)

<md-list-item my-task-directive ng-repeat="task in TasksCtrl.tasks track by task.id"> 

TasksCtrl

TasksService.index().then(function(tasks) { 
    vm.tasks = tasks.data ? tasks.data : []; 
}); 

$scope.$on('task-updated', function() { 
    var newTask = TasksService.getUpdatedTask(); 
    $timeout(function() { 
     vm.tasks.splice(newTask.index, 1, newTask.task); 
    }); 
}); 

TaskSidebarCtrl

$scope.$watch(function() { 
    return TasksService.getSelectedTask(); 
}, function (newVal, oldVal) { 

    if (newVal !== oldVal) { 
     /* Using copy here so index view does not update as we edit */ 
     vm.selectedTask = angular.copy(newVal); 
     vm.index = TasksService.getSelectedTaskIndex(); 

    } 
}); 

TasksService.update(vm.selectedTask).then(function(data) { 
    // notifications etc here, then... 
    TasksService.updateTaskInIndex(vm.index, data.data); 
}); 

代わりTasksService.updateTaskInIndex(vm.index、data.data)TaskSidebarCtrl 更新で関数のTasksService

var selectedTask = {}; 
var indexOfTask; 
var updatedTask = {}; 
var updatedIndex; 

this.setSelectedTask = function(task, index) { 
    selectedTask = task; 
    indexOfTask = index; 
}; 
this.getSelectedTask = function() { 
    return selectedTask; 
}; 
this.getSelectedTaskIndex = function() { 
    return indexOfTask; 
}; 
this.getUpdatedTask = function() { 
     return { 
      'index': updatedIndex, 
      'task': updatedTask 
     }; 
}; 
this.updateTaskInIndex = function(index, task) { 
    updatedTask = task; 
    updatedIndex = index; 
    $rootScope.$broadcast('task-updated'); 
}; 

(宛先で)単純angular.copyを使用する一ことを意味します1回限りのバインディングのため、インデックスビューでは時間バインドされたプロパティは更新されません。上記の作業はby task.idではありませんが、できるだけこの犠牲を払うつもりはありません。また、私は一度限りの拘束力を犠牲にしたくありません。

回避策はありますか?

+2

優秀な質問です。あなたは例を挙げていくつかのプランナーを持っていますか? –

+0

問題の複製を試みました。それはうまく働いたhttp:// jsfiddle。net/21Lt4g26/ –

+0

@rishabhdevあなたは1回限りのバインディングを使用していません。私のタスクオブジェクトの複雑さとレンダリングが必要な番号のために、1つの時間バインディングを使用することは不可欠です。 – DJC

答えて

1

track by task.idは新しい更新されたタスクで同じ値を取得するため、エントリのDOM要素を再構築することはなく、この既存の要素の式は1回限りのバインディングによって更新されません。

エントリが更新されたときに変更される式は、古いタスクのノードを削除し、新しいノードを挿入します.1回限りのバインド式が再び評価されます。このための簡単な方法は、tracking_idというプロパティーに"{id}_{version}"という形式のプロパティを割り当てることです。バージョンはすべての更新で変更され、track by task.tracking_idを使用します。

関連する問題