Difficulty getting JavaScript animation to work with AngularJS Directive - angularjs

function percentToPixel(perc) {
return ($(".stepNavContainer").outerWidth() / 100) * parseFloat(perc);
}
var app = angular.module('app', ["ngAnimate"]);
app.controller("appController", function($scope) {
});
app.directive("init-modal", function() {
return {
restrict: 'E',
link: function(scope, element, attrs) {
scope.init = function() {
TweenMax.set($("#cursor"), {
x: percentToPixel("0") + "px",
xPercent: -50
});
TweenMax.set($("#joinModalNavStep1"), {
x: percentToPixel("0") + "px",
xPercent: -50
});
TweenMax.set($("#joinModalNavStep2"), {
x: percentToPixel("50") + "px",
xPercent: -50
});
TweenMax.set($("#joinModalNavStep3"), {
x: percentToPixel("100") + "px",
xPercent: -50
});
};
}
};
});
app.directive("step-modal", function() {
return {
restrict: 'E',
link: function(scope, element, attrs) {
var tlStepNavAnimation = new TimelineMax();
tlStepNavAnimation.to(cursor, 1, {
x: percentToPixel("0") + "px",
xPercent: -50,
ease: Back.easeInOut
});
tlStepNavAnimation.addPause();
tlStepNavAnimation.to(cursor, 1, {
x: percentToPixel("50") + "px",
xPercent: -50,
ease: Back.easeInOut
});
tlStepNavAnimation.addPause();
tlStepNavAnimation.to(cursor, 1, {
x: percentToPixel("100") + "px",
xPercent: -50,
ease: Back.easeInOut
});
scope.play = function() {
tlStepNavAnimation.play();
};
scope.reverse = function() {
tlStepNavAnimation.reverse();
};
}
};
});
html,
body {
overflow: hidden;
}
body {
background-color: white;
margin: 0;
padding: 0;
}
.stepNavContainer {
position: relative;
height: 50px;
width: 50%;
left: 25%;
border: 1px solid red;
}
.circle {
display: block;
position: absolute;
width: 50px;
height: 50px;
border-radius: 50%;
}
#cursor {
display: block;
position: absolute;
width: 50px;
height: 50px;
background: #c32026;
border-radius: 50%;
}
.step {
background: #999999;
}
.btn {
width: 100px;
height: 50px;
border: 1px solid black;
}
<!DOCTYPE html>
<html ng-app="app" ng-controller="appController">
<head>
<title>Title of the document</title>
<!-- Angular Material style sheet -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/angular-material/1.0.6/angular-material.min.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<div init-modal ng-click="init()" id="setupBtn" class="btn">
<span>Setup</span>
</div>
<div step-modal ng-click="reverse()" id="previousBtn" class="btn">
<span>Previous</span>
</div>
<div id="nextBtn" class="btn">
<span step-modal ng-click="play()">Next</span>
</div>
<div init-modal class="stepNavContainer">
<span id="joinModalNavStep1" class="circle step"></span>
<span id="joinModalNavStep2" class="circle step"></span>
<span id="joinModalNavStep3" class="circle step"></span>
<span id="cursor" class="circle"></span>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular-animate.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.18.2/TweenMax.min.js"></script>
</body>
</html>
So, I have a working JavaScript animation (Greensock) that you can see here http://codepen.io/jstafford/pen/VaLgvK . I am trying to plug this into an AngularJS directive, but I am not even making it inside the directives for Setup (init-modal directive) or Next and Previous (step-modal directive) buttons. 1) Push Setup button to setup the three circles and cursor at their initial positions which triggers the init-modal directive 2) Then the pushing of Next button or Previoius button triggers the step-modal directive to cause the step animation to occur. I am new to AngularJS and I am trying to do this the AngularJS way but really struggling. Any help greatly appreciated.

First, give a camel case name to your directive:
app.directive("initModal", function() {
return {
restrict: 'E',
link: function(){}
}
}
restrict: 'E' => Element: <init-modal></init-modal>
restrict: 'A' => Attribute: <div init-modal></div>
restrict: 'C' => Classname: <div class="init-modal"></div>
Angular's directive documentation

Related

I want to show a modal window on selecting a list item in angular js

I want to show a pop up window when a user selects an element from the dropdown list. But instead im getting a plain text no modal window is being shown. Please help: below is the referece for my code-
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.value = '';
$scope.accntDetails = {
accnt01: { bankName: "HDFC", bankbranch: "delhi", accntNumber: "12345" },
accnt02: { bankName: "ICICI", bankbranch: "mumbai", accntNumber: "12346" },
accnt03: { bankName: "IDBI", bankbranch: "pune", accntNumber: "12347" }
};
$scope.modalShown = false;
$scope.toggleModal = function() {
$scope.modalShown = true;
};
$scope.changedValue = function(bank) {
$scope.value = bank.bankName;
$scope.toggleModal();
console.log($scope.value);
}
angular.module('myApp').directive('modalDialog', function() {
return {
restrict: 'E',
scope: {
show: '='
},
transclude: true,
link: function(scope, element, attrs) {
console.log('attrs: ', attrs);
scope.dialogStyle = {};
if (attrs.boxWidth) {
scope.dialogStyle.width = attrs.boxWidth;
}
if (attrs.boxHeight) {
scope.dialogStyle.height = attrs.boxHeight;
}
scope.hideModal = function() {
scope.modalShown = false;
};
},
template: `<div class='ng-modal' ng-show='modalShown'>
<div class='ng-modal-overlay' ng-click='hideModal()'></div>
<div class='ng-modal-dialog' ng-style='dialogStyle'>
<div class='ng-modal-close' ng-click='hideModal()'>X</div>
<div class='ng-modal-dialog-content' ng-transclude></div>
</div>
</div>`
};
});
});
/* Custom CSS- this is the css code for showing up a modal */
.ng-modal-overlay {
/* A dark translucent div that covers the whole screen */
position: absolute;
z-index: 9999;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: #808080;
opacity: 0.8;
}
.ng-modal-dialog {
background-color: #fff;
box-shadow: 10px 10px #595554;
border-radius: 4px;
z-index: 10000;
position: absolute;
top: 50%;
left: 50%;
-ms-transform: translate(-50%, -50%);
-o-transform: translate(-50%, -50%);
-webkit-transform: translate(-50%, -50%);
-moz-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
}
.ng-modal-dialog-content {
padding: 10px;
text-align: left;
}
.ng-modal-close {
position: absolute;
top: 3px;
right: 5px;
padding: 5px;
cursor: pointer;
font-size: 120%;
display: inline-block;
font-weight: bold;
font-family: 'arial', 'sans-serif';
}
<body>
<div ng-app="myApp" ng-controller="myCtrl">
<p>Select account number:</p>
<!-- <select ng-model="accnt" ng-options="y.bankName for (x, y) in accntDetails">
</select> -->
<select ng-model="bankSelected" ng-change=" toggleModal();"
data-ng-options="bank as bank.bankName for bank in accntDetails">
<option value="">Select Account</option>
</select>
<h1>You selected: {{bankSelected.bankName}}</h1>
<h2>branch: {{bankSelected.bankbranch}}</h2>
<h3>Number: {{bankSelected.accntNumber}}</h3>
<div ng-show="modalShown">
<modal-dialog box-width="400px" box-height="150px">
<div class="row">
<div class="col-md-12">
<h3>Header</h3>
<hr style="border-top:1px solid darkblue" />
</div>
</div>
<div class="row">
<div class="col-md-12">
This is an important message
</div>
</div>
</modal-dialog>
</div>
</div>
</body>
when a user click on any element of the list a modal window should popup. I have tried this code. If i use it onClick event it works fine the modal opens but if i use it with ng-select it doesnt works:
Okay, I think there are two problems here. One is that your JSON is not valid to run on a repeat. It should be an array of Object to get the details. I was able to run the same when I tried that with the JSON as :
CODEPEN
like accntDetails = [{BankDetails1},{BankDetails2},{BankDetails}]

ngRepeat strange behaviour when its elements order change

I am learning angularjs and I came across some behaviour that I can't understand. I render a list of items in ng-repeat, each has a button to remove itself from the $scope's array - this works as expected but once I added a sortable to the list strange things started to happen.
Here is the running example showing the issue:
https://embed.plnkr.co/eQWcxZ7p8CcACfk6Z53X/
In the example - if I move [^] item 4 (Rocket Launcher) to position 1 and use Rocket Launcher's delete [X] button the list gets updated (i.e. item 4 - Rocket Launcher - that was on position 1 is removed) but the other items delete buttons stop working. Basically moving items and deleting them somehow break the bindings (?).
The code:
(function() {
'use strict';
var app = angular.module('myApp', []);
app.controller('myAppController', function($scope) {
$scope.boxes = [];
$scope.removeBoxItem = function(box, item) {
console.log('Removing "' + item.name + '" form box "' + box.name + '"...');
var index = box.items.indexOf(item);
box.items.splice(index, 1);
console.log(box);
};
this.init = function() {
var e;
e = new Box({
name: 'Red box'
});
$scope.boxes.push(e);
e.items.push(new Item({
index: 1,
name: 'Rock'
}));
e.items.push(new Item({
index: 2,
name: 'Scissors'
}));
e.items.push(new Item({
index: 3,
name: 'Paper'
}));
e.items.push(new Item({
index: 4,
name: 'Rocket launcher'
}));
e = new Box({
name: 'Green box'
});
e.items.push(new Item({
index: 1,
name: 'Chuck the Plant'
}));
e.items.push(new Item({
index: 2,
name: 'Hamster'
}));
e.items.push(new Item({
index: 3,
name: 'Tentacle Chow'
}));
$scope.boxes.push(e);
};
this.init();
});
app.directive("sortable", ["$timeout", function($timeout) {
return {
template: '<div class="sortable" ng-transclude></div>',
transclude: true,
scope: {
'handle': '#'
},
link: function(scope, element, attrs) {
$timeout(function() {
//console.log(element)
var sortable = element.find('> div');
console.log(sortable[0]);
scope.sortable = Sortable.create(sortable[0], {
handle: scope.handle || null
});
});
}
};
}]);
}());
function Box(args) {
this.name = args.name || null;
this.items = [];
}
function Item(args) {
this.index = args.index || null;
this.name = args.name || null;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<link rel="stylesheet" href="style.css" />
<style>
.container {
border: 1px solid #929292;
padding: 5px;
}
.header {
font-size: 1.2rem;
padding: 10px 15px;
background-color: #F5F5F5;
border-bottom: 2px solid #E2E2E2;
}
.body {
background-color: #F2F2F2;
padding: 10px 10px;
margin-bottom: 10px;
}
.body .item {
border: 1px solid #D2D2D2;
padding: 5px;
margin-bottom: 5px;
}
.body .options {
float: right;
}
.body .options .delete {
cursor: pointer;
}
.body .options .handle {
cursor: move;
}
.debug {
margin-top: 20px;
border-top: 1px dotted #929292;
}
</style>
</head>
<body>
<div ng-app="myApp" ng-controller="myAppController as appCtrl">
<div class="container">
<div ng-repeat="box in boxes">
<div class="header">{{ box.name }}</div>
<div class="body">
<div data-sortable="" data-handle=".handle">
<div class="item" ng-repeat="item in box.items">
{{item.index }}) {{ item.name }}
<div class="options">
<span ng-click="removeBoxItem(box, item)" class="delete">[X]</span>
<span class="handle">[^]</span>
</div>
</div>
</div>
</div>
</div>
<div class="debug">
<pre>{{ boxes | json }}
</pre>
</div>
</div>
</div>
<script data-require="jquery#3.1.1" data-semver="3.1.1" src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script data-require="Sortable.js#1.6.0" data-semver="1.6.0" src="https://cdnjs.cloudflare.com/ajax/libs/Sortable/1.6.0/Sortable.js"></script>
<script data-require="angular.js#1.6.6" data-semver="1.6.6" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.6/angular.js"></script>
<script src="script.js"></script>
</body>
</html>
I am confused by this, in my real code things get even more broken - I made a collapsible directive that surrounds the "Boxes" so I can open and manipulate one at a time - in that case moving item 4 to position 1 and deleting it removes all items from the view (but not from the $scope). Than adding new item to the $scope's array causes items to correctly reappear. For now I created simpler version as I guess this is all somehow connected.
I am aware the sortable should set the objects indexes etc but for now I'd like to understand what is happening. I suspect I have some issues with understanding what is going on with scopes (?). Would be grateful for any help.

template works fine whereas templateUrl not in angular component

code to create tabs component
Hi,I am learning angular component from this link ,the problem is when i tried to load from external files instead of template it throws following error
angular.js:13708 TypeError: Cannot set property 'selected' of undefined
at controller.selectTab (scr.js:47)
at controller.$postLink (scr.js:50)
at angular.js:9228
at forEach (angular.js:329)
at nodeLinkFn (angular.js:9225)
at compositeLinkFn (angular.js:8510)
at compositeLinkFn (angular.js:8513)
at compositeLinkFn (angular.js:8513)
at publicLinkFn (angular.js:8390)
at angular.js:1756
here is the scr.js code
var tab = {
bindings: {
label: '#'
},
require: {
tabs: '^^tabs'
},
transclude: true,
template:['$templateCache',function($templateCache){
return $templateCache.get('tab.html')
}
],
controller: function () {
this.$onInit = function () {
this.tab = {
label: this.label,
selected: false
};
this.tabs.addTab(this.tab);
};
}
};
var tabs = {
bindings: {
selected: '#'
},
transclude: true,
template:['$templateCache',function($templateCache){
return $templateCache.get('tab.html')
}
],
controller: function () {
this.$onInit = function () {
this.tabs = [];
};
this.addTab = function addTab(tab) {
this.tabs.push(tab);
};
this.selectTab = function selectTab(index) {
for (var i = 0; i < this.tabs.length; i++) {
this.tabs[i].selected = false;
}
this.tabs[index].selected = true;
};
this.$postLink = function () {
this.selectTab(this.selected);
console.log(this.selected)
};
},
};
angular
.module('app', [])
.component('tab', tab)
.component('tabs', tabs);
Here is html code:
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.7/angular.js"></script>
<script src="scr.js"></script>
<style>
* {
box-sizing: border-box;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
}
body {
font: 300 14px/1.4 'Helvetica Neue', Helvetica, Arial, sans-serif;
background: #111;
margin: 0;
padding: 0;
}
.tabs {
margin: 25px;
background: #fff;
}
.tabs__list {
list-style: none;
margin: 0;
padding: 0;
overflow: hidden;
border-bottom: 1px solid #eee;
}
.tabs__list li {
float: left;
}
.tabs__list li a {
color: #444;
display: block;
text-decoration: none;
padding: 10px 20px;
}
.tabs__content {
padding: 10px;
}
</style>
</head>
<body>
<div ng-app="app">
<div>
<tabs selected="2">
<tab label="Tab 1">
Tab 1 contents!
</tab>
<tab label="Tab 2">
Tab 2 contents!
</tab>
<tab label="Tab 3">
Tab 3 contents!
</tab>
</tabs>
</div>
</div>
</body>
</html>
here are two template which i am trying to load in component tab.html and tabs.html respectively:
<div class="tabs__content" ng-if="$ctrl.tab.selected">
<div ng-transclude></div>
</div>
<div class="tabs">
<ul class="tabs__list">
<li ng-repeat="tab in $ctrl.tabs">
<a href=""
ng-bind="tab.label"
ng-click="$ctrl.selectTab($index);"></a>
</li>
</ul>
<div class="tabs__content" ng-transclude></div>
</div>
can any one please help me fix this,Thanks in advance

Sharing controller for multiple directives not working

Plunker Code
I am having an issue getting the ng-class to work in the flipCard directive's templates. Technically it does work, if I set the property immediate in the controller it will add the css class.
What it looks like to me in that children directives may be getting an independent copy of the controller instead of sharing the base flipCard directive's controller. So when I call flipCtrl.move it is calling the flipCardOver directive's instance of the controller as setting the property on the controller in the flipCtrl.move function is not updating the base parents flipped property, though console logging it says it is set to true.
Goal: Have a controller on flipCard that is shared with flipCardBack, flipCardFront, flipCardOver, flipCardReset While also allowing multiple flipCard directives on a page and not having conflicts.
What am I missing?
angular.module('cardFlip', [])
.controller('flipCardController', ['$scope', '$element', '$timeout', '$window',
function($scope, $element, $timeout, $window) {
var vm = this;
vm.flipped = false;
vm.moved = false;
vm.originalTop = -1;
vm.originalLeft = -1;
vm.move = function(e) {
vm.flipped = true;
console.log(vm.flipped);
};
vm.reset = function() {
vm.flipped = false;
};
}
])
.directive('flipCard', function() {
return {
restrict: 'AE',
controller: 'flipCardController',
controllerAs: 'flipCtrl',
scope: true,
transclude: true,
// LOOK: this is the template that I am expecting to change
template: '<div class="container"><div class="panel" ng-class="{ flip: flipCtrl.flipped, slide: flipCtrl.moved }" ng-transclude></div></div>'
}
})
.directive('flipCardFront', function() {
return {
restrict: 'AE',
require: '^flipCard',
transclude: true,
template: '<div class="front" ng-transclude></div>'
}
})
.directive('flipCardBack', function() {
return {
restrict: 'AE',
require: '^flipCard',
transclude: true,
template: '<div class="back" ng-transclude></div>'
}
})
.directive('flipCardOver', function() {
return {
restrict: 'AE',
require: '^flipCard',
link: function(scope, element, attribs, flipCtrl) {
// LOOK: this is the event I am expecting to call move that sets flipped to true
element.on('click', flipCtrl.move);
}
}
})
.directive('flipCardReset', function() {
return {
restrict: 'AE',
require: '^flipCard',
link: function(scope, element, attribs, flipCtrl) {
element.on('click', flipCtrl.reset);
}
}
});
/* Styles go here */
[ng-click] {
cursor: pointer;
}
.panel .pad {
padding: 0 15px;
}
.panel.flip .action {
display: none;
}
.panel {
float: left;
width: 200px;
height: 200px;
margin: 20px;
position: relative;
font-size: .8em;
-webkit-perspective: 600px;
perspective: 600px;
}
/* -- make sure to declare a default for every property that you want animated -- */
/* -- general styles, including Y axis rotation -- */
.panel .front {
float: none;
position: absolute;
top: 0;
left: 0;
z-index: 900;
width: inherit;
height: inherit;
background: #6b7077;
-webkit-transform: rotateX(0) rotateY(0);
transform: rotateX(0) rotateY(0);
-webkit-transform-style: preserve-3d;
transform-style: preserve-3d;
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
/* -- transition is the magic sauce for animation -- */
-webkit-transition: all .4s ease-in-out;
transition: all .4s ease-in-out;
}
.panel.flip .front {
z-index: 900;
-webkit-transform: rotateY(179deg);
transform: rotateY(179deg);
}
.panel.slide {
top: 15%;
left: 15%;
-webkit-transition: all 5s ease-in-out;
transition: all 5s ease-in-out;
}
.panel .back {
float: none;
position: absolute;
top: 0;
left: 0;
z-index: 800;
width: inherit;
height: inherit;
box-shadow: 0 2px 15px rgba(0, 0, 0, 0.2);
-webkit-transform: rotateY(-179deg);
transform: rotateY(-179deg);
-webkit-transform-style: preserve-3d;
transform-style: preserve-3d;
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
/* -- transition is the magic sauce for animation -- */
-webkit-transition: all .4s ease-in-out;
transition: all .4s ease-in-out;
}
.panel.flip .back {
z-index: 1000;
-webkit-transform: rotateX(0) rotateY(0);
transform: rotateX(0) rotateY(0);
}
<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.8/angular.js"></script>
</head>
<body>
<div ng-app="cardFlip">
<div ui-view="main">
<flip-card>
<flip-card-front>
<div style="width:50px;height:50px;" flip-card-over="function(){return true;}">
FRONT1
</div>
</flip-card-front>
<flip-card-back>
<div style="width:100px;height:100px;" flip-card-reset="function(){return true;}">
BACK1
</div>
</flip-card-back>
</flip-card>
</div>
</div>
</body>
</html>
At first I was stumped too, but then I realised - you haven't told Angular about the change using scope.$evalAsync() (safer than doing $apply() or $digest() in case there is already a digest happening). This is because you are handling the click yourself, rather than using ng-click (which triggers a digest, so doesn't have this problem).
Here is a forked Plunkr with it working.
angular.module('cardFlip', [])
.controller('flipCardController', ['$scope', '$element', '$timeout', '$window',
function($scope, $element, $timeout, $window) {
var vm = this;
vm.flipped = false;
vm.moved = false;
vm.originalTop = -1;
vm.originalLeft = -1;
vm.move = function(e) {
vm.flipped = true;
console.log(vm.flipped);
};
vm.reset = function() {
vm.flipped = false;
};
}
])
.directive('flipCard', function() {
return {
restrict: 'AE',
controller: 'flipCardController',
controllerAs: 'flipCtrl',
scope: true,
transclude: true,
// LOOK: this is the template that I am expecting to change
template: '<div class="container"><div class="panel" ng-class="{ flip: flipCtrl.flipped, slide: flipCtrl.moved }" ng-transclude></div></div>'
}
})
.directive('flipCardFront', function() {
return {
restrict: 'AE',
require: '^flipCard',
transclude: true,
template: '<div class="front" ng-transclude></div>'
}
})
.directive('flipCardBack', function() {
return {
restrict: 'AE',
require: '^flipCard',
transclude: true,
template: '<div class="back" ng-transclude></div>'
}
})
.directive('flipCardOver', function() {
return {
restrict: 'AE',
require: '^flipCard',
link: function(scope, element, attribs, flipCtrl) {
// LOOK: this is the event I am expecting to call move that sets flipped to true
element.on('click', function () {
flipCtrl.move();
scope.$evalAsync(); // tell Angular we did something
});
}
}
})
.directive('flipCardReset', function() {
return {
restrict: 'AE',
require: '^flipCard',
link: function(scope, element, attribs, flipCtrl) {
element.on('click', function () {
flipCtrl.reset();
scope.$evalAsync(); // tell Angular
});
}
}
});
/* Styles go here */
[ng-click] {
cursor: pointer;
}
.panel .pad {
padding: 0 15px;
}
.panel.flip .action {
display: none;
}
.panel {
float: left;
width: 200px;
height: 200px;
margin: 20px;
position: relative;
font-size: .8em;
-webkit-perspective: 600px;
perspective: 600px;
}
/* -- make sure to declare a default for every property that you want animated -- */
/* -- general styles, including Y axis rotation -- */
.panel .front {
float: none;
position: absolute;
top: 0;
left: 0;
z-index: 900;
width: inherit;
height: inherit;
background: #6b7077;
-webkit-transform: rotateX(0) rotateY(0);
transform: rotateX(0) rotateY(0);
-webkit-transform-style: preserve-3d;
transform-style: preserve-3d;
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
/* -- transition is the magic sauce for animation -- */
-webkit-transition: all .4s ease-in-out;
transition: all .4s ease-in-out;
}
.panel.flip .front {
z-index: 900;
-webkit-transform: rotateY(179deg);
transform: rotateY(179deg);
}
.panel.slide {
top: 15%;
left: 15%;
-webkit-transition: all 5s ease-in-out;
transition: all 5s ease-in-out;
}
.panel .back {
float: none;
position: absolute;
top: 0;
left: 0;
z-index: 800;
width: inherit;
height: inherit;
box-shadow: 0 2px 15px rgba(0, 0, 0, 0.2);
-webkit-transform: rotateY(-179deg);
transform: rotateY(-179deg);
-webkit-transform-style: preserve-3d;
transform-style: preserve-3d;
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
/* -- transition is the magic sauce for animation -- */
-webkit-transition: all .4s ease-in-out;
transition: all .4s ease-in-out;
}
.panel.flip .back {
z-index: 1000;
-webkit-transform: rotateX(0) rotateY(0);
transform: rotateX(0) rotateY(0);
}
<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.8/angular.js"></script>
</head>
<body>
<div ng-app="cardFlip">
<div ui-view="main">
<flip-card>
<flip-card-front>
<div style="width:50px;height:50px;" flip-card-over="function(){return true;}">
FRONT1
</div>
</flip-card-front>
<flip-card-back>
<div style="width:100px;height:100px;" flip-card-reset="function(){return true;}">
BACK1
</div>
</flip-card-back>
</flip-card>
</div>
</div>
</body>
</html>

How to stop angular 1.2 ngclass animation from running on re-compile

Example: http://codepen.io/anon/pen/ixEdu
In the example provided above I have an angular animation using ngClass. When the element containing the animation is re-compiled the animation is run. How do I stop this from occuring?
HTML:
<div ng-app="app" ng-controller="appCtrl">
myVal: {{ myVal }} <br>
Change Value<small> - Yes, we want animation.</small><br>
<div class="demo" recompile-test>
Recompile
<small> - No!!! we do not want animation.</small>
<div value-rotate="myVal" class="demo1"></div>
<div class="demo2-container">
<div value-rotate="myVal" class="demo2"></div>
</div>
</div>
</div>
CSS:
.demo2-container {
display: block;
background-color: #ccc;
height: 100px;
}
.demo2 {
display: inline-block;
vertical-align: middle;
width: 90px;
line-height: 100px;
height: 100%;
padding-left: 6px;
font-size: 11px;
}
.value-rotate__value.show-add,
.value-rotate__value.show-remove {
-webkit-transition-delay: 4s;
-webkit-transition: 0.5s linear all;
transition: 0.5s linear all;
transition-delay: 0.1s;
animation-delay: 0.1s;
}
.value-rotate__value.show-add {
position: absolute;
top: -100%;
}
.value-rotate__value.show-remove {
position: absolute;
top: 100%;
}
.value-rotate__value {
position: absolute;
top: 100%;
}
.value-rotate__value.show {
top:0;
}
Javascript:
angular.module('app', ['ngAnimate'])
.controller("appCtrl", function ($scope) {
$scope.myVal = 56;
$scope.changeVal = function() {
$scope.myVal += 1;
}
})
.directive('recompileTest', function($compile) {
return {
link: function(scope, element) {
var originalHtml = element.html();
var originalScope = element.scope();
scope.recompile = function() {
element.html(originalHtml);
$compile(element.contents())(originalScope);
};
}
}
})
.directive('valueRotate', function($timeout) {
return {
scope: {
value: '=valueRotate'
},
template: '' +
' <span class="value-rotate__value" ng-class="{show: valueToggle == true}">{{ value1 }}</span>' +
' <span class="value-rotate__value" ng-class="{show: valueToggle == false}">{{ value2 }}</span>' +
'',
link: function (scope, element, attrs) {
element.css({ position: 'relative', overflow: 'hidden' });
scope.$watch('value', function(newValue, oldValue) {
if (scope.valueToggle) {
scope.value2 = newValue;
} else {
scope.value1 = newValue;
}
scope.valueToggle = !scope.valueToggle;
});
//set the initial height based on contents.
/*
$timeout(function() {
element.children().css('height', element[0].offsetHeight + 'px');
});
*/
}
};
});
You could add a css class to override with transition: none while the directive is showing an initial value.
Example: http://codepen.io/anon/pen/LeGoD
In css:
.noAnimate {
transition: none !important;
}
In html template:
<span class="value-rotate__value" ng-class="{show: valueToggle == true, noAnimate: isInitialValue}">{{ value1 }}</span>
In directive:
scope.$watch('value', function(newValue, oldValue) {
// the newValue and oldValue will be equal only when
// this function is called for the first time,
// thus it is an initial value.
scope.isInitialValue = (newValue === oldValue);
if (scope.valueToggle) {
scope.value2 = newValue;
} else {
scope.value1 = newValue;
}
scope.valueToggle = !scope.valueToggle;
});
Hope this helps.

Resources