Programatically changing ngShow doesn't make use of ngAnimate classes - angularjs

I'm trying to trigger ngShow via my controller, it works, but it doesn't make use of the ngAnimate classes that I need to get a fade transition.
It works like it should if I use a button to toggle ngShow, but not if I toggle it programmatically. Is this expected behavior? Can I get around it?
Plunk:
http://plnkr.co/edit/swJDP1KBBxcRfK9auYPs?p=preview
<body ng-controller="MainCtrl">
<input type="checkbox" ng-model="visible">
<div ng-show="visible" class="wrap" role="document">
Hello
</div>
</body>
var app = angular.module( "app", ['ngAnimate']);
app.run(function($rootScope) {
$rootScope.visible = false;
});
app.controller('MainCtrl', function($rootScope, $scope) {
$rootScope.visible = true;
});
.wrap.ng-hide-add-active {
display: block!important;
transition: 0.5s ease-in-out all;
}
.wrap.ng-hide-remove-active {
display: block!important;
transition: 0.5s ease-in-out all;
transition-delay: 0.5s;
}
.wrap.ng-hide {
opacity: 0;
}

You're run block and controller code likely get executed in the same digest cycle so Angular doesn't see the visible variable changing. This would work if you put your controller code in a timeout. e.g.
app.controller('MainCtrl', function($rootScope, $scope, $timeout) {
$timeout(function() {
$rootScope.visible = true;
});
});
http://plnkr.co/edit/5IhGE3ol5kI64OlT1e8v?p=preview

Related

ng-if = 'false' is hiding the DIV

I have the ng-click and ng-if directives on the same div.
Since the click variable is initially set to false the box DIV does not appear. If I set click to true or use !click for ng-if directive, then the box DIV appears but still no animation occurse upon clicking.
If I remove the ng-click from box DIV and add it to another DIV or button to do the toggle, animation works. However, the box DIV is still hidden initially and also disappears after the animation run.
HTML
<div ng-app="animationApp" ng-controller="c1">
<div ng-click="click=!click" ng-if="click" class="box"></div>
</div>
JS
angular.module('animationApp', ['ngAnimate'])
.controller('c1', function ($scope, $animate, $timeout) {
$scope.click = false;
})
;
CSS
.box {
width: 40px;
height: 40px;
background-color: indianred;
}
.box.ng-enter {
-webkit-transition: all 0.35s ease;
transition: all 0.35s ease;
transform: rotateZ(0deg);
}
.box.ng-enter-active {
transform: rotateZ(-180deg);
}
.box.ng-leave {
-webkit-transition: all 0.35s ease;
transition: all 0.35s ease;
transform: rotateZ(-180deg);
}
.box.ng-leave-active {
transform: rotateZ(0deg);
}
Demo
https://jsfiddle.net/ae8kwzxg/93/
This line is do nothing: "ng-click="click=!click".
The reason why is not work is because your $scope.click variable is primitive type (bool). It means in this line: ng-click="click=!click" click variable is a copy of your $scope.click variable and you just change the copy but not the actual $scope.click. If you will change your $scope.click variable to object, for example $scope.click = {active:true}
and change your HTML to: <div ng-click="click.active=!click.active" ng-if="click.active" class="box"></div>
It will work.
But better way is always do assignments in function:
<div ng-app="animationApp" ng-controller="c1">
<div ng-click="clicked()" ng-if="click" class="box"></div>
</div>
And your controller will be:
angular.module('animationApp', ['ngAnimate'])
.controller('c1', function ($scope, $animate, $timeout) {
$scope.click = true;
$scope.clicked = function(){
$scope.click = !$scope.click;
}
})
This is working example: https://jsfiddle.net/ae8kwzxg/94/

AngularJS with CSS3 Animations - Slideshow Issues

I am attempting to create a simple content slider with AngularJS. I am following this tutorial:https://www.sitepoint.com/creating-slide-show-plugin-angularjs/
However, the content is "jumping". The next slide appears below the current one; it does not appear in its appropriate place while the other is fading out. Here is an image that hopefully clarifies the issue:
The HTML:
<div class="row" id='topSlider' ng-controller="SliderCtrl">
<h2 class="col-sm-12">Latest Stories</h2>
<div class="col-sm-12">
<div class="slider" ng-repeat="story in stories" ng-show="story.visible">
<a class="containerLink" href="View/ViewPost?postID={{story.StoryID}}">
<div class="slide">
<h3 class="cursive">{{story.Title}}</h3>
<blockquote>{{story.StoryPara}}</blockquote>
</div>
</a>
</div>
</div>
<div class="row" id="arrows">
<span class="glyphicon glyphicon-arrow-left"></span>
<span class="glyphicon glyphicon-arrow-right"></span>
</div>
The controller:
app.controller("SliderCtrl", ["$scope", "$http", "$timeout", function ($scope, $http, $timeout) {
$scope.currentIndex = 0;
$http.post("/StoryWall/Home/GetLatestStories").then(function (response) {
$scope.stories = response.data;
$scope.stories[0].visible = true;
},
function (response) {
$scope.stories = response.data;
});
$scope.next = function () {
$scope.currentIndex < $scope.stories.length - 1 ? $scope.currentIndex++ : $scope.currentIndex = 0;
};
$scope.prev = function () {
$scope.currentIndex > 0 ? $scope.currentIndex-- : $scope.currentIndex = $scope.stories.length - 1;
};
$scope.$watch("currentIndex", function () {
$scope.stories.forEach(function (story) {
story.visible = false;
});
$scope.stories[$scope.currentIndex].visible = true;
});
var timer;
var sliderFunction = function () {
timer = $timeout(function () {
$scope.next();
timer = $timeout(sliderFunction, 2000);
}, 5000);
};
sliderFunction();
}]);
and the CSS:
.slider.ng-hide-add, .slider.ng-hide-remove {
-webkit-transition:all linear 1s;
-moz-transition:all linear 1s;
-o-transition:all linear 1s;
transition:all linear 1s;
display:block!important;
clear: none;
float: none;
}
.slider.ng-hide-add.ng-hide-add-active,
.slider.ng-hide-remove {
opacity: 0;
}
.slider.ng-hide-add,
.slider.ng-hide-remove.ng-hide-remove-active {
opacity: 1;
}
Please note, if I remove the CSS it works just fine. The containers hide and show as they should. However, I would like to be able to apply some animations. I am new to both CSS animations and AngularJS; I apologize if this is a redudant or obvious issue.
check this css -> https://daneden.github.io/animate.css/
it's my script
var app=angular.module("app",[]);
app.controller("control",function($scope){
$scope.tab="1";
});
you focus on ng-show method
for example
all slider item in div like that
<div ng-show="tab==1" class="slider-item animated slideInRight">
...............
</div>
and your button must be
<button ng-mouseover="tab=1">1</button>
I hope I could help you

ng-repeat staggered animation on page load in Angular 1.4+

In this other question, the answer provides a workaround (a dirty hack) to make ng-enter animations work on page load.
But, after upgrading to 1.4, this statement:
$rootElement.data("$$ngAnimateState").running = false;
does not work anymore.
Note: Using $timeout is not an option for me, because I've tried but I need to give a big timeout to make it work (more than 1.5 seconds, unacceptable).
You can call animation manually with $animateCss service. Please pay attention to animateOnLoad directive:
angular.module('app', ['ngAnimate']);
angular.module('app').controller('categoriesCtrl', ['$scope', function($scope) {
$scope.categories = ['12345', '6789', '9876', '54321'];
}]);
angular.module('app').directive('animateOnLoad',['$animateCss', function($animateCss) {
return {
'link': function(scope, element) {
$animateCss(element, {
'event': 'enter',
structural: true
}).start();
}
};
}]);
.category {
display:block;
font-size:20px;
background:black;
color:#fff;
margin:10px;
padding:10px;
text-align:center;
}
.category.ng-enter {
/* standard transition code */
-webkit-transition: 2s linear all;
transition: 2s linear all;
opacity:0;
}
.category.ng-enter.ng-enter-active {
/* standard transition styles */
opacity:1;
}
<script src="https://code.angularjs.org/1.4.4/angular.js"></script>
<script src="https://code.angularjs.org/1.4.4/angular-animate.js"></script>
<div data-ng-app="app" data-ng-controller="categoriesCtrl">
<div class="category" ng-repeat="category in categories" animate-on-load>
{{category}}
</div>
</div>

Angular JS simple button ng-click doesn't work

I have the following HTML
<html ng-app="processBeautifierApp">
...
<body ng-controller="PBCtrl" style="padding: 20px;">
<div id="header">
<div style="padding: 7px; float: right;">
<select ng-model="selectedProcess" ng-options="prozess as prozess for prozess in prozessListe"></select><br/>
<button type="button" ng-click="forceRefresh()">Force DCTM Refresh</button>
</div>
</div>
...
</body>
The corresponding javascript
var processBeautifierApp = angular.module('processBeautifierApp', []);
processBeautifierApp.controller('PBCtrl', function ($scope, $http, $interval, $window){
...
$scope.forceRefresh = function() {
...
}
});
The select element and the button are showing correctly. The options have been populated from the mode, $scope.selectedProcess changes when the user selects a different option.
But: The ng-click of the button doesn't react. $scope.forceRefresh() will never be called. There is no error on the console ... it just doesn't react at all. Can you see why?
Check the working example of your code plnkr.co
var processBeautifierApp = angular.module('processBeautifierApp', []);
processBeautifierApp.controller('PBCtrl', function ($scope, $http, $interval, $window){
$scope.forceRefresh = function() {
alert("asd");
}
});
Ok the solution was as simple as possible ... I am really ashamed
I used $scope.forceRefresh as the name of the function, but I also used $scope.forceRefresh somewhere else in the code as a boolean flag to enable/disable force refresh. Renaming the function did the trick

AngularJS animate element on scope change

I am new to AngularJS and at the moment I'm trying out AngularJS animations.
I wrote a CSS animation class that I would like to apply to a Twitter Bootstrap badge on the "Message" button when the value on the badge changes.
The unread message count is handled by the "MessagesCtrl" controller.
For now, the count changes on a button click ("Add Message").
Here is the complete application that I have so far:
<!DOCTYPE html>
<html ng-app="ExampleApp">
<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css">
<script src="http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.0/angular.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.0/angular-animate.min.js></script>
<style rel="stylesheet">
#-webkit-keyframes shake {
0% { -webkit-transform: translate(2px, 2px) rotate(20deg); }
20% { -webkit-transform: translate(-4px, -4px) rotate(-20deg); }
40% { -webkit-transform: translate(2px, 2px) rotate(20deg); }
60% { -webkit-transform: translate(-2px, 2px) rotate(-20deg); }
80% { -webkit-transform: translate(4px, -4px) rotate(20deg); }
100% { -webkit-transform: translate(-2px, 2px) rotate(-20deg); }
}
.shake {
-webkit-animation-name: shake;
-webkit-animation-duration: 0.6s;
-webkit-transform-origin: 50% 50%;
-webkit-animation-iteration-count: 1;
-webkit-animation-timing-function: linear;
}
</style>
<script>
var app = angular.module("ExampleApp", ['ngAnimate']);
app.controller("MessagesCtrl", ['$scope', function ($scope) {
$scope.count = 0;
$scope.addMessage = function () {
$scope.count++;
};
}]);
app.directive('shake', ['$animate', 'MessagesCtrl', function ($animate) {
return {
scope: {
count: '='
},
link: function(scope, element, attrs) {
scope.$watch(attrs, function() {
$animate.addClass(element, 'shake').then(function() {
element.removeClass('shake');
});
});
}
};
}]);
</script>
</head>
<body ng-controller="MessagesCtrl">
<button class="btn btn-primary" type="button">
Messages <span shake id="badgeMessage" class="badge" ng-if="count > 0">{{ count }}</span>
</button>
<button ng-click="addMessage()">Add Message</button>
</body>
</html>
When you click the "Add Message" button, the unread count changes, but the shake animation isn't applied on the badge. Can anyone see why this isn't happening? I think the problem is that I'm
not including the $scope of the controller into the directive, but I'm not sure how to do this.
The animation is called inside the "shake" attribute directive.
Thank you for your time and assistance.
Pass count to the isolated scope you have set up:
<span shake id="badgeMessage" class="badge" count="count" ...
Also change your ng-if to ng-show.
Then watch the count:
scope.$watch('count', function(newValue, oldValue) {
if (newValue === oldValue) return;
$animate.addClass(element, 'shake').then(function() {
element.removeClass('shake');
});
});
Demo: http://plnkr.co/edit/pf5S0e705LK1q1OTGTcq?p=preview
If you want to continue to use ng-if instead you can do this to get it to animate the first time:
scope.$watch('count', function(newValue, oldValue) {
if (newValue === oldValue) return;
animate();
});
var animate = function() {
$animate.addClass(element, 'shake').then(function() {
element.removeClass('shake');
});
};
$timeout(animate);
Demo: http://plnkr.co/edit/sgSTOB5yqiaSgJL5Adl6?p=preview

Resources