如何在角度设置不同的控制器中的不同菜单

时间:2013-05-12 10:53:20

标签: angularjs

我的应用程序中有顶级菜单,我希望根据控制器有不同的内容。在Rails中使用content_for很容易,但是如何用角度来实现呢?我已经知道这个解决方案了:AngularJS: How can I pass variables between controllers?但也许有更好的方法可以做到这一点?

4 个答案:

答案 0 :(得分:2)

Angular的一个有趣的事情是,如果不了解应用程序的上下文,通常没有“更好的方法”。有“其他”方式,最好的取决于它们。我想更多信息也可能有助于定制或推荐特定答案。

然而,这是关于这个主题的思考:

第一个想法

更多定义的服务

你找到的答案并不坏,虽然我可能会更进一步,并有一些'菜单服务',而不是一个高度通用的'财产'商店。这个菜单服务可以由ng-view实例化的控制器操纵。

通过路线映射

更进一步,可以在路由提供程序声明中包含菜单信息,然后在$routeChangeSuccess$routeChangeStart上让菜单控制器根据路由中的数据自行更新(也许维护服务,以便控制器可以提供“特殊”菜单选项,从而允许一定程度的定制。)

更多选项

如果共享服务(一个Angular最佳实践,fyi)不符合您的喜好或设置并且没有使用路由,那么(可能很棘手)那么我可以看到更多选项:

$rootScope

一个是注入$rootScope(所有范围的伟大的祖父),并在那里有一个集合,这是你的菜单项;然后每个控制器可以手动更新。

自定义活动

这里$rootScope.$emit()是你的朋友 - 你可以发出某种事件和供应菜单配置数据。然后控制器将监听($rootScope.$on())事件并使用新发出的菜单列表更新/清除/替换它自己的菜单项列表。

高级路由

变得更加有趣,您甚至可以尝试查看路线的resolve部分中是否包含函数。

<强>参考

有关使用示波器的信息,请参阅Angular的文档:http://docs.angularjs.org/api/ng。$ rootScope.Scope

复杂路由的信息在这里:http://www.yearofmoo.com/2012/10/more-angularjs-magic-to-supercharge-your-webapp.html#additional-features-of-controllers-and-routes(yearofmoo是Rails粉丝,所以他们的意见可能与您自己的意见相符)

答案 1 :(得分:1)

对于类似的任务,我写了一个模仿rails content_for

的角度js指令

抱歉CoffeeScript:

App.directive "contentFor", ["$sce", ($sce) ->
  compile: (e, attrs, transclude) ->
    pre: (scope, iElement, iAttrs, controller) ->
      varname = iAttrs["contentFor"]

      # Looks for the closest scope where 'varname' is defined 
      # or pick the top one
      targetScope = scope
      while targetScope.$parent
        if ( if targetScope.hasOwnProperty then targetScope.hasOwnProperty(varname) else targetScope[varname] )
          break
        else
          targetScope = targetScope.$parent

      # Store html inside varname
      html = iElement.html()
      targetScope[varname] = $sce.trustAsHtml(html)

      # remove the directive element
      iElement.remove()
]

您可以像这样使用

<span content-for="menuHtml">
  <ul>
     <li>Menu Item 1</li>
     <li>Menu Item 2</li>
     <li>Menu Item 3</li>
  </ul>
</span>

这相当于<%= yield(:menuHtml) %>

<nav ng-bind-html="menuHtml"></nav>

最后,您可以将菜单重置为控制器中$routeChangeSuccess事件的默认绑定:

$scope.$on '$routeChangeSuccess', ->
  $scope.menuHtml = $sce.trustAsHtml("<ul>...</ul>")

答案 2 :(得分:0)

将顶级菜单绑定到顶级范围内的对象。在该控制器中创建一个方法来设置该变量。在您的子控制器中调用该方法来设置适当的变量,该变量将根据您的控制器更改菜单。

如果菜单项不是来自服务器,您可以利用services存储菜单项。

答案 3 :(得分:0)

我认为直接引用将被替换的div而不是像mcasimir的答案那样使用angular的范围更加简单。此外,它还有一个额外的好处,即允许angular编译指令,在另一个答案中会给你一个“不可信”的错误。这是指令的样子:

.directive('appContentFor', ($compile) -> {
  replace: true,
  compile: (element,attr,transclude)->
    return (scope, element, attrs)->
      element.remove()
      node = $(attrs.node)
      $(node[0]).replaceWith($compile(element.html())(scope))})

通过注入$ compile service angular可以在html上执行它的工作,然后将其插入到它所属的位置。现在您可以像这样使用此指令:

<div app-content-for node="div#awesomeContentFor">
  <ul id="awesome_inserted_list">
    <li>{{1+2}}</li>
    <li>{{something_on_current_scope}}</li>
  </ul>
</div>

然后在其他地方添加id为awesomeContentFor的div:

<div id="awesomecontentfor"></div>