usersam
usersam

Reputation: 1245

angular set $scope.value in controller function is not working

I am trying to set a angular variable value in controller function which is created by a directive. Somehow it is not working for some unknown reasons. The value is displayed when set independently but doesn't work when i try to assign value in a controller function.

My code is as below,

<!doctype html>
<html>
<head>
<meta charset="UTF-8" />
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular.min.js"></script>

</head>
<body>
    <div ng-app="mainApp">
        <div ng-controller="MyController">
            <div id="Details" class="Details">{{Details}}</div></br>
             <div id="Test" class="Test">
             <collection collection='testdata'></collection>             
             </div>          
        </div>              
    </div>
</body>
<script>    
var mainApp = angular.module("mainApp", [])

mainApp.directive('collection', function () {
    return {
        restrict: "E",
        replace: true,
        scope: {collection: '=', showFn : '&'},
        template: "<ul><member ng-repeat='member in collection' member='member'></member></ul>"         
    }
})

mainApp.directive('member', function ($compile) {
    var NewChild = "<li><span ng-click=ShowDetailsFunc()>{{member.TagName}}</span></li>";

    return {
        restrict: "E",
        replace: true,
        scope: {member: '=', ShowHideCtrlFunc : '&', ShowDetailsCtrlFunc : '&'},
        template: NewChild,
        controller: 'MyController',
        link: function (scope, element, attrs) {            
            var collectionSt = '<collection collection="member.children"></collection>';
            if (angular.isArray(scope.member.children)) {               
                    $compile(collectionSt)(scope, function(cloned, scope)   {                                           
                        element.attr('xml-path', scope.member.TagPath);
                        element.append(cloned);                         
                     });                      
                    scope.ShowDetailsFunc = function() {
                        scope.ShowDetailsCtrlFunc(element,event);                     
                    }

            }
        }   

    }
})

mainApp.controller('MyController', function ($scope) {
    $scope.testdata = [{"TagName":"MyRootNode","TagPath":">MyRootNode","children":[{"TagName":"LandXML","TagPath":">MyRootNode>ChildItems>LandXML","children":[{"TagName":"Units","TagPath":">MyRootNode>ChildItems>ChildItems[1]>Units","children":[{"TagName":"Imperial","TagPath":">MyRootNode>ChildItems>ChildItems[1]>ChildItems[1]>Imperial","children":[]},{"TagName":"Project","TagPath":">MyRootNode>ChildItems>ChildItems[1]>Project","children":[]},{"TagName":"Application","TagPath":">MyRootNode>ChildItems>ChildItems[1]>Application","children":[{"TagName":"Author","TagPath":">MyRootNode>ChildItems>ChildItems[1]>ChildItems[2]>Author","children":[]},{"TagName":"Alignments","TagPath":">MyRootNode>ChildItems>ChildItems[1]>Alignments","children":[]},{"TagName":"Roadways","TagPath":">MyRootNode>ChildItems>ChildItems[1]>Roadways","children":[{"TagName":"Roadway","TagPath":">MyRootNode>ChildItems>ChildItems[1]>ChildItems[3]>Roadway[1]","children":[]},{"TagName":"Roadway","TagPath":">MyRootNode>ChildItems>ChildItems[1]>ChildItems[3]>Roadway[2]","children":[]},{"TagName":"Roadway","TagPath":">MyRootNode>ChildItems>ChildItems[1]>ChildItems[3]>Roadway[3]","children":[]},{"TagName":"Roadway","TagPath":">MyRootNode>ChildItems>ChildItems[1]>ChildItems[3]>Roadway[4]","children":[]},{"TagName":"Roadway","TagPath":">MyRootNode>ChildItems>ChildItems[1]>ChildItems[3]>Roadway[5]","children":[]}]}]}]}]},{"TagName":"Surfaces","TagPath":">MyRootNode>ChildItems>Surfaces","children":[{"TagName":"Surface1","TagPath":">MyRootNode>ChildItems>ChildItems[2]>Surface1","children":[]},{"TagName":"Surface2","TagPath":">MyRootNode>ChildItems>ChildItems[2]>Surface2","children":[]}]}]}]

    $scope.Details = "defalut value"
    $scope.ShowDetailsCtrlFunc = function(element,event) {
            console.log("in function ShowDetailsCtrlFunc");                     
            var myxmlpath = $(element).attr("xml-path")
            $scope.Details = getObjects($scope.testdata, 'TagPath', myxmlpath)[0].TagName; 
            console.log($scope.Details)                         
            //event.stopImmediatePropagation();
      };    
});
function getObjects(obj, key, val) {
    var objects = [];
    for (var i in obj) {
        if (!obj.hasOwnProperty(i)) continue;
        if (typeof obj[i] == 'object') {
            objects = objects.concat(getObjects(obj[i], key, val));
        } else if (i == key && obj[key] == val) {
            objects.push(obj);
        }
    }
    return objects;
}   
</script>   
</html>

Please help me to understand where i am making mistake and how it can be rectified.

Please help. Many thanks in advance.

Upvotes: 0

Views: 377

Answers (1)

Marcus H&#246;glund
Marcus H&#246;glund

Reputation: 16846

The problem is that you are nesting MyController-controller when you create the directives in this circular way. The result is that the $scope.Details gets set on the specific nested scope instead of the one which is presenting the value in the view.

You can solve this by $emit the change which will send the new value upstream and finally reach the presenting scope value.

Here's an example

var mainApp = angular.module("mainApp", [])

mainApp.directive('collection', function () {
    return {
        restrict: "E",
        replace: true,
        scope: {collection: '=', showFn : '&'},
        template: "<ul><member ng-repeat='member in collection' member='member'></member></ul>"         
    }
})

mainApp.directive('member', function ($compile) {
    var NewChild = "<li><span ng-click=ShowDetailsFunc()>{{member.TagName}}</span></li>";

    return {
        restrict: "E",
        replace: true,
        scope: {member: '=', ShowHideCtrlFunc : '&', ShowDetailsCtrlFunc : '&'},
        template: NewChild,
        controller: 'MyController',
        link: function (scope, element, attrs) {            
            var collectionSt = '<collection collection="member.children"></collection>';
            if (angular.isArray(scope.member.children)) {               
                    $compile(collectionSt)(scope, function(cloned, scope)   {                                           
                        element.attr('xml-path', scope.member.TagPath);
                        element.append(cloned);                         
                     });                      
                    scope.ShowDetailsFunc = function() {
                        scope.ShowDetailsCtrlFunc(element);                     
                    }

            }
        }   

    }
})

mainApp.controller('MyController', function ($scope) {
    $scope.testdata = [{"TagName":"MyRootNode","TagPath":">MyRootNode","children":[{"TagName":"LandXML","TagPath":">MyRootNode>ChildItems>LandXML","children":[{"TagName":"Units","TagPath":">MyRootNode>ChildItems>ChildItems[1]>Units","children":[{"TagName":"Imperial","TagPath":">MyRootNode>ChildItems>ChildItems[1]>ChildItems[1]>Imperial","children":[]},{"TagName":"Project","TagPath":">MyRootNode>ChildItems>ChildItems[1]>Project","children":[]},{"TagName":"Application","TagPath":">MyRootNode>ChildItems>ChildItems[1]>Application","children":[{"TagName":"Author","TagPath":">MyRootNode>ChildItems>ChildItems[1]>ChildItems[2]>Author","children":[]},{"TagName":"Alignments","TagPath":">MyRootNode>ChildItems>ChildItems[1]>Alignments","children":[]},{"TagName":"Roadways","TagPath":">MyRootNode>ChildItems>ChildItems[1]>Roadways","children":[{"TagName":"Roadway","TagPath":">MyRootNode>ChildItems>ChildItems[1]>ChildItems[3]>Roadway[1]","children":[]},{"TagName":"Roadway","TagPath":">MyRootNode>ChildItems>ChildItems[1]>ChildItems[3]>Roadway[2]","children":[]},{"TagName":"Roadway","TagPath":">MyRootNode>ChildItems>ChildItems[1]>ChildItems[3]>Roadway[3]","children":[]},{"TagName":"Roadway","TagPath":">MyRootNode>ChildItems>ChildItems[1]>ChildItems[3]>Roadway[4]","children":[]},{"TagName":"Roadway","TagPath":">MyRootNode>ChildItems>ChildItems[1]>ChildItems[3]>Roadway[5]","children":[]}]}]}]}]},{"TagName":"Surfaces","TagPath":">MyRootNode>ChildItems>Surfaces","children":[{"TagName":"Surface1","TagPath":">MyRootNode>ChildItems>ChildItems[2]>Surface1","children":[]},{"TagName":"Surface2","TagPath":">MyRootNode>ChildItems>ChildItems[2]>Surface2","children":[]}]}]}]

    $scope.Details = "defalut value";
    $scope.ShowDetailsCtrlFunc = function(element) {
            console.log("in function ShowDetailsCtrlFunc");                     
            var myxmlpath = angular.element(element).attr("xml-path")
            var detail = getObjects($scope.testdata, 'TagPath', myxmlpath)[0].TagName; 
            console.log(detail);
            $scope.$emit('detailSelected',detail);
            //event.stopImmediatePropagation();
      };
      $scope.$on('detailSelected',function($event, message){
      $scope.Details = message;
    });
});
function getObjects(obj, key, val) {
    var objects = [];
    for (var i in obj) {
        if (!obj.hasOwnProperty(i)) continue;
        if (typeof obj[i] == 'object') {
            objects = objects.concat(getObjects(obj[i], key, val));
        } else if (i == key && obj[key] == val) {
            objects.push(obj);
        }
    }
    return objects;
}
<!doctype html>
<html>
<head>
<meta charset="UTF-8" />
<script data-require="[email protected]" data-semver="1.6.4" src="https://code.angularjs.org/1.6.4/angular.min.js"></script>

</head>
<body>
    <div ng-app="mainApp">
        <div ng-controller="MyController">
            <div id="Details" class="Details">{{Details}}</div></br>
             <div id="Test" class="Test">
             <collection collection='testdata'></collection>             
             </div>          
        </div>              
    </div>
</body>
  
</html>

Upvotes: 1

Related Questions