AngularJS 1.2 - ngAnimate not working - angularjs

I am new to using ng-animate with AngularJS 1.2. I am not sure why my ng-animate does not work a certain class name but works with the default for a simple fade in that I saw in an example.
In this example, I try to set my ng-animate class to be 'animation':
http://plnkr.co/edit/QWQUUVdcLmzLKRvVibqN?p=preview
but when I use the default, and my class name for animations is just ".ng-enter" and ".ng-leave", the fade in animation seems to work fine.
http://plnkr.co/edit/lEQhMwd6RWmsdmJbosu0?p=preview
Any help would be greatly appreciated, thanks!

The ng-animate attribute is deprecated in 1.2.
In 1.2 you define the appropriate CSS classes using a special naming convention. If you want a specific name like 'animation', you need to add that class to the element you want to animate.
As long as you have the correct CSS classes, some directives will be animated automatically. Which ones can be found here: http://docs.angularjs.org/api/ngAnimate
This is the reason your animation works in your second example when just defining the ".ng-enter" class. This would however automatically animate all directives that support the enter animation.
I have updated your first example to make it work with the class named 'animation':
HTML:
<li ng-repeat="item in items" class="animation">{{item}}</li>
CSS (Keeping selectors ungrouped for clarity):
.animation {
-webkit-transition: 1s;
}
.animation.ng-enter {
opacity: 0;
}
.animation.ng-leave {
opacity: 1;
}
.animation.ng-enter.ng-enter-active {
opacity: 1;
}
.animation.ng-leave.ng-leave-active {
opacity: 0;
}
Plunker: http://plnkr.co/edit/J0qJEMmwdzqXzu733fJf?p=preview

Also important to remember to add the animation module as a dependency to your module definition. Just in case anyone else is having problems getting animations working and hasn't done this.
angular.module('myApp', ['ngAnimate']);

You must check that the version of your angular.min.js matches with the version of angular-animate.min.js.
I got mine fixed this way.

As Tasse said ng-animate is deprecated, we need to use the class.
If you are copying CSS from angularjs web site http://www.nganimate.org/angularjs/ng-repeat/move then you need to modify those CSS in a particular format
For complete detail check Apply Angularjs Animation in 2 minutes

This is in addition to accepted answer, for those who are trying to animate an element with ng-show directive. These are styles which must be used:
.animation.ng-hide-remove {
transition:2s linear all;
opacity:0;
}
.animation.ng-hide-remove.ng-hide-remove-active {
opacity:1;
}
Please note, not all angular directives adds ng-enter, ng-enter-active, ng-leave and ng-leave-active. For example, ng-show directive adds ng-hide-remove at the beginning of animation and ng-hide-remove-active at the end of it. For more details follow this link:
https://www.w3schools.com/angular/angular_animations.asp

Related

Angular 1 ng-class doesn't work as expected

I have a simple ng-class that switches two classes based on the condition. When the class is switched, the order of the classes is messed up not sure why. Has anyone a solution for this?
<div class="ui" ng-class="{'two column grid' : submitNow, 'one column grid' : defaultState}"></div>
Rendered HTML when submitNow is true. This works as expected
<!-- submitNow is true -->
<div class="ui ng-scope two column grid"></div>
Rendered HTML when defaultState is true. This messes up the order of classes added by ng-class
<!-- defaultState is true -->
<div class="ui ng-scope column grid one"></div>
*** Edit ****
Quite strange because it works on jsfiddle. But here's the screenshot of my rendered html code
Here is a demo
https://codepen.io/vibwaj/pen/KKPBdNp
OK...looking at the style rules in elements inspector, semantic ui uses selectors like .ui[class*="two column"].grid > .row > .column
Not sure why they do it that way which is unusual and does make the order important.
Also not sure if it is angular or the browser that sorts the order of those classes. I suspect it is the browser, but that is a guess.
Rather than try to figure out what causes the sort you can add the following rule to fix layout for non specific class order.
.ui.two.column.grid > .row > .column,
.ui.two.column.grid > .column:not(.row){
width:50%!important;
}
Working codepen
Update:
I didn't notice the semantic UI framework that is using this approach.
If you still need the same approach, you can check the forked Codepen which I created a custom directive to be alternative than the original NgClass directive.
app.directive("myNgClass", function() {
return {
link: function(scope, element, attrs) {
scope.$watch(
function() {
return attrs.isExpand;
},
function(isExpand) {
element.removeAttr("class");
if (JSON.parse(isExpand)) {
element.addClass("two column grid");
} else {
element.addClass("one column grid");
}
}
);
}
};
});
Original Answer
So diving deep into the NgClass directive implementation in Angularjs source code and checking how they update the classes, there is a function called updateClasses.
In this function, it finds which classes should be removed and added.
Instead of replacing all the classes when the Boolean flag gets inverted, NgClass keeps the overlapping classes and checks which classes should be added / removed.
So in your case,one column grid (the default case) and two column grid have the column grid classes in common, so it will keep them, but remove the one from the start and add two at the end. So the result will be column grid one.
I really don't suggest to use the order of the classes as CSS selectors. This will make it more harder to select elements and make things more complex.
I also have a comment regarding the CSS selectors that you are using. I really suggest you to read Keep your CSS selectors short article so you can have a better practice of using shorter selector and why keeping the CSS selectors short can help with many things.
For example, If you don't need the one, column and grid classes seprately, you can just use .one-column-grid as a class name / CSS Selector instead of .one.column.grid.

Using angular to change class settings

There is a lot of information on how to use ng-class and ng-style on elements. But I was wondering if there is a way to use angular to change the "settings" of a class.
So for example, say that you had a css class that looked as follows:
.testclass {
color: red;
background-color: blue;
}
I want to use angular to change the color:red to color:black, without attaching angular to the HTML DOM object, but via the class instead.
OK, this isn't a very useful example. What I was really planning to use it for was to hide part of ck-editor (class cle_top) and I want to set the whole class to hidden when someone clicks a button (and visible if the click it again).
======== To make it clearer, this is the bit of HTML I want to hide =======
<span id="cke_1_top" class="cke_top cke_reset_all" role="presentation" style="height: auto; -webkit-user-select: none;"><span id="cke_8" class="cke_voice_label">
Editor toolbars</span><span id="cke_1_toolbox" class="cke_toolbox" role="group" aria-labelledby="cke_8" onmousedown="return false;">
<span id="cke_11" class="cke_toolbar" aria-labelledby="cke_11_label" role="toolbar"><span id="cke_11_label" class="cke_voice_label">
But I need to do it without being able to add angular hooks in the HTML code (like adding ng-class to the span, which would have been a simple solution)
Attached is a JSfiddle that shows my problem, and as you can see, the toolbar button does nothing.
http://jsfiddle.net/vrghost/uqvo3ceh/
Which kind of works now, it adds the class invisible to the span, however, it does not hide the span that it is looking at.
Use the same process on a test text and it works...
Don't know of anything that will edit the class itself, but that probably isn't want you want to do. Other options are:
1) Create a second class, that comes after the first one in your CSS file that adds / changes the properties you want. Ex:
.testclass {
color: red;
background-color: blue;
}
.newclass {
color: green; // change property in first CSS class
display: none; // or hide
}
Then apply the second class conditionally:
<div class="text-class" ng-class="{newclass: hideScopeFlag}">blah</div>
2) Simply use ng-if, ng-hide, or ng-show if all you are doing is hiding something. Ex:
<div class="text-class" ng-hide="hideScopeFlag">blah</div>
or
<div class="text-class" ng-show="!hideScopeFlag">blah</div>
Why not simply toggle the class off/on for that element when the user clicks the button? (Edit: You said you want to "set the whole class to hidden" - I am assuming you mean to remove the class?)
To answer your question though, you can do this with JavaScript using document.styleSheets.
See this Stack Overflow question and the blog post it references. It mentions that there may be some browser compatibility issues. I have not investigated this.
EDIT: This implementation of 'ng-toggle' will allow you to hide or show an element with a single button.
The simplest solution without messing with the stylesheets is to add a new rule like
.visibleOff .testclass {
color: black;
}
and then you just need to toggle the "visibleOff" class on a parent element (the wrapper or the body element) of the editor.
To hide certain elements in the DOM you can also use a $scope variable that acts as a boolean. You can set it to false by default and on button click toggle it to true and back.
$scope.hidden = false;
$scope.toggleHide = function(){
$scope.hidden = !$scope.hidden;
}
In your dom you can then wrap your element with an ng-hide="hidden" attribute like so:
<div ng-hide="hidden">...</div>
<button ng-click="toggleHide()">togglehide</button>
A plunker example can be found here: http://plnkr.co/edit/?p=preview
If anyone wanted to know how to do this, potentially this could be useful for other things as well.
Created a function that uses document.querySelector to find the element, then just do a toggle to turn on or of, and that, as they say, is it folks.
$scope.toolBarVisible = function(){
console.log("Changing visibility");
var element = document.querySelector( '.cke_top' );
console.log("Just to do some debugging we check " + element);
var myEl = angular.element( element );
myEl.toggle();
element = document.querySelector( '.cke_bottom' );
myEl = angular.element( element );
myEl.toggle();
var myEl2 = angular.element( document.querySelector( '.test' ) );
myEl2.toggleClass("invisible")
}
And for those that are looking closely, yes, it hides the bottom as well, and all without changing ckeditor or the code.
Hope someone finds it helpful.

How to add a style tag to the head using angularjs directive

Hi I am allowing users to specify whether they want to print reports in a landscape or portrait format.
I was wondering if it's possible to add this (see below) into the head of the web document using a angularjs directive? That way it will change the printing size depending on the user input.
<style>#media print{#page {size: landscape}}</style>
This depends on whether you are going to be using this functionality in many different places. If you only need it once, then a directive may be overkill.
You can simply put
<style> #media print {#page { size: {{ orientation }} } }</style>
within your angular controller, and specify orientation on the $scope.
To my knowledge there is no need for the style tag to be in the head.
You can use the ngStyle directive to conditionally apply css. See AngularJS ngStyle. The example at the end of the link shows how to do that.
I had to crate custom stylesheet on the fly with unique IDs, I made it nicely work with angularJS like this :
<style type="text/css"
ng-bind="vm.css">
</style>
(note the use of ng-bind)
where vm.css looks like that in the controller
vm.css = `#${$scope.id} { background-color: red; }`
Hope this helps!

How to disable remove icon in ui-select2

Is there a way to disable the icons in ui-select2? I am using ui-select2 in angular js, which is like adding tags while posting a question on stackoverflow:
How can I disable remove icon conditionally?
Official website of ui select2
[Edit 2018-11-12] You could always do a "display: none" on the x span:
span.select2-selection__choice__remove {
display: none;
}
You could also use that to disable click on it with pure JS.
And there is also a "locked" option: http://select2.github.io/select2/#locked-selections
You can then control, per data, which one can't be removed from the selection.
Could something like this help you?
Remove span tag in string using jquery
It's not a direct answer, and it's not ui-select2 specific, but it should help you understand how to remove certain elements. You can just add a condition and that's that.
This is also works
span.select2-selection__clear {
display: none;
}

Hide Angular brackets until javascript loaded

I have a few bits of HTML like
<p class="noresults">{{numberOfContacts}} Results Are Available</p>
Is it possible for me to hide {{numberOfContacts}} until Angular has loaded? So it would just say Results Are Available
I've seem some solutions such as hiding the entire body until Angular has loaded, but I'd rather not do that if possible.
Yes, use ng-cloak. Simply add class="ng-cloak" or ng-cloak to an element like this
Using directive <div ng-cloak></div>
Using class <div class="ng-cloak"></div>
It's simply a set of CSS rules with display: none !important and as Angular has rendered your DOM it removes the ng-cloak so an element is visible.
use <span ng-bind="numberOfContacts" /> instead of {{numberOfContacts}}
Sometimes, even if I used the ng-cloak, I could still see the braces for a few seconds. Adding the following style resolved my issue:
[ng-cloak]
{
display: none !important;
}
Please see this link link for more explanation.
Hope it helps :D
This is typically only an issue when working with complex content on really slow devices. In those instances, there can be a brief moment when the browser displays the HTML in the document while AngularJS is parsing the HTML, getting ready, and processing the directives. In this interval of time, any inline template expressions you have defined will be visible to the user. Most devices nowadays have pretty good browsers which are quick enough to prevent this from being an issue. There are two ways to solve the problem.
Avoid using inline template expressions and stick with ng-bind directive.
(Best) Use the ng-cloak directive which will hide the content until Angular has finished processing it. Basically, the ng-cloak directive uses CSS to hide the elements and angular removes the CSS class when the content has been processed, ensuring that the user never sees the {{ and }} characters of a template expression.
One strategy to consider is using the ng-cloak directly to the body element, which will ensure that the user will see an empty browser while AngularJS loads. However, you can be more specific by applying it to parts of the document where there are inline expressions.
I have seen issues with ng-cloak not working when added to an element. In the past, I have worked around this issue by simply adding ng-cloak class to element.
You can use ng-bind instead of expression like
<span ng-bind="data"></span>

Resources