Angularjs animation restrict for class - angularjs

Good day. I have a question:
is there any way to restrict to angular adding additional classes for element for animation?
i.e.: when element has some transition in CSS, and i try to add another class with ng-class, it also adds: class-add, class-add-active.
I don't want angular to add this classes.

Yes there's a way to do it, you need to add a filter on class names you want to animate via a regex
angular.module('myApp', ['ngAnimate']).config(['$animateProvider', function($animateProvider){
$animateProvider.classNameFilter(/myClass/);
}]);
<div class="myClass"> ... </div>

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.

Apply rowTemplate on Kendo grid without overriding current

I'm using Angular 1.4 typescript, with Kendo (using angular directives).
I'm trying to make a RowTemplate for each row, to change the color based on a property of the item.
I know there are some approaches with jQuery, but I find them very displeasing... If I'm using angular, I would like to reference items with angular.
This is my HTML:
<div id="resultSubTasksGrid"
kendo-grid="resultGrid"
k-options="vm.gridOptions"
k-columns="vm.columns">
</div>
This is my gridOptions:.
gridOptions: kendo.ui.GridOptions = {
rowTemplate : "<tr data- uid='#: uid #' ng-class='sent: item.IsSent'></tr>"
}
My problem comes here: I don't want to override the full row. This approach does so. I have lot of columns, and almost all of them have celltemplates I don't want to lose (but I don't want to have them all in the RowTemplate either).
I would like to know if is it possible to have something like:
rowTemplate : "<tr data- uid='#: uid #' ng-class='sent: item.IsSent'>{{RENDERCONTENT}}</tr>"
Well, it seems that by how Kendo it's developed, once you set up a row-template, you need to go all in. There is not such thing as partial template or wrapper.
More information here.

AngularJs directive extending

I want to extend pagination directive (from angular-bootstrap),
but cannot find information how to extend built-in directives.
Basically i want paginate to do what it does + extra functionality of displaying [currentPage]/[totalpage] next to pagination buttons.
I don't want to create nested directive in pagination, just want be able to use:
<pagination
class="pagination-sm"
boundary-links="true"
<!-- based on attribute below i want to display 'current/total' -->
meta-info="true"
>
</pagination>
Can anyone help or navigate to helping source?
There is a way to "extend" 3rd party directive without modifying the source code using $provider.decorator()
Please refer to http://angular-tips.com/blog/2013/09/experiment-decorating-directives/
It is a little long, but satisfying when getting it work.
If you need to only overload template (and not JS logic of directives/controllers), you can very easily update ui-bootstrap to your needs :
in a template, just add :
<script id="template/pagination/pagination.html" type="text/ng-template">
<ul class="pagination">
...
</<ul>
</script>
You can also put that in a dedicated file and use grunt/gulp and html2js in order to automatically put in the templateCache :
angular.module('myApp', ['ui.bootstrap']).run(
['$templateCache', function($templateCache){
$templateCache.put('template/pagination/pagination.html',
"<ul class=\"pagination\">\n" +
" ...\n" +
"</ul>\n");
}
]);
That will replace the existing templates. Usefull when you want to add css classnames or updates labels. If you need to add logic, that's not sufficient (see other answer)

How to select an element by classname using jqLite?

I'm trying to remove jquery from my Angular.js app in order to make it lighter, and put Angular's jqLite instead. But the app makes heavy use of find('#id') and find ('.classname'), which are not supported by jqLite, only 'tag names' (as per documentation)
wondered what do u feel would be the best approach to change it. One approach I thought about is to create custom HTML tags. for example:
change
<span class="btn btn-large" id="add-to-bag">Add to bag</span>
to
<a2b style="display:none;"><span class="btn btn-large" >Add to bag</span></a2b>
and
$element.find('#add-to-bag')
to
$element.find('a2b')
Any thoughts? other ideas?
thanks
Lior
Essentially, and as-noted by #kevin-b:
// find('#id')
angular.element(document.querySelector('#id'))
//find('.classname'), assumes you already have the starting elem to search from
angular.element(elem.querySelector('.classname'))
Note: If you're looking to do this from your controllers you may want to have a look at the "Using Controllers Correctly" section in the developers guide and refactor your presentation logic into appropriate directives (such as <a2b ...>).
angualr uses the lighter version of jquery called as jqlite which means it doesnt have all the features of jQuery. here is a reference in angularjs docs about what you can use from jquery.
Angular Element docs
In your case you need to find a div with ID or class name.
for class name you can use
var elems =$element.find('div') //returns all the div's in the $elements
angular.forEach(elems,function(v,k)){
if(angular.element(v).hasClass('class-name')){
console.log(angular.element(v));
}}
or you can use much simpler way by query selector
angular.element(document.querySelector('#id'))
angular.element(elem.querySelector('.classname'))
it is not as flexible as jQuery but what
If elem.find() is not working for you, check that you are including JQuery script before angular script....

Complex angular js ng-class

I have the component and have a problem setting the css class to it.
I want it to always have a class of "box", then to have additional classes specified by the directive "class" argument and one conditional class "mini".
Conceptually what I want to achieve is something like this:
<div class="box {{class}}" data-ng-class="{mini: !isMaximized}">
...
</div>
The problem is that when I set the class html attribute, the ng-class attribute is omitted.
How to make my example work without changing the controller? Is it even possible, or should I set the class in the controller instead (which I wish to avoid)?
A quick solution would be define the box class inside ng-class attribute:
<div data-ng-class="{mini: !isMaximized, box: true}"></div>
If you want to include a scope variable as a class, you can't use ng-class:
<div class="{{class}} box {{!isMaximized && 'mini' || ''}}">
Angular expressions do not support the ternary operator, but it can be emulated like this:
condition && (answer if true) || (answer if false)
I needed multiple classes where one was $scope derived and others were literal classes. Thanks to the hint from Andre, below worked for me.
<h2 class="{{workStream.LatestBuildStatus}}"
ng-class="{'expandedIcon':workStream.isVisible, 'collapsedIcon':!workstream.isvisible}">{{workStream.Name}}</h2>
Edit: for newer versions of Angular see Nitins answer as it is the best one atm
For me, this worked (I'm working on AngularJS v1.2.14 at the moment so I guess 1.2.X+ should support this, not sure about the earlier versions):
<div class="box" data-ng-class="{ {{myScopedObj.classesToAdd}}: true, mini: !isMaximized }"></div>
I replaced your {{class}} with {{myScopedObj.classesToAdd}} to show that any scoped variable or even a bit more complex object can be used this way.
So, every DIV element crated this way will have "box" class and any class contained within myScopedObj.classesToAdd (useful when using ng-repeat and every element in the array needs to have a different class applied), and it will have the "mini" class if !isMaximized.
Another way to do this without double curly braces and includes scope variables, tested with angular v1.2+.
<div ng-class="['box',
aClass,
{true:'large': false: 'mini'}[isMaximized]]"></div>
It's also rather nice because the variable can use different types as a index without increasing complexity using ternaries. It can also remove any need for negations ;)
Here is a fiddle link
You can use simple expression given below
ng-class="{'active' : itemCount, 'activemenu' : showCart}"

Resources