简体   繁体   中英

AngularJS : Communication between directives - ng-repeat not refresh

I apologize of a mess but this is the first time on stackoverflow ;)

Link to jsfiddle http://jsfiddle.net/1u1oujmu/19/

I have problem with communication between directives and refresh ng-repeat . I have two pages homePage and dashboardPage - on these page I have directive when I refresh page (dashboardPage) everything is working, but when I switch on homePage and I will back to dahsboardPage my problem starts occurs.

Step reproduce:

  • dashboardPage - reload - add new link - list-link directive is refresh new link is on list
  • go to homePage
  • back to dashboard page
  • try to add new link - when link is added (on server and I receives response) I call factory to store a data:
dataFactory.editData("userLinksList", result.data);

//part of factory to edit and propagation data
editData: function(name, data){
        dataArray[name] = data;
        $rootScope.$broadcast(name);
    },

Then in directive controller I have condition to listen propagation "userLinksList" checkRootScope this is flag for only one register listener

Problem is in line:

$scope.data.links = dataFactory.getData("userLinksList");

In $scope.data.links I receives new data but I don't know why ng-repeat is not refresh

when I go to homePage and back to dashboard new link will be on list

if(checkRootScope){
  $rootScope.$on("userLinksList", function () {
    $scope.data.links = dataFactory.getData("userLinksList");
  });
  checkRootScope = false;
}
  • homePage - on the page I have list-link directive:

      <div class="columns marketing-grid"> <div class="col-md-6"> <list-link hp="true"></list-link> </div> </div> 
  • dashboardPage - on the page I have this same directive without parameter:
<div class="row">
  <div class="col-sm-12 col-md-8">
    <list-link></list-link>
  </div>
</div>

template of list-link :

<ul ng-if="data.links">
  <li ng-repeat="link in data.links | filter: search" class="link-list-item" data-id="{{link.id}}">
    <div class="row">
      <div class="col-md-9">
        <a ng-href="link.url"><h3>{{link.title}} <span>{{link.host}}</span></h3></a>
      </div>
      <div class="col-md-3 link-list-time text-right">
        {{link.date | date : 'd/MM/yyyy' }}
      </div>
      <div class="col-md-12">
        <blockquote ng-show="link.comment">{{link.comment}}</blockquote>
      </div>
      <div class="col-md-2">
        <span class="link-list-counter all" title="Number of links">{{link.counterAll}}</span>
      </div>
      <div class="col-md-6 link-list-tags">
        <span>tags:</span>
        <ul ng-if="link.tags">
          <li ng-repeat="item in link.tags"><a href="#" ng-click="">#{{item}}</a></li>
        </ul>
      </div>
      <div class="col-md-4 text-right link-list-buttons">
        <button class="btn btn-default btn-xs" title="Edit" ng-click="edit(link.id);">Edit <span class="glyphicon glyphicon-edit" aria-hidden="true"></span></button>
        <button class="btn btn-default btn-xs" title="Delete" ng-click="delete(link.id);">Delete <span class="glyphicon glyphicon-remove" aria-hidden="true"></span></button>
      </div>
    </div>
  </li>
</ul>

Directive list-link:

app.directive("listLink", ['path', function(path){
    var path = path.url(),
        checkRootScope = true;

    return {
        restrict : "E",
        scope : {
            hp : "="
        },
        templateUrl: path.template.listlink,
        replace : true,
        transclude : false,
        controller : ['$rootScope', '$scope','conn', 'auth', 'loaderService','stringOperation','dataFactory', function($rootScope, $scope, conn, auth, loaderService, stringOperation,dataFactory){

            var dataConenction = function(){
                conn.getData(path.server.link, { params : $scope.data })
                    .then(function(result){
                        if($scope.data.all == true){
                            dataFactory.addData("popularLinksList",result.data);
                            $scope.data.links = dataFactory.getData("popularLinksList");
                        } else{
                            dataFactory.addData("userLinksList",result.data);
                            $scope.data.links = dataFactory.getData("userLinksList");
                        }


                    }, function(msg){
                        console.log(msg);
                    });
            };

            $scope.hp = (typeof $scope.hp === "undefined" ? false : $scope.hp);
            $scope.path = path;
            $scope.userInfo = auth.getUserInfo();
            $scope.data = {
                auth : $scope.userInfo,
                check : false,
                all : $scope.hp
            };

            dataConenction();

            if(checkRootScope){
                $rootScope.$on("userLinksList", function () {
                    $scope.data.links = dataFactory.getData("userLinksList");
                });
                checkRootScope = false;
            }

            $scope.edit = function(id){
                $rootScope.$broadcast("editLink", {"id": id});
            };

            $scope.delete = function(id){
                var check = confirm("Are you sure you want to remove?");
                if (check == true) {
                    conn.deleteData(path.server.link, {"params" : {auth : $scope.userInfo, id : id}})
                        .then(function(result){
                            dataFactory.editData("userLinksList",result.data.links);
                            $scope.data.links = dataFactory.getData("userLinksList");

                            dataFactory.editData("userTagsList",result.data.tags);

                        }, function(msg){
                            console.log(msg);
                        });
                }
            };

        }]
    }
}]);

Not sure if you already fixed it but I had a crack at it.

First the "why not working" part -
Page1 creates a new scope, lets say scope1.
Page2 creates a new scope, say scope2.

When the Page1 is clicked the data.link is set to 5 items and below code is run [scope1.data.link = 5 items] -

        if(checkRootScope){
            $rootScope.$on("userLinksList", function () {
                $scope.data.links = dataFactory.getData("userLinksList");
            });
            checkRootScope = false;
        }

When the Page2 is clicked, it set 7 items to dataFactory and it is broadcasted to and $rootScope.on is executed to update scope2.data.links to 7 items. However scope2.data.links is still set to 5 items. This is because when $rootScope.on is executed first time the "$scope" variable within the "on" function refers to closure scope ie scope1 and NOT scope2. So essentially when scope.data.links is set to 7 then scope.data.links is set to 7 and scope2.data.links is still set to 5.

Basically ng-view creates a new scope and if directive is part of each of the views, you would always end up having different data.link value in each of the views.

Solution: You can fix it in two ways:

Option 1: You would be better off setting the value in scope as soon the promise is resolved instead of setting in factory and getting from it in $on listener. Atleast in this case.

http://plnkr.co/edit/IdrsO1OT9zDqdRiaSBho?p=preview

Option 2: If broadcast is really essentially I think you would have to bind the data.link to rootscope (which might not be a good practice).

http://plnkr.co/edit/VptbSKRf7crU3qqNyF3i?p=preview

and may be there are other options...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM