问题
When a panel is opened I need to have it scroll back to the ".panel-title" of the one that was just clicked. I know that I can create a directive to do this such as (got this from 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;
} );
}
And in the HTML I was supposed to use:
<div uib-accordion-group is-open="status.openPanel" scroll-top></div>
But this does not seem to work. When you click the second panel it opens the first and second panel and it never even scrolls to the top when opening the third one.
I just need it to scroll back to the ".panel-title" of the panel that was clicked. I think it is pretty ridiculous that this seems to be so difficult to do when a lot of the time the panel content can get pretty long and I think most people would want to scroll to the top of the info when a panel is opened.
I have seen other posts on here but they don't seem to be dealing with AngularJS. I am using " ui-bootstrap-tpls-2.1.3 "
EDIT - Here is a Plunker to play with if you would like.
Any help is greatly appreciated.
回答1:
this may be a quick and dirty method, but works flawless
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>
来源:https://stackoverflow.com/questions/39152485/angularjs-ui-bootstrap-accordion-scroll-to-top-of-active-open-accordion-on