I would like to do a simple fade in animation for the items that my ng-repeat generates, I followed all the instructions on the ngAnimate site but still no dice.
Here is my module
var app = angular.module('testApp', ['ngRoute','ngAnimate']);
Here is the ng-repeat in my markup
<div class="col-md-6 col-xs-12" ng-repeat="mark in marks" ng-animate="'animate' ">
<div class="col-md-12 well well-sm" >
<div data-ng-include="'./Partials/mark.html'" />
</div>
</div>
Here is some CSS for the animation
.animate-enter {
-webkit-transition: 1s linear all; /* Chrome */
transition: 1s linear all;
opacity: 0;
}
.animate-enter.animate-enter-active {
opacity: 1;
}
And here are the scripts I'm including
<!-- JS -->
<!-- Vendor Libs -->
<script src="./js/angular.min.js"></script>
<script src="./js/angular-animate.min.js"></script>
<script src="./js/angular-route.js"></script>
<script src="./js/jquery.min.js"></script>
<!-- UI Libs -->
<script src="./js/bootstrap.min.js"></script>
<!-- App libs -->
<script src="./js/app.js"></script>
<script src="./Controllers/MarksController.js"></script>
<script src="./Controllers/ViewMarkController.js"></script>
<script src="./Services/marksService.js"></script>
*) All the required CSS files are also linked in my header.
*) Link to Project: https://www.mediafire.com/?6h1qwcrblqczjpr
You don't need the ng-animate="'animate'" directive.
All you need to do is add a class to the intended item, and add the relevant angualrjs animate classes.
Please see the code below:
.animate-repeat {
-webkit-transition: 1s linear all;
transition: 1s linear all;
}
.animate-repeat.ng-move,
.animate-repeat.ng-enter,
.animate-repeat.ng-leave {
-webkit-transition:all linear 0.5s;
transition:all linear 0.5s;
}
.animate-repeat.ng-leave.ng-leave-active,
.animate-repeat.ng-move,
.animate-repeat.ng-enter {
opacity:0;
max-height:0;
}
.animate-repeat.ng-leave,
.animate-repeat.ng-move.ng-move-active,
.animate-repeat.ng-enter.ng-enter-active {
opacity:1;
max-height:40px;
}
The HTML:
<div ng-controller="RestaurantsController">
<input type="text" ng-model="search_cat.name">
<br>
<b>Category:</b>
<div ng-repeat="cat in cuisines">
<b><input type="checkbox" ng-model="cat.checked" /> {{cat.name}}</b>
</div>
<hr />
<div ng-repeat="w in filtered=(restaurants | filter:filterByCategory) " class="animate-repeat">
{{w.name}}
</div>
<hr /> Number of results: {{filtered.length}}
</div>
Please see working example here
From the source
Animations
AngularJS provides animation hooks for common directives such as ngRepeat, ngSwitch, and ngView, as well as custom directives via the $animate service. These animation hooks are set in place to trigger animations during the life cycle of various directives and when triggered, will attempt to perform a CSS Transition, CSS Keyframe Animation or a JavaScript callback Animation (depending on if an animation is placed on the given directive). Animations can be placed using vanilla CSS by following the naming conventions set in place by AngularJS or with JavaScript code when it's defined as a factory.
Animations are not available unless you include the ngAnimate module as a dependency within your application.
Related
I've been experimenting with HTMX recently and I cant seem to find a way to apply a transition to a target element. I have a form that submits a GET request and returns a table.
<form class="mt-3" hx-get="/data/statement/AJAX" hx-target="#statementAJAX" >
It basically returns a div containing the table like this:
<div id="statementAJAX" class="fade-in">
</div>
the CSS for the div is the following:
.fade-in {
opacity: 1;
animation-name: fadeInOpacity;
animation-iteration-count: 1;
animation-timing-function: ease-in;
animation-duration: 0.5s;
}
#keyframes fadeInOpacity {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
Now the css transition works when i first load the page but when I execute the AJAX request nothing happens.
I tried apllying style="opacity:0" to the form but obviously it applies only to the form and not the target...
Any idea how to apply the transition to the target element?
What you have there works for me. Are you trying to replace the entire table or add to the table?
This works for me using your CSS and hx-swap="outerHTML" to replace the table.
<a href="#" id="test" hx-get="/load.html" hx-target="#table" hx-trigger="click" hx-swap="outerHTML">
Submit
</a>
<div id="table" class="fade-in"></div>
load.html
<div id="table" class="fade-in">
table content
</div>
I was trying to do a page fade in when my app initially loads using appear; however, I am already using a routing css animation that does a fade in and fade out when going from page to page, but it still leaves me with an abrupt display of my page when it initially loads. So far, my attempts to add another transition tag around the routing transition in a outer nested way has failed. It still loads with an abrupt display of page. Any suggestions?
<template>
<div id="app">
<v-app>
<main>
<transition name="appearPageFadeIn" appear><!-- new appear tag -->
<cq-nav-mobile></cq-nav-mobile>
<cq-nav-desktop></cq-nav-desktop>
<transition name="interPageFadeOutIn" mode="out-in">
<router-view></router-view>
</transition>
<cq-footer></cq-footer>
</transition>
</main>
</v-app>
</div>
</template>
<!-- CSS -->
/* appear page animation */
.appearPageFadeIn-appear {
opacity: 0;
}
.appearPageFadeIn-appear-active {
transition: opacity 1s;
}
/* inter page routing animation */
.interPageFadeOutIn-enter {
opacity: 0;
}
.interPageFadeOutIn-enter-active {
transition: opacity 1s;
}
.interPageFadeOutIn-leave {
opacity: 1; //default
}
.interPageFadeOutIn-leave-active {
transition: opacity 1s;
opacity: 0;
}
I am trying to implement a slide effect using ng-animate and CSS styles, but can't figure out what's wrong with my code...
Can I do this using values in percentages for min-height and max-height? I cant use fixed values in px.
JSFIDDLE
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app>
Click to toggle menu
<div class="menu" ng-show="collapsed" ng-animate="{show: 'menu-show', hide: 'menu-hide'}">
<div class="files">
<input type="checkbox" />
<label>first</label>
<input type="checkbox" />
<label>second</label>
</div>
<div class="diffs">
<input type="checkbox" />
<label>first</label>
<input type="checkbox" />
<label>second</label>
</div>
</div>
</div>
CSS:
.menu-show-setup, .menu-hide-setup {
transition:all 0.5s ease-out;
overflow:hidden
}
.menu-show-setup {
max-height:0;
}
.menu-show-setup.menu-show-start {
max-height:25%;
}
.menu-hide-setup {
max-height:25%;
}
.menu-hide-setup.menu-hide-start {
max-height:0;
}
First ensure you have angular and angular-animate loaded.
The CDN for angular-animate is ...
<script src="//ajax.googleapis.com/ajax/libs/angularjs/X.Y.Z/angular-animate.js"></script>
Then you need to reference the animations that ngAnimate gives ...
https://docs.angularjs.org/api/ngAnimate
For example, ng-if when switched from false to true will add the class .fade AND .ng-enter to the element on which the ng-if is located. These classes will be automatically removed after a short time. ngAnimate does this for you.
What you HAVE to do is to style what these classes do ...
example:
.fade.ng-enter {
transition:0.5s linear all;
opacity:0;
}
/* The finishing CSS styles for the enter animation */
.fade.ng-enter.ng-enter-active {
opacity:1;
}
now ng-animate will animate from .fade.ng-enter to .fade.ng-enter.ng-enter-active
if you do not define these styles ng-animate will do nothing.
You will see classes being added and remove by ng-animate if you inspect the relevant element in your browser's develop tools. If you cannot see these classes being added and removed then something is wrong with your loading of angular or ng-animate.
I am using ngAnimate to animate entries in an ng-repeat. When loading the data all elements are animated as I have defined in my css:
.chat-message.notice.ng-enter {
-webkit-animation: rubberBand 1s;
-moz-animation: rubberBand 1s;
-ms-animation: rubberBand 1s;
animation: rubberBand 1s;
}
This works when a notice is appended with the following html:
<ul>
<li class="media chat-message pointer fade-animate"
ng-repeat-start="message in guestbook.messages track by $index"
ng-if="!message.bot">
<!-- more html -->
</li>
<li class="chat-message notice" ng-repeat-end ng-if="message.bot">
<div>
<p class="text-center">
{{ message.message }}
<small>({{ message.date | amTimeAgo }})</small>
<span class="close pull-right" ng-click="guestbook.remove(message)">×</span>
</p>
</div>
</li>
</ul>
However, when a new message is appended (at the top), every element is again animated. Is there a way that elements animate only once? That when a new message is appended to the array, only that element will animate?
JSFIDDLE
EDIT
After a few clicks on a 'new message', I can see not all notices are animated. Maybe it has something to do with the ng-repeat-start and ng-repeat-end?
If understood correctly just change this:
$scope.messages.unshift(message);
to this:
$scope.messages.push(message);
Even above answer fixed the problem, my solution might be helpful in other scenarios. The fix is pretty straightforward.
Use Angular varible $first and just add CSS class for the first element using ng-class directive in your HTML. In this example, class "first" will be added only to first element in ng-repeat:
ng-class="{'first': $first===true}"
and then apply animation rules to element with "first" CSS class
.chat-message.notice.first.ng-enter {
color:red !important;
font-weight:bold;
animation: rubberBand 1s;
}
Updated JSFIDDLE: http://jsfiddle.net/t6x3a1zj/7/
I've been playing with this for a while, but can anyone explain what the requirements are to have the tile-cascade page transition to work in Polymer? When I take a look at the code for the transition, I see the following:
polyfill-next-selector { content: ':host(.tile-cascade) > * [tile-cascade] > div:nth-of- type(2)'; }
:host(.tile-cascade) ::content > * /deep/ [tile-cascade] > div:nth-of-type(2) {
-webkit-transition-delay: 0.05s;
transition-delay: 0.05s;
}
polyfill-next-selector { content: ':host(.tile-cascade) > * [tile-cascade] > div:nth-of-type(3)'; }
:host(.tile-cascade) ::content > * /deep/ [tile-cascade] > div:nth-of-type(3) {
-webkit-transition-delay: 0.1s;
transition-delay: 0.1s;
}
I believe this tells us what the markup should be made of (IE: It's looking for divs after the element with the tile-cascade attribute, but I'm not sure if I'm missing other requirements. I've attached a screen shot of some of the code from Chrome dev tools in hopes that it will proved some context
From my experience, there are three things that you need to do.
People often forget to include the reference for the tile-cascade animation. So make sure you have <link rel="import" href="../bower_components/core-animated-pages/transitions/tile-cascade.html"> on top of your element.
You cannot apply the tile-cascade attribute to the direct child of your core-animated-pages. Apply it to the next level container.
Your core-animated-pages needs to include tile-cascade in the transitions attribute.
To demonstrate point 2 & 3, I have the following piece of code that works properly in my project.
<core-animated-pages selected="{{ $.tabs.selected }}" transitions="tile-cascade" notap fit>
<section>
<core-selector tile-cascade>
<div class="portal-item">
<div class="tile"></div>
</div>
<div class="portal-item">
<div class="tile"></div>
</div>
<div class="portal-item">
<div class="tile"></div>
</div>
<div class="portal-item">
<div class="tile"></div>
</div>
Update
4. As already mentioned in the OP, each tile element needs to be wrapped by a div.
Say if you are using a template to iterate through the tiles, you will need to wrap whatever inside your template with a div otherwise the tile-cascade won't work (Interestingly, the list-cascade animation works without the need of the div wrapper). e.g.
<core-animated-pages transitions="cross-fade tile-cascade">
<section>
<div class="container" horizontal layout center-justified wrap cross-fade tile-cascade>
<template repeat="{{item in hierarchyItems}}">
<!-- you need this div here otherwise the tile-cascade animation doesn't work! -->
<div>
<my-element></my-element>
</div>
</template>
</div>
</section>