transclude:'element'和templateUrl,它可行吗?

时间:2014-04-13 04:49:18

标签: angularjs angularjs-directive

我有一个指令,它将元素放在一个独立的作用域上并对它应用一个控制器,因此它可以处理状态,AJAX调用和验证。

<div login> 
  <div class="dropdown" ng-click="loginctrl.showForm()">
    Login <span class="caret"></span>
  </div>
</div>

当前被转换的元素变为:

<!-- login -->
<div class="login">
  <div class="dropdown" ng-click="loginctrl.showForm()">
    Login <span class="caret"></span>
  </div>
</div>

但是我有一个templateUrl我想要附加指令的内容,所以我使用transclude: 'element'来细化转换:

angular
.module('Login.module', [])
.controller('LoginCtrl', function(){
  this.login = function(){
     // do ajax calls for login
  };

  this.logout = function(){ 
     // do ajax calls for logout
  };

  this.facebook = function(){  
    // do ajax calls for facebook login
  };

  this.showForm = function(){
     // shows the template form
  };

  this.user = {}; // user model
})
.directive('login', function(){
  return {
    restrict: 'A',
    transclude: 'element',
    controllerAs: 'loginctrl',
    controller: 'LoginCtrl',
    replace: false,
    templateUrl: '/templates/login',
    link: function(scope, element, attrs, ctrl, transclude){
      transclude(scope, function(clone){
        clone.wrap('<div class="login"></div>');
        element.after(clone); // "element" is the <!-- login --> HTML comment
        // "clone" is the transcluded contents of the div, that is the login with ng-click, etc
      });
    }
  }
});

templateUrl(即登录/注册表单)是通过AJAX下载的(在开发工具中查看),但它不能在链接函数内部使用,也不能在转换中使用。我错过了什么吗?在这方面找不到任何帮助,我现在已经找了几天。

问题http://plnkr.co/edit/NzS7cAej17RnQxARlli3?p=preview

的版本坍塌了

1 个答案:

答案 0 :(得分:6)

评论后编辑:

我已使用以下内容更新this plnkr,我认为这样做符合您的要求。我已经对正在发生的事情做了一些补充说明。

.directive('login', function() {
  var useElementTransclusion = true;
  var replace = true;
  return {
    restrict: 'A',
    transclude: useElementTransclusion ? 'element' : true,
    controllerAs: 'loginctrl',
    controller: 'LoginCtrl',
    replace: useElementTransclusion ? true : replace,
    templateUrl: 'login.html',
    link: function(scope, element, attrs, ctrl, transclude) {
      // If transclude is 'element', then the element argument is
      // the HTML comment which is put in the place of the entire
      // element on which the directive was applied.
      // If transclude is true, then the element argument depends
      // on the value of replace. If replace is true then element 
      // is the content of the template. If replace is false then
      // element is the element on which the directive was applied.
      transclude(scope, function(clone) {
        // If transclude is 'element' then clone is an array
        // containing the single element on which the directive
        // was applied.
        // If transclude is true then clone is an array containng
        // the children of the element on which the directive was
        // applied.
        element.wrap('<div class="login"></div>');
        element.after(clone);
      });
    }
  }
});

如果您使用transclude; 'element',则必须使用replace: true,以获得某些解释see this issue。如果您使用transclude: true,则可以使用replace所需的任何值,具体取决于您对应用该指令的原始HTML节点所需的最终结果(是否仍然存在) )。


以下是原始答案,没有特别原因留在这里......

不完全确定这是否会产生您期望的确切结果,但是......

.directive('login', function() {
  return {
    restrict: 'A',
    transclude: 'element',
    controllerAs: 'loginctrl',
    controller: 'LoginCtrl',
    replace: true,
    templateUrl: '/templates/login',
    link: function(scope, element, attrs, ctrl, transclude) {
      transclude(scope, function(clone) {
        element.after(clone);
        clone.wrap('<div class="login"></div>');
      });
    }
  };
})

this fork of your plnkr中所示。

变化是:

  • 将替换更改为'true'
  • 在包装之前将克隆添加到DOM中,以便将包装添加到DOM中。