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,

+3


source to share


1 answer


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.

0


source







All Articles