AngularJS / ui-bootstrap 手风琴 - 单击时滚动到活动(打开)手风琴的顶部
Posted
技术标签:
【中文标题】AngularJS / ui-bootstrap 手风琴 - 单击时滚动到活动(打开)手风琴的顶部【英文标题】:AngularJS / ui-bootstrap accordion - scroll to top of active (open) accordion on click 【发布时间】:2017-01-02 07:28:01 【问题描述】:当一个面板打开时,我需要让它回滚到刚刚被点击的那个的“.panel-title”。我知道我可以创建一个指令来执行此操作,例如(从this site 获取):
.directive( 'scrollTop', scrollTop );
function scrollTop()
return
restrict: 'A',
link: link
;
function link( $scope, element )
$scope.collapsing = false;
$scope.$watch( function()
return $(element).find( '.panel-collapse' ).hasClass( 'collapsing' );
, function( status )
if ( $scope.collapsing && !status )
if ( $(element).hasClass( 'panel-open' ) )
$( 'html,body' ).animate(
scrollTop: $(element).offset().top - 20
, 500 );
$scope.collapsing = status;
);
在我应该使用的 HTML 中:
<div uib-accordion-group is-open="status.openPanel" scroll-top></div>
但这似乎不起作用。当您单击第二个面板时,它会打开第一个和第二个面板,并且在打开第三个面板时它甚至不会滚动到顶部。
我只需要它滚动回被点击的面板的“.panel-title”。我认为这很荒谬,因为很多时候面板内容可能会变得很长,而且我认为大多数人都希望在打开面板时滚动到信息的顶部。
我在这里看到了其他帖子,但他们似乎没有与 AngularJS 打交道。我正在使用“ ui-bootstrap-tpls-2.1.3 ”
编辑 - Here is a Plunker 如果您愿意,可以使用。
非常感谢任何帮助。
【问题讨论】:
您是否考虑过监听shown
和hidden
事件而不是使用您的观察者?我怀疑你的守望者开火太早了。在您的函数上设置断点(或在其中放置警报或控制台日志,或将引导动画速度编辑为慢得多以夸大时间)。报告您的发现。
【参考方案1】:
这可能是一种快速而肮脏的方法,但完美无缺
angular.module('ui.bootstrap.demo', ['ngAnimate', 'ui.bootstrap'])
.controller('AccordionDemoCtrl', function($scope)
$scope.oneAtATime = true;
$scope.groups = [
title: 'Dynamic Group Header - 1',
content: 'Dynamic Group Body - 1'
,
title: 'Dynamic Group Header - 2',
content: 'Dynamic Group Body - 2 Dynamic Group Header - 2 Dynamic Group Header - 2 Dynamic Group Header - 2 Dynamic Group Header - 2 Dynamic Group Header - 2'
];
$scope.items = ['Item 1', 'Item 2', 'Item 3'];
$scope.addItem = function()
var newItemNo = $scope.items.length + 1;
$scope.items.push('Item ' + newItemNo);
;
$scope.status =
isFirstOpen: true,
isFirstDisabled: false
;
//scrolling
var accordion = $('.accordion'), timeOut;
accordion.on('click', '.panel-heading', function(e)
if(e.target.nodeName != 'SPAN') return;
var element = this;
clearTimeout(timeOut);
//since we dont know the exact offsetTop for dynamic content
//using timeout 350 which let angular complete its render
timeOut = setTimeout(function()
accordion.animate(
scrollTop: element.offsetTop -2
, 300);
, 350);
);
);
.accordion
max-height: 220px;
overflow: auto;
padding: 2px; 8px 0 0;
*:focus outline: none !important;
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0/jquery.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.6/angular.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.6/angular-animate.js"></script>
<script src="https://angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.14.0.js"></script>
<link href="https://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet">
<div ng-app="ui.bootstrap.demo">
<div ng-controller="AccordionDemoCtrl">
<script type="text/ng-template" id="group-template.html">
<div class="panel panelClass || 'panel-default'">
<div class="panel-heading">
<h4 class="panel-title" style="color:#fa39c3">
<a href tabindex="0" class="accordion-toggle" ng-click="toggleOpen()" uib-accordion-transclude="heading"><span
ng-class="'text-muted': isDisabled">heading</span></a>
</h4>
</div>
<div class="panel-collapse collapse" uib-collapse="!isOpen">
<div class="panel-body" style="text-align: right" ng-transclude></div>
</div>
</div>
</script>
<div class="accordion">
<uib-accordion close-others="oneAtATime">
<uib-accordion-group heading="Static Header, initially expanded" is-open="status.isFirstOpen" is-disabled="status.isFirstDisabled">
This content is straight in the template.
</uib-accordion-group>
<uib-accordion-group heading="group.title" ng-repeat="group in groups">
group.content
</uib-accordion-group>
<uib-accordion-group heading="Dynamic Body Content">
<p>The body of the uib-accordion group grows to fit the contents</p>
<button type="button" class="btn btn-default btn-sm" ng-click="addItem()">Add Item</button>
<div ng-repeat="item in items">item</div>
</uib-accordion-group>
<uib-accordion-group heading="Custom template" template-url="group-template.html">
Hello
</uib-accordion-group>
<uib-accordion-group heading="Delete account" panel-class="panel-danger">
<p>Please, to delete your account, click the button below</p>
<p>Please, to delete your account, click the button below</p>
<p>Please, to delete your account, click the button below</p>
<button class="btn btn-danger">Delete</button>
</uib-accordion-group>
<uib-accordion-group is-open="status.open">
<uib-accordion-heading>
I can have markup, too! <i class="pull-right glyphicon" ng-class="'glyphicon-chevron-down': status.open, 'glyphicon-chevron-right': !status.open"></i>
</uib-accordion-heading>
This is just some content to illustrate fancy headings.
</uib-accordion-group>
</uib-accordion>
</div>
</div>
</div>
【讨论】:
这对我不起作用,但我的元素布局不同。就像我上面说的,我使用的是“ui-bootstrap-tpls-2.1.3”,这个例子使用的是“ui-bootstrap-tpls-0.14.0.js”,我不是100%肯定会有所不同,但它可能会有所不同。无论哪种方式,脚本都不会超过“ if(e.target.nodeName != 'SPAN') return; ” 我在原帖中添加了一个plunker链接-plnkr.co/edit/etdG2OjUi8GxgUywSpvf?p=preview 例如,我使用了$('.accordion')
,在您的情况下它应该是$('body')
。更新Plunker
是的,这仍然不适合我。它到达 body.animate 但不运行“ scrollTop: element.offsetTop -2 ”,因为如果我将其更改为 body.animate(opacity: 0, 300);它将整个身体淡化为 0 不透明度。所以我知道它正在运行动画部分。即使我将其更改为 body.animate(scrollTop: '100px', 300);甚至“ scrollTop:0 ”什么都不会向上滚动。
我通过从我的 CSS 文件中的 body 和 html 元素中删除 height: 100% 来完成这项工作。以上是关于AngularJS / ui-bootstrap 手风琴 - 单击时滚动到活动(打开)手风琴的顶部的主要内容,如果未能解决你的问题,请参考以下文章
如何为 ui-bootstrap 日期选择器创建 angularJs 包装器指令?
AngularJs的UI组件ui-Bootstrap分享——Datepicker Popup
使用 ui-bootstrap 显示在右上角的警报,使用 Angularjs 进行引导
AngularJs的UI组件ui-Bootstrap分享——Datepicker Popup