0

I have a widget like directive called waComments, it loads components via a RESTful service and displays them. In my view I'm using ng-repeat to loop over them and to render them with a button that if pressed Shows a new reply to form. This his handled by the waCommentsReply directive. One waComments widget has many child directives of type waCommentsReply. When the form is filled and submitted I want to add the new comment on top of my comments list. So both directives have to share the comments data.

I've tried to implement this here Sharing data between directives but without much success, the comment data is not updated when I add a new comment. I see that the RESTful API calls work and the data is returned, so this is not an issue.

Why is my implementation of Sharing data between directives not working in my case?

waCommentsReply directive:

waFrontend.directive('waCommentsReply', ['$rootScope', 'Comment', 'WaFormValidation', 'WaCommentStore', function($rootScope, Comment, WaFormValidation, WaCommentStore) {
    return {
        restrict: 'E',
        templateUrl: '/stubs/comment-form.html',
        transclude: true,
        scope: {
            replyTo: '@replyTo',
            replyFormList: '=replyFormList',
            loggedIn: '@loggedIn',
            model: '@model',
            id: '@id',
            cancelButton: '@cancelButton'
        },
        controller: function($scope) {
            $scope.comments = WaCommentStore;
            if ($scope.cancelButton == undefined) {
                $scope.cancelButton = true;
            } else {
                $scope.cancelButton = false;
            }

            $scope.comment = $scope.commentForm = {
                Comment: {
                    author_name: '',
                    body: '',
                    model: $scope.model,
                    foreign_key: $scope.id,
                    parent_id: $scope.replyTo
                }
            };

            $scope.$watch('replyFormList', function (newValue, oldValue) {
                if (newValue) {
                    $scope.replyFormList = newValue;
                }
            });

            if ($scope.loggedIn == undefined) {
                $scope.loggedIn = false;
            }

            /**
             * Handles the submission and response of a reply
             *
             * @return void
             */
            $scope.reply = function() {
                Comment.add($scope.comment).then(function(result) {
                    if (result.status == 'fail' || result.validation != undefined) {
                        $scope.validationErrors = result.validation;
                        WaFormValidation.validate(result.validation, $scope.commentForm);
                    } else if (result.status == 'success') {
                        //$scope.$parent.comments.unshift(result.data.comment);
                        //$scope.comments.unshift(result.data.comment);
                        $scope.comments.comments.unshift(result.data.comment);
                        //WaCommentStore.append($scope.model, $scope.id, result.data.comment);
                        $scope.comments, $scope.id, result.data.comment
                        $scope.comment = {};
                        $scope.replyFormList[$scope.replyTo] = false;
                    }
                });
            };

            $scope.close = function() {
                $scope.comment = {};
                if ($scope.replyFormList[$scope.replyTo] != undefined) {
                    $scope.replyFormList[$scope.replyTo] = false;
                }
            }
        }
    };
}]);

WaCommentStore directive:

waFrontend.factory('WaCommentStore', function() {
    return {
        comments: []
    };
});

waComments directive:

waFrontend.directive('waComments', ['$rootScope', 'Comment', 'WaCommentStore', function($rootScope, Comment, WaCommentStore) {
    return {
        restrict: 'E',
        templateUrl: '/stubs/comments.html',
        scope: {
            model: '@commentModel',
            id: '@commentFk'
        },
        controller: function($scope) {
            $scope.comments = WaCommentStore;
            $scope.loaded = false;
            $scope.loadedMore = true;
            $scope.currentPage = 1;
            $scope.loggedIn = false;
            $scope.paging = {};
            $scope.replyFormList = {};

            Comment.comments($scope.model, $scope.id).then(function(result) {
                $scope.comments.comments.push.apply($scope.comments.comments, result.data.comments);
                $scope.loggedIn = result.data.loggedIn;
                $scope.paging = result.paging.Comment;
                $scope.loaded = true;
            });

            $scope.loadMore = function() {
                $scope.loadedMore = false;
                if ($scope.paging.nextPage == false) {
                    //return false;
                }
                var options = {
                    page: $scope.paging.page + 1
                };
                Comment.comments($scope.model, $scope.id, options).then(function(result) {

                    $scope.comments.comments.push.apply($scope.comments.comments, result.data.comments);
                                        $scope.paging = result.paging.Comment;
                    $scope.loadedMore = true;
                });
            };

            $scope.submitComment = function() {
                //alert($scope.author_name + $scope.body);
            };

            $scope.reply = function(replyId) {
                $scope.replyFormList[replyId] = true;
            }
        }
    };
}]);
Community
  • 1
  • 1

2 Answers2

0

since in both directive you defined scope: {} basically it means you defined those directives to use isolated scope. with isolated scope, a scope/directive can't see what is in the parent scope. however parent scope, can be affected by the child scope changes with 2 way binding definition.

https://docs.angularjs.org/guide/scope

sagie
  • 1,744
  • 14
  • 15
  • "a scope/directive can't see what is in the parent scope" <- that is not true. $scope.$parent. But doing this is an anti-pattern in angular. Also to bind the data I would have to pass it to my child directives. –  Nov 20 '14 at 10:50
  • 1
    its 100% true. first make sure you understand what isolated scope actually means, than we can talk about hacking angular and working the wrong way. – sagie Nov 20 '14 at 11:40
0

try changing the shared data like this

waFrontend.factory('WaCommentStore', function() {
   var comments = [];

   var getComments = function() { return comments; }

   var setComments = function(data) { comments = data; }

   return {
        getComments : getComments ,
        setComments : setComments 
    };
});

I wanted to put it as a comments, but it would have been difficult to understand for you.

Please let me know if this works, else I will delete this answer.

harishr
  • 17,807
  • 9
  • 78
  • 125