简体   繁体   中英

Angular directive > Dynamic controller name > Interpolate controller name

I need some help on how to pass controllers definitions to inner directive nested in outer directive. Please see http://plnkr.co/edit/Om2vKdvEty9euGXJ5qan for a (not)working example.

  1. Is there any way to make angular interpolate what is passed on script.js@46 as item.ctrlName ?
  2. How to use controllerAs syntax in inner directive?

1) if you need the inner directive to have the parent controller you can use the require params on the inner directive. Something like this

angular.module('docsTabsExample', [])
  .directive('outer', function() {
    return {
      restrict: 'E',
      transclude: true,
      scope: {},
      templateUrl: '...', // or template
      controllerAs: 'outer',
      bindToController: true,  // This bind the scope with the controller object
      controller: function(scope, element, attrs) {
      }
    }
  })
  .directive('inner', function() {
    return {
      require: '^outer',
      restrict: 'E',
      transclude: true,
      scope: {
        title: '@'
      },
      controllerAs: 'inner',
      bindToController: true,  // This bind the scope with the controller object
      templateUrl: '...', // or template
      controller: function(scope, element, attrs, tabsCtrl) {
        // tabsCtrl and all the methods on the outer directive
      },
    };
});

2) You have set controller: controller and controller is a empty function, but you can set there a function like i did before and make sure of put the bindToController: true

I found the solution going step down (up ?) with the abstraction. I'm dynamically constructing the whole directive configuration object and then lazy registering it.

See http://plnkr.co/edit/pMsgop6u51zPLqkfWaWT

angular.module('app', ['moduleLazyLoader'])

.controller('mainCtrl', ['$log', function ($log) {
this.list = [
  {
    name: 'asd',
    ctrl: [
      'ItemAsdCtrl',
      function () {
        $log.debug('ItemAsdCtrl');
      }
    ]
  },
  {
    name: 'xyz',
    ctrl: [
      'ItemXyzCtrl',
      function () {
        $log.debug('ItemXyzCtrl');
      }
    ]
  }
];
}])

.directive('outer', ['factoryLazyLoader', '$log', '$compile', function (factoryLazyLoader, $log, $compile) {

function controller () {}

return {
  restrict: 'E',
  controller: controller,
  controllerAs: 'outer',
  bindToController: true,
  scope: {
    list: '=list'
  },
  link: function (scope, element, attributes) {
    var directives = [];

    scope.outer.list = scope.outer.list.map(function (ele, idx) {

      var directiveSuffix = ele.ctrl[0];

        directiveSuffix[0].toUpperCase();

      var directiveName = 'item' + directiveSuffix,
        directiveAttrName = directiveName.split(/(?=[A-Z])/).join("-").toLowerCase();

      directives.push(directiveAttrName);

      factoryLazyLoader.registerDirective([
        directiveName,
        function () {
          return {
            restrict: 'E',
            replace: true,
            controller: ele.ctrl[1],
            controllerAs: ele.ctrl[0],
            bindToController: true,
            template: '<div>{{' + ele.ctrl[0] + ' | json}}</div>',
            scope: {
              item: '=item'
            }
          }
        }
      ])

      return ele;
    });

    var tpl = '<div>';

    angular.forEach(directives, function (val, idx) {
      tpl += '<' + val +' item="outer.list[' + idx + ']">' + '</' + val  + '>';
    });

    tpl += '</div>'

    // debugger;

    element.replaceWith($compile(tpl)(scope))


  }
};
}])

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