Angular ui-router - 将布局的一部分暴露给子状态/模板

时间:2014-04-14 23:18:18

标签: angularjs angular-ui-router

以下面的模型截图为例,我需要能够在视图的右上角放置一些自定义操作。用户看到的内容取决于当前显示的视图(例如分享按钮)。

我正在使用ui-router和嵌套状态。我可能接近错了,所以我的问题更具有通用性而非具体。将部分布局暴露给可能是几层深的儿童state的最佳方法是什么?

<div>
   <header id="menu">
      <a class="fa fa-bars"></a>

      <div>Title</div>

      <div class="actions">
         <!-- I want a child state, possibly multiple levels deep in the 
              state hierarchy, to be able to insert content here -->
      </div>
   </header>

   <div id="content">
      <div ui-view></div>
   </div>
</div>

mockup

1 个答案:

答案 0 :(得分:0)

我可以看到几种方法,选择一种最适合你的方法:

1)actions视图可以作为监视$state.current的指令实现,并根据当前状态,相应地更新其视图。如果您希望每个州的能力能够指定自己的行为,那么可能在使用data时设置$stateProvider.state属性,并使用该信息来确定哪些行为可以起作用。

2)实现某种交叉转换指令。所以这样的事情(未经测试但未完全实现,请务必测试内存泄漏):

angular.module('app',[]).directive('crossTransclude', function(){
    return {
        require : '^crossTranscludeController',
        transclude: true,
        link: function($scope, $el, $attr, ctrl, transclude){
            ctrl.setTranscludeFn(transclude);
            $scope.$on('$destroy', function(){
              ctrl.unsetTranscludeFn(transclude);
            });
        }
    };
})
.directive('crossTranscludeController', function(){
  return {
    controller : function CrossTranscludeController(){
      this.transcludeFn = null;
      this.transcludeTargetEl = null;
      this.setTranscludeFn = function(func){
        this.transcludeFn = func;
        this._crossTransclude();
      }

      this.unsetTranscludeFn = function(){
        this.transcludeFn = null;
        this._crossTransclude();
      }

      this.registerTranscludeTarget = function($element){
        this.transcludeTargetEl = $element;
        this._crossTransclude();
      }

      this.deregisterTranscludeTarget = function(){
        this.transcludeTargetEl = null;
        this._crossTransclude();
      }

      this._crossTransclude = function(){
        if(this.transcludedClone)
        if(this.transcludeFn && this.transcludeTargetEl){
          this.transcludeFn(function(clone){
            this.transcludeTargetEl.empty();
            this.transcludeTargetEl.append(clone);
          });
        } else {
          if(this.transcludeTargetEl){
            this.transcludeTargetEl.empty();
          }
        }
      }
    }
  };
})
.directive('crossTranscludeTarget', function(){
  return {
    require: '^crossTranscludeController',
    link: function($scope, $el, $attr, ctrl){
      ctrl.registerTranscludeTarget($el);
      $scope.$on('$destroy', function(){
        ctrl.deregisterTranscludeTarget();
      });
    }
  };
});

使用方法如下:

的index.html

<div cross-transclude-controller>
    <div cross-transclude-target>

    </div>


    <div ui-view>

    </div>
</div>

subview.html

<div>
    <div cross-transclude>
        This content should end up in 'cross-transclude-target', bound to the subview's scope
    </div>
</div>