The directive does not update the view with asynchronous data using controllerAs and bindToController
I'm having trouble getting the directive to update my view.
In my controller, I am setting intial values ββfor the directive's attributes <tiki-list>
. Then after 2 seconds I update vm.listObjectSelected
to test its async behavior.
However, the view does not reflect the update.
controller
var listObject = [{"display":"display1", "value":"value1"}, {"display":"display2", "value":"value2"}, {"display":"display3", "value":"value3"}]
vm.listObject = listObject
vm.listObjectSelected = [{"display":"display1", "value":"value1"}]
$timeout(function(){
vm.listObjectSelected = [{"display":"display1", "value":"value1"}, {"display":"display3", "value":"value3"}]
}, 2000)
Html
<tiki-list max="" type="multi" list="editController.listObject" selected="editController.listObjectSelected"></tiki-list>
Directive
(function(){
'use strict';
angular.module("tiki").directive("tikiList", tikiList)
function tikiList(helper){
var directive = {
restrict:"EA",
scope:{
list: "=", //the object to repeat over, this contains 2 array's
retunObject: "=", //the array that is outputted
selected: "=", //preselected values
max: "=", //maximum range, other elements are greyed out, starts at 0
title:"@title", //the title of this list
type:"@type", //[single, multi]
},
templateUrl:"js/directive/list.html",
link:link,
bindToController: true,
controllerAs:"vm",
controller:controller
}
return directive
function link(scope, el, attr, ctrl){
scope.vm.onClick = onClick
// preprocess the "list" if there is a "selected" attribute
// the "selected" attribute is an object that contains the selected items
// return a "selectedItems" array containing the indeces of matching display names
// add the .active property to the "list" object to the correct indeces
if(scope.vm.selected){
var selectedItems = helper.isItemInList(helper.createArrayFromProperty(scope.vm.selected, "display"), helper.createArrayFromProperty(scope.vm.list, "display"))
for(var i = 0; i < selectedItems.length; i++){
scope.vm.list[selectedItems[i]].active = true
}
}
// add the property .disabled to the "list" if there is a max attribute
// the property will be added to all indeces that exceed the max value
if(scope.vm.max){
for(var y = 0; y < scope.vm.list.length; y++){
if(y >= scope.vm.max){
scope.vm.list[y].disabled = true
}
}
}
function onClick(index){
// only allow items that are in range of the "max" attribute are allowed to be clicked
if(!scope.vm.max || index < scope.vm.max){
if(scope.vm.type === "single"){
angular.forEach(scope.vm.list, function(val, key){
scope.vm.list[key].active = false
})
scope.vm.list[index].active = true
}
if(scope.vm.type === "multi"){
scope.vm.list[index].active = !scope.vm.list[index].active
}
}
}
scope.vm.listing = scope.vm.list
}
}
controller.$inject = [];
function controller(){
}
})()
Directive pattern
<ul class="listOptions">
<li class="listOptions-title" ng-class="{'show':title}">{{vm.title}}</li>
<li ng-click="vm.onClick($index)" ng-class="{'active':list.active, 'disabled':list.disabled}" ng-repeat="list in vm.listing track by $index">{{list.display}}</li>
</ul>
I think it has something to do with the controller, but I can't get my head around it.
THX,
source to share
I think the reason is that the array is a reference type. When you change data in a service or async step, the data point moves to a new location in memory, but the data in the directive or controller does not change.
Instead of writing your function:
$timeout(function(){
vm.listObjectSelected = [{"display":"display1", "value":"value1"}, {"display":"display3", "value":"value3"}]
}, 2000)
You should try doing it like this:
$(timeout(function(){vm.listObjectSelected.push({you need data here})},200)
or you can use a promise, you can return a promise and get it in a directive, use
promise.then(function(){//let data = service.data again}
Hope this helps you.