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