Bhargav Ponnapalli
Bhargav Ponnapalli

Reputation: 9422

Angular Directive Two Way Binding Not Working

I am trying to use the two way directive binding using "=" in the directive scope object, but its not working if I update the value within a callback function inside the link function (Not getting updated in the controller).

Directive

app.directive("simpleDropdown",function($document,$compile){
    return {
        scope:{
            content:"=",
            array:"="
        },
        restrict:'EA',
        template:'<span class="simple-dropdown"><ul class="dropdown-menu"><li ng-repeat="i in array" data-index="{{$index}}"><a>{{i}}</a></li></ul></span>',
        compile:function(tElem,tAttrs){
            return function link(scope,elem,attrs){

                    //This is updated in the controller.
                    scope.content = scope.array[0];


                    var origin = angular.element(elem);
                    var dropdownSpan = origin.find(".simple-dropdown");
                    var dropdownMenu = $(dropdownSpan).find(".dropdown-menu");
                    dropdownSpan.prepend(scope.content);
                    var closeAllDropdowns = function(){
                        angular.element($document).find(".simple-dropdown .dropdown-menu").removeClass("show");
                    }
                    var handler = function(){
                            //close all dropdownMenus in simpleDropdown
                            closeAllDropdowns();

                        };
                    dropdownSpan.on("click",function(e){
                        e.stopPropagation();
                        closeAllDropdowns();
                        dropdownMenu.addClass("show");
                        var selectElement = function(event){
                            event.stopPropagation();
                            closeAllDropdowns();
                            console.log(scope.content);


                            //This is not updated
                            scope.content = angular.element(this).find("a").html();


                        };
                        dropdownMenu.find("li").off("click").on("click",selectElement);
                        $document.on("click",handler);
                        scope.$on("destroy",function(){
                        $document.off('click',handler);
                    });
                    }); 

            }
        }
    }
});

Controller

var module = angular.module("dataemoApp",["multiAutocomplete","simpleDropdown"]);


module.controller("mySuperAwesomeController",['$scope',function($scope){

$scope.assignee = "Bhargav";
$scope.assignees = [
    "Bhargav",
    "Akhilesh",
    "Utsav"
];
}]);

HTML

<simple-dropdown content="assignee" array="assignees"> </simple-dropdown> 

Scope.$apply does not work either. Am I missing something here? Please let me know. Thanks.

Upvotes: 1

Views: 2022

Answers (3)

Long Field
Long Field

Reputation: 878

As bind to array, you need "=?", instead of "=" in your directive

scope:{content:"=",array:"=?"}

Upvotes: 0

Pavel Morshenyuk
Pavel Morshenyuk

Reputation: 11471

Try to operate with object properties, not a string:

scope:{
   content: { text: "="},
   array: {text: "="}
}

Like this:

app.directive("simpleDropdown",function($document,$compile){
    return {
        scope:{
           content: { text: "="},
           array: { value: "="}
        },
        restrict:'EA',
        template:'<span class="simple-dropdown"><ul class="dropdown-menu"><li ng-repeat="i in array.value" data-index="{{$index}}"><a>{{i}}</a></li></ul></span>',
        compile:function(tElem,tAttrs){
            return function link(scope,elem,attrs){

                    //This is updated in the controller.
                    scope.content.text = scope.array.value[0];


                    var origin = angular.element(elem);
                    var dropdownSpan = origin.find(".simple-dropdown");
                    var dropdownMenu = $(dropdownSpan).find(".dropdown-menu");
                    dropdownSpan.prepend(scope.content.text);
                    var closeAllDropdowns = function(){
                        angular.element($document).find(".simple-dropdown .dropdown-menu").removeClass("show");
                    }
                    var handler = function(){
                            //close all dropdownMenus in simpleDropdown
                            closeAllDropdowns();

                        };
                    dropdownSpan.on("click",function(e){
                        e.stopPropagation();
                        closeAllDropdowns();
                        dropdownMenu.addClass("show");
                        var selectElement = function(event){
                            event.stopPropagation();
                            closeAllDropdowns();
                            console.log(scope.content.text);


                            //This is not updated
                            scope.content.text = angular.element(this).find("a").html();


                        };
                        dropdownMenu.find("li").off("click").on("click",selectElement);
                        $document.on("click",handler);
                        scope.$on("destroy",function(){
                        $document.off('click',handler);
                    });
                    }); 

            }
        }
    }
});

Upvotes: 2

orange
orange

Reputation: 8090

You're overwriting scope.content with a new variable. This won't be updated. Try scope.content.push('something') instead or something else that maintains the object reference of scope.content.

Upvotes: 3

Related Questions