Passing asynchronously obtained data to a directive

假如想象 提交于 2019-12-18 05:10:15

问题


I currently have an AngularJS controller that is basically getting some JSON asynchronously through a $http.get() call, then linking the obtained data to some scope variable.

A resumed version of the controller code:

mapsControllers.controller('interactionsController', ['$http', function($http) {
  var ctrlModel = this;

  $http.get("data/interactionsPages.json").
  success(function(data) {
    ctrlModel.sidebar = {};
    ctrlModel.sidebar.pages = data;
  }).
  error(function() {...});
}]);

Then, I have a custom directive which receives those same scope variables through a HTML element.

A resumed version of the directive code:

mapsDirectives.directive('sidebar', function() {
  return {
    restrict : 'E',
    scope : {
      pages : '@'
    },
    controller : function($scope) {            
      $scope.firstPage = 0;

      $scope.lastPage = $scope.pages.length - 1;

      $scope.activePage = 0;

      //...
    },
    link : function(scope) {
      console.log(scope.pages);
    },
    templateURL : 'sidebar.html'
  }
});

A resumed version of the HTML:

<body>
  <div ng-controller='interactionsController as interactionsCtrl'>
    <mm-sidebar pages='{{interactionsCtrl.ctrlModel.sidebar.pages}}'>
    </mm-sidebar>
  </div>
</body>

The problem is, since the $http.get() is asynchronous, the directive is being badly initialised (e.g: $scope.pages.length - 1 is undefined).

I couldn't find anything that solved this problem for me, although there are some presented solutions that would seem to solve the case. Namely, I tried to watch the variables, only initialising the variables after detected changes, as suggested in many other posts. For testing, I used something like:

//... inside the directive's return{ }
link: function() {
  scope.$watch('pages', function(pages){
    if(pages)
      console.log(pages);
  });
}

I've tested it, and the $watch function wasn't called more than once (the logged value being undefined), which, I assume, means it isn't detecting the change in the variable value. However, I confirmed that the value was being changed.

So, what is the problem here?


回答1:


Move the declaration for the sidebar object in the controller and change the scope binding to =.

mapsDirectives.controller("interactionsController", ["$http", "$timeout",
    function($http, $timeout) {
        var ctrlModel = this;
        ctrlModel.sidebar = {
            pages: []
        };
      /*
      $http.get("data/interactionsPages.json").
          success(function(data) {
          //ctrlModel.sidebar = {};
          ctrlModel.sidebar.pages = data;
       }).
       error(function() {});
      */

      $timeout(function() {
        //ctrlModel.sidebar = {};
        ctrlModel.sidebar.pages = ["one", "two"];
      }, 2000);
    }
]);

mapsDirectives.directive('mmSidebar', [function() {
    return {
      restrict: 'E',
      scope: {
        pages: '='
      },
      controller: function() {},
      link: function(scope, element, attrs, ctrl) {
        scope.$watch("pages", function(val) {
          scope.firstPage = 0;
          scope.lastPage = scope.pages.length - 1;
          scope.activePage = 0;
        });
      },
      templateUrl: 'sidebar.html'
    };
}]);

Then match the directive name and drop the braces.

<mm-sidebar pages='interactionsCtrl.sidebar.pages'>
</mm-sidebar>

Here's a working example: http://plnkr.co/edit/VP79w4vL5xiifEWqAUGI




回答2:


The problem appears to be your html markup.

In your controller you have specified the ctrlModel is equal to this.

In your html markup you have declared the same this to be named interactionsController.
So tacking on ctrlModel to interactionsController is incorrect.

<body>
  <div ng-controller='interactionsController as interactionsCtrl'>
    <!-- remove this -->
    <mm-sidebar pages='{{interactionsCtrl.ctrlModel.sidebar.pages}}'>

    <!-- replace with this -->
    <mm-sidebar pages='{{interactionsCtrl.sidebar.pages}}'>

    </mm-sidebar>
  </div>
</body>


来源:https://stackoverflow.com/questions/29520247/passing-asynchronously-obtained-data-to-a-directive

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!