简体   繁体   中英

Pass angular directive scope to directive controller

I'm currently learning to use directives in AngularJs, and even though I know Angular 2.0 is still just in alpha, I've started reading into "preparing for angular 2.0" articles around the web.

There's quite a bit of them that mention stepping away from the link function and using the controller and bindToController just to make directives act a bit more like an Angular 2.0 "component".

The problem I'm having is that I don't really know how to pass my directive scope to the controller I'm using for that directive...
For instance, when given the following directive:

(function() {
  'use strict';

  angular.module('app').directive('gidsImagePreview', imagePreview);

  /* @ngInject */
  function imagePreview() {
    var directive = {
        restrict: 'EA',
      templateUrl: 'scripts/directives/gidsImagePreview.directive.html',
      scope : {
            images : '='
        },
      controller: ImagePreviewController,
      controllerAs: 'vm',
            bindToController: true
    };

    return directive;
  }

    /* @ngInject */
  function ImagePreviewController(){
        var self = this;
        self.featured = self.images[0];
        self.preview = preview;

        function preview(img){
            self.featured = img;
        }
  }
})();

And the following html to "call" the directive (vm.project.images is an array of image objects with a filename property):

<gids-image-preview images="vm.project.images"></gids-image-preview>

Then, how is it that my "self.images" in the ImagePreviewController is always undefined?

Reading this article , he/she seems to be doing exactly what I'm doing (just not with an array object)...

You simply need to inject the scope into the controllers. If you aren't minify-ing you cna simply put $scope as an argument to ImagePreviewController :

    function ImagePreviewController($scope) {
        ...
     }

Also if minify-ing is important add: ImagePreviewController.$inject = ['$scope']; below the controller definition.

If you want to use the array literal syntax, declare it this way:

    var ImagePreviewController = ['$scope', function ($scope) { ... }];

Then you can access the images array via $scope.images . I prefer using the $inject property, simply as a matter of style. The this/self workflow you were trying to use is only useful if you want the controller itself to expose an API for other directives to use.

For future reference, the angular docs have a pretty complete description of directives and the different ways you can compose them: https://docs.angularjs.org/guide/directive

但是您可以使用[directiveElement] .getIsolatedScope()函数。该函数随处可见。也许此函数可以通过其他方式帮助您解决问题。

As it turns out, nothing was really wrong with what I was doing. It was a timing issue.
The moment I wanted to use the "images" in my directive controller, it was still undefined because the main object on which my directive was bound (project.images) wasn't loaded yet.
I've put a resolve function in my routing config to make sure that the main object was loaded before my detailpage (containing the directive) is opened.

Also, just to add to this, @camden_kid mentioned I had to use var vm=this in my controller because I used the controllerAs: "vm" option; as far as I know, this is not true, what you use inside your controller function is irrelevant to how you refer to properties of that controller in your views.
So, using controllerAs: 'vm' only means you will have to use the "vm." notation in the view. It has nothing to do with what variable you will be using in the controller function (do correct me if this is wrong, but, from what I've learned so far, this is not the case).

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