Search code examples
javascriptangularjsangularjs-directiveangularjs-scope

Angular JS two-way bound variable does not update parent scope


My understanding of AngularJS directives is pretty poor. What I've been trying to do is use this mediaLibrary directive as a popup, so I can add media library items to a portfolio item (like images to a slideshow) using vm.toggleMediaToSiteItem. This function works perfectly. However, I'm trying to toggle the directive's 'active' variable on the parent scope to deactivate the popup by clicking on the 'media__freeze' div. Instead of changing the value of 'vm.MediaPopup', the closePopup function creates a new 'active' variable in the scope of the mediaLibrary directive. Any idea what I'm doing wrong? Below is the relevant code.

Parent HTML

<div ng-controller="parent as vm">
    <p>{{vm.Media | json}}</p>
    <a class="button" ng-click="vm.MediaPopup = !vm.MediaPopup">Add media</a>
    <media-library selected-media="vm.Media" multi-select="true" popup="true" active="vm.MediaPopup"></media-library>
</div>

Directive

<div class="media" ng-controller="mediaLibrary as lib" ng-class="popup ? 'popup' : ''">
<div ng-if="popup" class="media__freeze" ng-show="active" ng-click="lib.closePopup()">
    <img src="/cms/img/icons/close-white.png" alt="Close" />
</div>

Directive JS

directive('mediaLibrary', function($http, $timeout, $route){
return{
    restrict: 'E', //invoked by attibutes
    scope: {
        selectedMedia: '=selectedMedia',
        multiSelect: '=multiSelect',
        popup: '=',
        active: '=active'
    },
    templateUrl:'js/directives/templates/media-library.html',
    bindToController: emuueMediaLibrary
}
});

Controller JS

function emuueMediaLibrary($scope, $http, $location, mediaService, toastr, queryString){
var vm = this;
vm.view = 0;
vm.MediaImages = []
vm.MediaAudio = [];
vm.MediaVideo = [];
vm.loading = true;
vm.Limit = 50000000;
//console.log($scope); 

vm.toggleMediaToSiteItem = function(arr, item){
    if(!$scope.multiSelect){
        $scope.selectedMedia.length = 0;
        angular.forEach(arr, function(media){
            if(item.Id != media.Id){
                media.Selected = false;
            }
        })
    }
    if(item.Selected){
        $scope.selectedMedia.push({Id: item.Id, Path: item.FilePath});
    }else{
        $scope.selectedMedia.splice($scope.selectedMedia.indexOf(item.Id), 1);
    }
}

vm.closePopup = function(){
    $scope.active = false;
}
}

Solution

  • This is because two way binding will work only for reference types not value types, you have to wrap this active field in the object to make it work correct.

    Check this http://zcourts.com/2013/05/31/angularjs-if-you-dont-have-a-dot-youre-doing-it-wrong/#sthash.gXsaD1WA.dpbs