我来自JQuery,而我在AngularJs的第一步让我有点困惑......
我的情况:
我有一个用css(顶部:-50px)隐藏的面板(#floatingpanel),在视口之外。
我有一个链接(a.trigger),在我的应用程序的最深处,当你点击该链接时,"顶部"我小组的财产来自" -50px"到" 0px"使其可见(您单击以切换可见性)。
该面板就在我页面主容器的这一端,但是它在数百个其他div
中的链接。
让我们看一下DOM结构:
<body>
<div class="main-wrapper" ng-app="myapp">
<div class="app">
<div class="many-things">
[...]
<a href="#" class="trigger" ng-click="toggleMyPanelVisibility()">
Click here to see the panel
</a>
[...]
</div>
</div><!-- .app -->
<div id="floatingpanel">
Hey ! I was hidden !
</div>
</div> <!-- #mainwrapper -->
</body>
在jQuery中,它将是:
$('a.trigger').click( function(e) {
e.preventDefault();
var el = $('#floatingpanel');
var top = el.css('top');
if (top<0) el.css('top', 0);
else el.css('top', -50);
});
容易! ;-)
如何使用AngularJs制作它?
我会这样做:
var app = angular.module('myapp');
app.run(["$rootScope", function($rootScope) {
// Toggle du myaccountpanel
$rootScope.floatingpanelVisibility = false;
$rootScope.toggleMyPanelVisibility = function() {
$rootScope.floatingpanelVisibility = !$rootScope.floatingpanelVisibility;
var panel = angular.element( $('#floatingpanel') );
var top = -50;
if ($rootScope.floatingpanelVisibility)
top = 0;
panel.css({'top': top });
}
});
好吧,它有效但是...我想如果我继续这样做,我的app.run
会很快超载,不是吗?
我也可以用我的&#34; main-wrapper&#34;上的控制器来做到这一点。但它很愚蠢,它已经是我的应用范围!
如何使用指令执行此操作?
什么是最好的方式&#34;解决这个烂摊子?
感谢您的帮助!
答案 0 :(得分:2)
我在Angular中看到的两种最常见的方法是通过rootscope消息传递或通过服务。这项服务是两者中更清洁/更好的服务。
接受的答案假设所有内容都在同一个控制器下,并且这显然不是构建OP所描述内容的方式。
想象一个由一堆小部件组成的页面 - 子视图或指令,全部由他们自己的独立控制器处理。这是处理OP在Angular中描述为“所有东西”的正确方法。
现在,您需要一种方法来触发一个可由任何其他人响应的事件。如果您定义一个服务,比如,“pageEventService”公开一个函数来启动/触发事件“togglePanel”,以及一个保存状态的属性 - “panelIsVisible”,您可以在任何需要触发的地方引用该服务事件,并在小组中引用它以响应该值。
.controller('SomeControllerThatCanTriggerEvent', function(pageEventService) {
var model = this;
model.togglePanel = pageEventService.togglePanel;
});
由此控制器控制的标记中的某处...
<a ng-click="model.togglePanel()">Toggle the Panel</a>
Panel控制器中的......
.controller('PanelController', function(pageEventService) {
var model = this;
model.panelIsVisible = pageEventService.panelIsVisible;
});
并在面板标记中......
<div id="TheAlmightyPanel" ng-show="model.panelIsVisible">... cool stuff here ...</div>
这比rootscope消息传递更干净,因为您可以明确指出pageEventService可以执行的操作以及有谁引用它。您可以在视图,子视图和指令中使用它 - 无论您需要它。
答案 1 :(得分:1)
你正在做的事情可以在不触及DOM的情况下完成,使用内置的角度指令本身,这里我只是使用ng-show
指令,如果你想把特定的类放到它,那么只需使用{{3}同样,任何动画都可以作为css动画提供,并且通过包含ngAnimate
模块,您可以更好地使用添加的类名来提供ng-class
行为。
实施例: -
<div class="main-wrapper" ng-app="myapp">
<div ng-controller="panelController as panel">
<a href="#" class="trigger" ng-click="panel.toggle($event)">Click here to see the panel</a>
<div ng-show="panel.show" class='panel'>
<!-- <div ng-class="{'show':panel.show}"> and define css rules for panel.show-->
Hey ! I was hidden !
</div>
</div>
</div>
在控制器panelController
angular.module('app').controller('panelController', function($scope){
var vm = this;
vm.show = false;
this.toggle = function($event){
$event.preventDefault();
vm.show = !vm.show;
}
});
我在这里只是使用控制器As语法,你可以使用$ scope,如果你愿意,你甚至可以将它转换为指令。
根据您的问题更新进行修改:
创建一个控制器并使用内置的角度指令并没有什么不好的,当你需要时,而不是在你真的不需要时使用jquery / manual dom操作。
<body>
<div class="main-wrapper" ng-app="myapp" ng-controller="mainController as main">
<div class="app">
<div class="many-things">
[...]
<a href="#" class="trigger" ng-click="main.togglePanel($event)">Click here to see the panel</a>
[...]
</div>
</div><!-- .app -->
<div id="floatingpanel" ng-show="panel.show">
Hey ! I was hidden !
</div>
</div> <!-- #mainwrapper -->
</body>
这可能是你的错误答案,因为你似乎在考虑不创建控制器或重新设计你的观点。
.directive('togglePanel', function(jQuery){
return {
restrict: 'A',
link:function(scope, elm, attr){
elm.on('click', handleToggle);
scope.$on('$destroy', function(){
elm.off('click', handleToggle);
});
function handleToggle(e){
var $target = jQuery(attr.togglePanel);//Get the target
//Do what you want to do with the target
}
}
}
}).constant('jQuery', window.jQuery);
并将其用作:
<a href="#" class="trigger" toggle-panel="#floatingPanel">Click here to see the panel</a>
答案 2 :(得分:0)
好的!感谢@PSL,我已经明白,如果我在ng-app元素上设置控制器,这不是问题。
<div class="main-wrapper" ng-app="myapp" ng-controller="mainController as main">
我认为这是一种不好的做法......
有了#34; mainController&#34;我可以轻松地与我的2个元素进行互动:通过ng-click
链接,通过ng-class
(或ng-show
等)与面板进行互动
我看不出更好的方法。如果我避免这个&#34; mainController&#34;我可以制定一个指令但是触摸我的面板会迫使我访问范围之外的DOM ...
我必须将我的思维从jquery方式转变为有角度的方式(this link can help)。