AngularJS / ui-bootstrap accordion - scroll up to the active (open) accordion when pressed

When the panel is open, I need it to move back to the ".panel-title" of the one that was just clicked. I know that I can create a directive for this, for example (I got it 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 HTML I had to use:

 <div uib-accordion-group is-open="status.openPanel" scroll-top></div> 

But this does not seem to work. When you click on the second panel, it opens the first and second panel and never scrolls at the top when you open the third.

I just need to scroll back to the ".panel-title" panel on which the button was clicked. I think it’s pretty funny that it seems so hard to do when a lot of time for the contents of the panel can drag on for quite some time, and I think most people will want to scroll the top of the information when opening the panel.

I saw other posts here, but they don't seem to be related to AngularJS. I am using "ui-bootstrap-tpls-2.1.3"

EDIT - Here is a plunger you can play with if you want.

Any help is greatly appreciated.

+6
source share
1 answer

it may be a quick and dirty method, but it works flawlessly

 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.imtqy.com/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> 
+1
source

All Articles