I have an ionic v1 app. I want to add a basic animation to an element when it gets added to the view via ng-repeat. Reading the docs, the element should have a ng-enter class I can use to add CSS animations but it doesn't.
ngAnimate is included with Ionic. I'm loading the module:
angular.module('app', [
'ionic',
'ngAnimate',
Here's view code which uses ng-repeat:
<div class="entry" ng-repeat="message in messages | orderBy:'-id'">{{message}}
</div>
When I dynamically add a message to $scope.messages it gets added to the view as you would expect but it does not contain the ng-enter class which according to the docs it should.
I'm using ionic version 1.3.3, Angular 1.5.3 and ngAnimate 1.5.3.
Here's a codepen showing the issue: https://codepen.io/jamesjacobs/pen/YQyaZq
What am I missing? Thanks.
Here is how to use ngAnimate with ionic
in view
<ion-item class="chat-item item-remove-animate item-avatar item-icon-right" ...
css
If you want to use it with chat-item class use it as below
.chat-item.ng-enter {
-webkit-animation: fadeInLeft 1s;
animation: fadeInLeft 1s;
}
above code will animate whole list at a once. If you want to animate each item one by one use ng-enter-stagger with delay 200ms
.chat-item.ng-enter-stagger {
-webkit-animation-delay:200ms;
animation-delay:200ms;
/* override to make sure it's not inherited from other styles */
-webkit-animation-duration:0;
animation-duration:0;
}
Demo
Related
I'm not sure if this is a bug, or I have a lack of understanding of the expected behaviour.
On the following codepen (With Angular 1.4) I expect the parent to animate followed by the child items to animate. However, the parent does not animate and the child items still wait for the transition period.
In this codepen (With Angular 1.3) the animations work as expected.
Is this a bug, am I missing something, or has something changed in 1.3 to 1.4 that I have not followed?
Code for completion
HTML
<div ng-app="app" ng-controller="TestCtrl as test">
<button ng-click="toggleItems()">Toggle Items</button>
<div class="parent" ng-show="items">
<p class="child" ng-repeat="item in items">{{item.name}}</p>
</div>
</div>
CSS
.parent {
background:#f00;
transition:all linear 0.5s;
}
.parent.ng-hide {
opacity:0;
}
.child {
background:#0f0;
transition:all linear 0.5s;
}
.child.ng-enter {
opacity:0;
}
JS
var app = angular.module('app', ['ngAnimate'])
app.controller('TestCtrl', function($scope){
$scope.items = null;
$scope.toggleItems = function(){
if( $scope.items ){
$scope.items = null;
} else {
$scope.items = [
{name: 'item 1'},
{name: 'item 2'},
{name: 'item 3'},
];
}
};
});
I found out what was the issue. But it finally seems like an Angular bug or just an outdated angular css:
1.3.5
Using ng-hide with ng-animate will apply :
ng-hide-animate ng-hide-add ng-hide-add-active when added.
ng-hide-animate ng-hide-remove ng-hide-remove-active when removed.
This works well since i found this line of CSS about ng-hide :
.ng-hide:not(.ng-hide-animate) {
display: none !important;
}
This mean your div will not be display when there is no animation. When there is an animation it will show and produce the animation.
1.4.0
In the official documentation Angular added this :
CSS Class-based Animations Class-based animations (animations that are
triggered via ngClass, ngShow, ngHide and some other directives) have
a slightly different naming convention. Class-based animations are
basic enough that a standard transition or keyframe can be referenced
on the class being added and removed.
For example if we wanted to do a CSS animation for ngHide then we
place an animation on the .ng-hide CSS class:
<div ng-show="bool" class="fade"> Show and hide me </div>
<button ng-click="bool=true">Toggle</button>
<style> .fade.ng-hide { transition:0.5s linear all; opacity:0; }
</style>
This mean that on 1.4.0 using ng-hide will simple add and remove ng-hide class.
**/!** In your codePen exemple i found that this line is still there in the CSS
.ng-hide:not(.ng-hide-animate) {
display: none !important;
}
Wich that each time you add ng-hide or remove it, you'll simple set "display:none" wich mean that no animation can be run. You'll need to override this behavior to use proper animations.
Doing this :
.parent.ng-hide {
display:block!important;
opacity:0;
}
Could do the trick but i'm not really sure that this is a safe way to do this.
At least i found the explanation, it would require more investigation to know how to deal with it in a proper way.
Hope it helped.
I am not able to understand how the ngAnimate works exactly. here is my doubt.
1) ngAnimate - only works on directives?
2) how to make ng-animate work without the directive
3) Any of above way, how to add call back after animation complete?
Because i see all the animation examples only with directives.
I have a small demo here, any one help me to animation both without directive and with directive approach to simply adding a class name as `fade'?
my CODE:
<div class="container" ng-app="myApp">
<div class="content" ng-controller="count">
<h1 ng-click="animate()">Click ME</h1>
<h2>Let me Fade</h2>
</div>
</div>
<div class="container" ng-app="myApp">
<div class="content" ng-controller="count">
<h1 ng-click="animate()">Click ME</h1>
<h2>Let me Fade</h2>
</div>
</div>
Demo to update
I am not able to understand how the ngAnimate works exactly. here is
my doubt.
ngAnimate is a module that provides support for animations in angular apps. There are two ways to make use of animations when ngAnimate is used: by using CSS and JavaScript. For CSS based animations, angularjs adds a class ng-enter/ng-leave whenever an element is shown/removed from 'view'. You simply need to play with these classes to make the animation work!
Prerequisite:
You would need to add the library for angular-animate
<script src="ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular-animate.js">
</script>
and include ngAnimate as the dependency in your myApp module.
var myApp = angular.module('myApp', ['ngAnimate']);
1) ngAnimate - only works on directives?
Yes. You cannot use ngAnimate without directive.
According to documentation, following directives are "animation aware":
ngRepeat, ngView, ngInclude, ngSwitch, ngIf, ngClass,
ngShow, ngHide, ngModel, ngMessages and ngMessage
2) how to make ng-animate work without the directive
You cannot!. Remember, even ng-click is a directive
3) Any of above way, how to add call back after animation complete?
Yes, You can add a callback after the animation is complete using the $animate service(which would usually be done in a custom directive) and use $animate.leave(element, [options]);
Have a look at this example for triggering events after the animation ends.
Finally, here is the updated demo you mentioned in question.
You may toggle a flag to true/false with each click on <h1> and make content inside <h2> hide/show based on flag.
<div class="container" ng-app="myApp">
<div class="content" ng-controller="count">
<h1 ng-click="animate()">Click ME</h1>
<h2 ng-if="flag" class="fade">Let me Fade</h2>
</div>
</div>
Also, you'd need to handle fade-effect with css
.fade.ng-enter {
transition:0.5s linear all;
opacity:0;
}
.fade.ng-enter.ng-enter-active {
opacity:1;
}
.fade.ng-leave {
transition:0.5s linear all;
opacity:1;
}
.fade.ng-leave.ng-leave-active {
opacity:0;
}
Hope it helps!
<div class="container" ng-app="myApp">
<div class="content" ng-controller="count">
<h1 ng-click="animate()">Click ME</h1>
<h2 ng-if="clicked" class="animate-if">Let me Fade</h2>
</div>
I added a variable named clicked which is set to true or false to animate the Let me Fade Text
var myApp = angular.module('myApp', []);
myApp.controller('count', function($scope) {
$scope.clicked=false;
$scope.animate = function () {
$scope.clicked=!$scope.clicked;
}
});
In this JS file upon clicking the click me button the variable clicked is set to true or false .
**
h2.fade {
opacity : 0;
transition: opacity 1s ease-in-out;
}
.animate-enter, .animate-leave {
transition: 500ms ease-in all;
position: relative;
display: block;
}
.animate-enter.animate-enter-active, .animate-leave {
left: 0;
}
.animate-leave.animate-leave-active, .animate-enter {
left: 500px;
}
**
Here in the css file i added css for the class animate which acts upon clicked variable if the variable is true it goes for animate-enter-active
otherwise it goes for leave-active
I'm using onsen ui and angular for the first time.
Basically I'm looking to navigate from the index to another page with a full screen carousel, with a specific carousel-item showing.
I started out with this code which is more or less the onsen ui sample carousel code modified to use ng-repeat and to set an initial index.
html
<ons-navigator title="Navigator" var="myNavigator">
<ons-page ng-controller="MyController">
<ons-toolbar>
<div class="center">Carousel</div>
</ons-toolbar>
<ons-carousel swipeable overscrollable auto-scroll fullscreen var="carousel">
<ons-carousel-item ng-repeat="i in ['gray', '#085078', '#373B44', '#D38312']" style="background-color: {{i}};">
<div class="item-label">{{i}}</div>
</ons-carousel-item>
<ons-carousel-cover>
<div class="cover-label">Swipe left or right</div>
</ons-carousel-cover>
</ons-carousel>
</ons-page>
</ons-navigator>
app.js
var app = ons.bootstrap();
app.controller("MyController", function($scope) {
ons.ready(function() {
carousel.setActiveCarouselItemIndex(2);
});
});
And that seemed to work fine when the carousel was the main page.
setting initial-index didn't seem to work with ng-repeat.
html
<ons-carousel swipeable overscrollable auto-scroll fullscreen initial-index="2" var="carousel">
Then, when I tried navigating to the page with the carousel, it said that carousel was undefined.
I also tried adding an event listener on the carousel, since it didn't seem to be loaded at that point.
document.addEventListener('ons-carousel:init', function() {
carousel.setActiveCarouselItemIndex(2);
});
The event listener triggered, but the setActiveCarouselItemIndex didn't seem to do anything.
This same code works when I do not use ng-repeat and have a bunch of ons-carousel-items in the html.
What I started out with: http://codepen.io/anon/pen/aObNqW
A simple example of where I am stuck: http://codepen.io/anon/pen/yNLOvY
If there is a better way to do this, I'd love to know!
Your code is fine, the problem is that you are trying to switch the carousel page when onsen is ready, which is before the carousel element is created. You can add a timeout function to make it work, or just call the script after the carousel has been loaded. If you choose the first option, just modify you controller in this way:
var app = ons.bootstrap();
app.controller("MyController", function($scope) {
ons.ready(function() {
setImmediate(function(){
carousel.setActiveCarouselItemIndex(2);
});
});
});
HERE you can find a working CodePen example
I find it extremely difficult to make an animation in angular, comparing to jquery. There are so many versions of angular animation fadein and fadeout that I found them from blogs/ tutorials/ etc, some of them are on older version of angular. Angular's seems to be very inconsistent when a newer version of it comes out to replace the old ones. I can't see any standard way of doing it. Hence I don't know where to start.
I just to fade in a form or a html doc when the button is clicked.
html,
<button ng-click="loadInclude" >Load Include Form</button>
<div ng-include="'form.php'" ng-if="readyToLoadForm===true"></div>
angular,
var app = angular.module("myapp", ['ngAnimate']);
app.controller("FormController",function($scope) {
$scope.readyToLoadForm = false;
$scope.loadInclude = function(e) {
$scope.readyToLoadForm = true;
};
}
);
any ideas?
you can use a ng-show or ng-hide in this case
<div ng-show="readyToLoadForm" class="animate-show animate-hide">TEST HERE</div>
when using angular-animate.js angular will add and remove several classes to this item when showing and hiding. based on that classes we can set a css animation to the element.
here is a simple plunker
for ng-include animation
ng-leave .ng-leave-active .ng-enter-active classes add to the element. there is a little desc about classes added when animating. and that desc is from ngAnimate
here is the ng-enter demo Plunker
here is the reference for how the classes assigned to the element when animation elements in angularjs
I would like to create master page, that is main page which will be used in all views of the application.
For example, Left navigation and top men navigation. This navigation should be displayed in all the views, whenever url changes in application.
As per ng-view, it only renders given partial view and replace previous view. In the image above all my left and top navigation should be displayed by using angular Controller.
Controller code
angular.module('modelDemo').controller("authCtrl", ['$scope', function($scope) {
$scope.list;
}]);
Please let me know, how can i achieve this
You can use angular-route or Angular-ui-router, and setting your master, following this steps:
Step 1. Make your index.html your master page.
Step 2. Add the <header>, <footer>, <aside>, <div>, etc. referencing your templates by using ng-include
NOTE: your left and top navigation will be part of it
Step 3. The content of the view will be rendered using the directive attribute ng-view or ui-view
Step 4. Use your module app.config() to configure the children pages
Source:
using Angular Route: https://docs.angularjs.org/tutorial/step_07
template for a brand-new app: https://github.com/angular/angular-seed
using Angular UI Router: Angular Tutorial 30 mins
ng view should be able to do that just fine. Keep your top navigation / left navigation html intact and use ng view for the various display area. http://docs.angularjs.org/api/ng.directive:ngView
To use the controller from the top navigation inside ng-view you can use $parent to get access to that scope : https://stackoverflow.com/a/14700326/390330
Fiddle for parent scope : http://jsfiddle.net/ezhrw/2/
<button ng:click="$parent.letter = greek">Assignment expression {{ greek }}</button>
I was trying to create the same concept, but needed a way to define placeholders. I started experimenting in Plnkr.co and thus far, I resorted to using a LayoutManager that drives itself from settings within the routeProvider object.
Here is an example: http://embed.plnkr.co/4GPDfTSQCuqukJE7AniZ/
You'll see an example of how multiple routes use the same header and footer, I did not include an example with a sidebar.
Let me explain the LayoutManager.
I wanted to have placeholders that could be overridden. In this example, I have a toolbar that contains a title and provides a space to the right of the title for additional toolbar items. This gives views an opportunity to throw in additional functionality.
All of this is driven by the LayoutManager. The LayoutManager is a service that reads layout properties set on the $routeProvider. I wanted to implement this in a way keep things clean and self contained, per route. The LayoutManager is injected into the toolbar directive. The toolbar directive drives it's scope properties of the LayoutManager.
In turn, the LayoutManager has a dependency on the routeProvider as well as the rootScope $routeChange event.
I'm very new to Angular, open to suggestions.
I could not see any problem, if you are using bootstrap then use can easily divide your screen as you want
<div class="row">
<div class="col-lg-3">
Left panel
</div>
<div class="col-lg-9" style="border:1px solid #999; overflow-y:auto">
<div> Top Banner </div>
<!-- Main view to render all the page -->
<div ui-view> </div>
</div>
</div>
If you want complete demo and code on then see this link
Edited: 3 Nov. 2016:
If you are using ui-router then we can user abstract state to create different master pages.
You don't need to play show/hide, ng-if but just define the routing properly with you master pages and child pages
Better to see the detail
I know this is an old thread, but thought it should be noted that as of Angular 1.5+ we have been introduced to components. Instead of dealing with routes with named views and all that nonsense or using ngInclude you should be using a header component and footer component. Simply add these to your index.html (or whatever you call your master html template) and voila.
For example (this is using Angular Material and is missing the layout module but hopefully you get the point)
1. Added to index.html
<layout-header></layout-header>
2. header.component.js (you don't need all of this but I think it's helpful)
(function () {
'use strict';
angular
.module('layout')
.component('layoutHeader', {
templateUrl: 'layout/header.html',
bindings: {},
controller: Controller
});
Controller.$inject = [];
function Controller() {
var ctrl = this;
initialize();
////////////////////
function initialize(){
}
}
}());
3. header.html
<md-toolbar>
<div class="md-toolbar-tools">
<h2>
<span>Really Awesome Title!!!!</span>
</h2>
<span flex></span>
<md-button class="md-icon-button" aria-label="More">
<md-icon class="material-icons">more_vert</md-icon>
</md-button>
</div>
</md-toolbar>