...">

Best practice for animating multiple ui views as one

I have an application that basically looks like

<div ui-view="header"> <div ui-view="main"> <div ui-view="footer"> 

Now the footer will remain unchanged for all the different states of the application, but the header will change in some states, but will also share content in many states. The only ui-view that will change in all states will be ui-view="main" .

Currently, my $stateProvider looks like this (footer not yet implemented):

 app.config(['$stateProvider', '$urlRouterProvider', function($stateProvider, $urlRouterProvider) { $stateProvider.state('root',{ url: '', abstract: true, views: { 'header': { templateUrl: appHelper.views+'/header.html', }, } }) .state('root.home', { url: '/', views: { 'header': { templateUrl: appHelper.views+'/header.html', }, 'main@': { templateUrl: appHelper.views+'/home.html', controller: 'HomeController as homeVm', } }, resolve: { posts: function(dataService) { return dataService.getPosts(); }, artists: function(dataService) { return dataService.getArtists(); } } }) .state('root.artist', { url: '/artist/:slug', views: { 'header@': { templateUrl: appHelper.views+'/artistHeader.html', controller: 'ArtistController as artistVm', }, 'main@': { templateUrl: appHelper.views+'/artist.html', controller: 'ArtistController as artistVm', } }, resolve: { artist: function($stateParams, dataService) { return dataService.getArtist($stateParams.slug); } } }); }]); 

So far so good. But here is the catch. During transitions, I want to animate all the ui-view as one. To make everything look cohesive in my case (its an attenuation animation), I would like to put them in a div wrapper and have the div do the attenuation / attenuation (doing this on each of the different ui-view views will cause all kinds of deformities).

What is the best practice in this scenario?

I wrap them in ui-view and somehow connect it to $stateProvider (nested ui-view s?). Are there any other ways to do this? Can I listen to $stateChange and apply classes to my wrapper like ngAnimate with ui-view ? (fade and then wait until it disappears completely with a successful solution before fading out).

From my Google search efforts, it seems that ui-view is very preferable when handling transition type animations.

+8
angularjs transition angular-ui-router ng-animate
source share
1 answer

... During transitions, I want to animate all ui-views as one. To make things look cohesive in my case (its an attenuation animation), I would like to put them in a wrapper div and have that div do an attenuation / fade in (doing this on every different ui-view causes all kinds of uglyness).

What is the best practice in this scenario?

Option 1: Using the $stateChangeStart and $stateChangeSuccess

This approach will have some side effects, as mentioned in the comments of @David. Therefore, avoid this until the ui-router offers the best way to manage state transition promises. It currently relies on event.preventDefault() to prevent the transition.

Basically, ui-router will start your view of ui-view route changes at the same time as the inbound view. So what you get is the previous ui-view , which is still displayed while the next ui-view is being displayed, and if you are animating the view, then there will be such a transition time between the old view and the new one. You should think about rendering the new ui representation until the old one finishes the animation (before reviving the new one)

For similar reasons, moving them to another ui-view and connecting them to $stateProvider would not be reasonable.

Option 2: (recommended) CSS based animations

I mainly use CSS based transitions and you can achieve this either

  • Assigning a common CSS class to each ui-view and applying animation in this class.
  • or inclusion of three ui-view in a <div> (if you really need it) and apply animation to it.

In any case, you will consider all ui-views as a single entity, and revitalizing them will make things more cohesive.

HTML:

 <div ui-view="header" ></div> <div ui-view="main" ></div> <div ui-view="footer" ></div> 

CSS

 [ui-view].ng-enter { animation: fadein 2s; } @keyframes fadein { from { opacity: 0; } to { opacity: 1; } } 

Here plunkr works based on your use case where I have an abstract root state and three sub-states root.home , root.artist and root.band . As long as ui-view='main' changes in all states, ui-view='footer' does not change in any and ui-view='header' changes for the state "root.artist". The fact that you use the css .ng-enter and .ng-leave classes to start the animation, you technically overcome the problems with the previous approach.

  $stateProvider .state('root',{ abstract:true, views:{ 'header':{ //absolutely targets the 'header' view in root unnamed state. templateUrl:'header.html' }, 'footer':{ //absolutely targets the 'footer' view in root unnamed state. templateUrl:'footer.html' } } }) .state('root.home',{ views:{ 'main@':{ templateUrl:'main.html' }, } }) .state('root.artist',{ views:{ 'header@':{ templateUrl:'artist-header.html' }, 'main@':{ templateUrl:'artist-main.html' }, } }) .state('root.band',{ views:{ 'main@':{ templateUrl:'band-main.html' }, } }) 
+2
source share

All Articles