9

I have an angular app with a powerpoint-like interface.

The left items (scrollable <div>) are parts of a controller called with a ui-sref, the slide content is from another (child) controller and is updated with an ng-show.

Illustration of the powerpoint-like interface

If I click on an item (on the left of the picture), the slide content (on the right) changes dynamically. The problem is that the scrollable view always scrolls to the top when an item is clicked.

I have tried many approaches described on SO, but nothing works:

  • set the attribute autoscroll to false on the ui-view
  • myModule.value('$anchorScroll', angular.noop);
  • myModule.run(['$anchorScroll', function($anchorScroll) { $anchorScroll = angular.noop; }]);
  • $anchorScrollProvider.disableAutoScrolling();

Edit/ here the attributes of all links tags:

ui-sref="{{linkquestion}}" 
ng-repeat="question in questionnaire.Question | orderBy: 'numero' | filter:{statut: false}" 
ng-mouseenter="options = true" 
ng-mouseleave="options = false"

Anyone have an idea?

scniro
  • 16,844
  • 8
  • 62
  • 106
Gautier Drusch
  • 701
  • 5
  • 16
  • 4
    I think that the easiest and most correct will be to use UI-Router's **Nested States & Views** https://github.com/angular-ui/ui-router#nested-states--views and sidebar is one view, and main is second, distinguished by `ui-sref` element id in sidebar's main loop – Rafal Lesniak Oct 08 '15 at 16:57
  • 2
    unfortunately, the screenshot doesn't demonstrate the issue well enough on it's own to provide a full answer. Please provide a [mcve] of the issue. – Claies Oct 10 '15 at 17:46
  • could you provide fiddle? – Farzad Yousefzadeh Oct 10 '15 at 17:51
  • Rafal is pb right. If you are reloading 'slide dynamic' portion of the dom the scroll shouldn't reset once you click an item. If that happens maybe another angular cycle iterates through items ui-srefs for some internal purpose. I would suggest wrapping the left side in another div which would be isolated from the angular refresh – victor Oct 11 '15 at 09:21
  • Could you please post your full anchor tags? – Tiago Oct 11 '15 at 11:50
  • The update you posted is still not providing a complete picture of the structure of your application. This is still not something that others can test, verify, or change code for to provide a solution. – Claies Oct 12 '15 at 14:27
  • I also adhere to @RafalLesniak answer (comment). Behaviors like the one you are designing for are what nested states & views were created for. They are very convoluted to do without, so you'd do better if you try his approach. – Giuseppe Oct 12 '15 at 17:48
  • Are you using `ui-view` on the right side or just using `ng-show` to hide or display specific slide? – Shashank Agrawal Oct 13 '15 at 07:16
  • Shashank, I only use ng-show – Gautier Drusch Oct 13 '15 at 08:33
  • @GautierDrusch As people stated before the reason for a "basic" jsfidle, jsbin is to look into your js code, maybe to test own "solutions". Just to understand are you using angular ui-router or not as ui-router has "autoScroll" option and angularjs has "anchorScroll"? if Not, did you tried to DI $anchorScroll into your controller and maybe make a $watch to it to handle possible changes ? – Fer To Oct 14 '15 at 14:19
  • @GautierDrusch has my answer come close to what you are trying to achieve? Please share some feedback when you can – scniro Oct 14 '15 at 16:05

1 Answers1

4

I'm not totally sure what you are attempting with $anchorScroll, but as comments suggest, leveraging ui-router with ui-view is likely what you are wanting to use instead of an ng-show. Also, it's a bit difficult to completely dissect your example and guide you in the correct direction without sample code or a somewhat working example as a baseline. However, from your diagram, I have at least an idea of what you are after - so I've made a best guess.

I encourage you to scrap using ng-show and reconsider your markup in favor of leveraging ui-view. I have crafted an example that is similar to your concept, and I can dynamically change state and display content without a scroll jump. Observe the following complete working example...

<section class="container">
    <aside>
        <a ng-repeat="n in nav" ui-sref="{{ n.state }}">state: {{ n.state }}</a>
    </aside>
    <div ui-view></div>
</section>

angular.module('app', ['ui.router'])
.config(['$stateProvider', function($stateProvider) {
    $stateProvider
        .state('a', { template: '<span>a</span>' })
        .state('b', { template: '<span>b</span>' })
        .state('c', { template: '<span>c</span>' })
        .state('d', { template: '<span>d</span>' })
        .state('e', { template: '<span>e</span>' })
        .state('f', { template: '<span>f</span>' })
        .state('g', { template: '<span>g</span>' })
        .state('h', { template: '<span>h</span>' })
        .state('i', { template: '<span>i</span>' })
        .state('j', { template: '<span>j</span>' })
        .state('k', { template: '<span>k</span>' })
        .state('l', { template: '<span>k</span>' });
}])
.controller('ctrl', ['$scope', function($scope) {
    $scope.nav = [
        {'state': 'a' }, {'state': 'b' }, {'state': 'c' },
        {'state': 'd' }, {'state': 'e' }, {'state': 'f' },
        {'state': 'g' }, {'state': 'h' }, {'state': 'i' },
        {'state': 'j' }, {'state': 'k' }, {'state': 'l' }
    ];
}]);

Excuse my total simplicity for states and content - this is just to demonstate. But, you'll be able to see the behavior in the working example and can hopefully mold this foundation into your working copy.

JSFiddle Link - working demo

As always, be sure to check out the ui-router docs for more information.


Per your comment, this may be a slightly more dynamic way to do this. In this, I am just defining one state that is parameterized and subscribing to the $stateChangeSuccess event - giving me an opportunity to populate scope variables based on a passed $stateParam - perhaps via an ajax call.

Please remember - the dynamic nature of this will vary greatly with what your are trying to do. There are ways to leverage child and nested states, there are ways to add dynamic states - really - you can get get as dynamic as you wish here. Most importantly, leveraging ui-view as intended in the following examples resolves the scroll issue. Observe the following, possibly dynamic, possibly favorable example...

<section class="container">
    <aside>
        <a ng-repeat="n in nav" ui-sref="slide({'id': n.slide })">state: {{ n.slide }}</a>
    </aside>
    <div ui-view><span>dynamic content</span></div>
</section>

.config(['$stateProvider', function($stateProvider) {
    $stateProvider
        .state('slide', { url: 'slide/:id', template: '<span>{{ content }}</span>' })
}])
.controller('ctrl', ['$scope', function($scope) {
    $scope.nav = [
        {'slide': 'a' }, {'slide': 'b' }, {'slide': 'c' },
        {'slide': 'd' }, {'slide': 'e' }, {'slide': 'f' },
        {'slide': 'g' }, {'slide': 'h' }, {'slide': 'i' },
        {'slide': 'j' }, {'slide': 'k' }, {'slide': 'l' }
    ];

    $scope.$on('$stateChangeSuccess', function(event, toState, toParams, fromState, fromParams) { 
        // - just to demo
        // - use this param to get dynamic content 
        // - then populate scope variables in template
        $scope.content = toParams.id;
    });
}]);

JSFiddle Link - a bit more dynamic demo

Community
  • 1
  • 1
scniro
  • 16,844
  • 8
  • 62
  • 106
  • Your solution works well but the states of my app are fully dynamic (coming from a server). Is it possible to use $stateProvider dynamically ? For now, I ended with $scope.$emit and $scope.$broadcast. – Gautier Drusch Oct 17 '15 at 07:15