Toggle two classes with AngularJS / jqLite on click - angularjs

I wan't to get a slideIn / slideOut animation by toggling the classes slideInRight and slideOutRight to a ul element.
I've tried it in different ways but I it only works with one className.
How can I add the class slideInRight on the first, and the class slideOutRight on the second click on my ul element with the class dropdown-menu?
I've tried it this way:
angular.element('.dropdown-toggle').on('click', function(){
angular.element('ul.dropdown-menu').toggleClass('slideOutRight slideInRight');
});
What am I doing wrong?
Hope you can help.
UPDATE:
Here is a Plunker of the current state of my code. This way only the slideInRight animation works. If I click the button again, the ul disappears without the slideOutRight animation.
What's wrong?

You may want to try using angular's ng-class?
I'm sort of new to angular, but the way I did it was like this:
<ul class="dropdown-menu" ng-class="ulOpen ? 'slideOutRight' : 'slideInRight'">
and the js
angular.element('.dropdown-toggle').on('click', function(){
if($(this).hasClass('.slideOutRight')) {
ulOpen = true;
} else {
ulOpen = false;
}
});

Add ulOpen to your controller as a scope variable
Controller
$scope.ulOpen = false;
HTML
Then you should rely on the angularjs directive ng-click to set the value of ulOpen:
<button class="dropdown-toggle" type="button" ng-click="ulOpen=!ulOpen">Toggle Class</button>
And ng-class to switch class based on the value of ulOpen:
<ul class="dropdown-menu" ng-class="slideOutRight: ulOpen, slideInRight: !ulOpen">
In general, I would recommend whenever possible you find the pure angularjs solution. I find very few cases where there isn't a native angular directive that can handle what I would otherwise attempt to do in jquery.

Related

angular element addClass active fails

on my page I´ve loaded angular and bootstrap. On default loading the panel "#default" is active. In an other case the page get a variable ("name") with. This variable is a string which identifies an other panel. Finally this name panel should be shown. In the code below the remove works but the add not.
if (name) {
angular.element("#deault").removeClass("active");
angular.element(document.querySelector("#some-other")).addClass("active");
angular.element("#other-"+name).attr("aria-expanded"));
angular.element("#other-"+name).attr("aria-expanded", true)
document.getElementById("#other-"+name).click()
}else{
log('no Id "#other-"+name existent')
}
log('test')
}
I'm replying because I'm assuming you want to highlight an "active" element.
In angular there's ng-class directive where you can assign class to an element based on a condition.
https://docs.angularjs.org/api/ng/directive/ngClass
based on your comment, I think it doesn't work because when you try to addClass, the DOM is not ready yet. so try this:
angular.element(document).ready(function () {
angular.element(document.querySelector("#some-other")).addClass("active");
});
update
based on your comment I think you should just simply do this
on the other-panel DOM element add ng-class like
<div id="other-panel" ng-class="{active: name}">
...
</div>
in your controller
$scope.name = name #this name should be the name you used in your old code, I guess you get it from $location service

ui.bootstrap popover-is-open doesn't work properly

I want not to show ui.bootstrap popover by using popover-is-open directive. For example, in template:
<button class="fa fa-link add-link"
uib-popover="popover"
popover-is-open="isOpen"> Show popover </i>
And in controller:
angular.module('demoModule').controller('PopoverDemoCtrl', function ($scope) {
$scope.isOpen = false;
});
See plunkr
I am expecting that popover should never be opened, but it opens on click on it. It seems that popover-is-open affects only first angular compiling. Any ideas?
upd: Actually, i want not to show popover only in some cases, in other cases it should be shown. For example, i have download-dialog popover and i want to show it only if size of file is greater than some limit.
The popover-is-open is only for the initial behavior, i.e. if it evaulates to true, then the popover opens instantly even without a click. If you change the value of isOpen to true in your plunkr, you see that (my example plunkr).
What you want is the popover-enable attribute:
<button class="fa fa-link add-link"
uib-popover="popover"
popover-enable="isOpen">Show popover</button>
Update for the question update:
You are free to evaluate any boolean expression in the popover-enable attribute instead of the static isOpen which always evaulates to false in your example.
I have created an advanced plunkr to show that:
<input type="text" ng-model="downloadSize">
<button class="fa fa-link add-link"
uib-popover="popover"
popover-enable="isOpen()">Show popover</button>
with the controller code
$scope.isOpen = function() { return $scope.downloadSize > 100; }
You have a new text box where you can enter a number to simulate the download size. When it gets > 100, the popup will be enabled.
In order to handle the open state whit the popover-is-open value you must set popover-trigger="none" or maybe popover-trigger="'none'". As it says in the docs
Using the 'none' trigger will disable the internal trigger(s), one can
then use the popover-is-open attribute exclusively to show and hide
the popover.
Use
$scope.$apply(function () {
$scope.isOpen = false;
});
method for applying this property

Is there any way to delay ng-view?

I have layout where I have:
<li ng-click="GetLoader();">ACCOUNT</li>
<li ng-click="GetLoader();">SETTINGS</li>
On the index page, I have a menu and ng-view where I can change pages on a click
Also included on the index page is a spinner.
<div class="loading" ng-show="ticketloading" ng-init="GetLoader()">
<div>
<img class="spinner" ng-src="~/Images/ajax-loader.gif" />
</div>
</div>
In my script I have -
$scope.GetLoader = function() {
$scope.ticketloading = true;
loader.css("z-index", "1");
}
My problem is that when a user clicks on "Account" it gets loaded, but just for few milliseconds. Then it changes to all blank. I receive data from ng-view. My question is how can I delay showing ng-view to show the loader a little bit longer.
Thanx in advance!
First of all you should avoid using DOM manipulations in controller. In your case it's better to use declarative ngClass directive to set opacity.
Then your actual issue is that you don't want to use static setTimeout to hide loaded, but rather listen $routeChangeSuccess:
$rootScope.$on('$routeChangeSuccess', function() {
$rootScope.ticketloading = false;
});
and use this loading flag in template like you are currently doing.
You can put above event listener in run block for example.
You can add property in your controller, for example dataLoading and add ng-if attribute to ng-view like this:
layout
<div ng-view ng-if="!dataLoading">
controller
function loadData()
{
var self = this;
self.dataLoading = true;
dataService.loadData(params, function(){
...
self.dataLoading = false;
});
}

Angular bootstrap animate.css remove animation

In my project, thanks to animate.css, I can have entry animations like this:
<div class="row animated fadeInDown" ng-show="someCondition">
This is great. When someCondition is true, the div appears with an animation. What I don't understand is how to cause the reverse to happen. Say, in my controller I set someCondition = false;. What should I do in the markup to make the div do a fadeOutUp?
I tried putting the fade out in the class="" attribute, but that just conflicts with the fade in. I also tried ng-class={} but I don't know what condition is true when something is being removed.
Try a conditional ng-class:
<div ng-class="someCondition && 'fadeInDown' || 'fadeOutUp'">
UPDATE:
Use a variable class name in your markup:
<div ng-class="someClass">
and add a watch to the controller to apply the proper class name:
$scope.$watch('someCondition', function(newval, oldval){
if($scope.someCondition){
$scope.someClass = 'fadeInDown';
} else {
$scope.someClass = 'fadeOutUp';
}
});
In the following fiddle I added a setInterval to simulate the condition change:
http://jsfiddle.net/F52y5/59/

Using template in angular directive works but templateUrl doesn't work

I have the following example.
In the example I'm using kendo menu with angular directive for kendo. Each item in the menu is my custom directive. When I use template inside the directive is works fine but when I use templateUrl it doesn't work, any ideas?
The reason I am using a custom directive for the menu is because I couldn't find out how to register click of a specific item in the menu. There is an event in kendo menu (select) that I can use to register all menu item selections but then in the callback function I don't know which item was selected because there is no id on the DOM element and I also don't get the model data so there is no indication of what was clicked. How can I know that the "Open" menu was clicked for example?
1) The directive kendo-menu bootstraps the kendo menu from it's content. If you are using a template all is fine because the sub html structure is created before kendo bootstraps the menu. If you are using a templateUrl the template gets loaded and if the data arrive angular updates the dom in your directive. But at this time the kendo-menu directive is ready with bootstrapping the menu, so it will not be aware of any changes angular made on the dom. How to solve this: as you did - only use inline templates or put the templates to the templateCache before you used the template. But this requires a lot of changes to your code.
2) I am not quite sure where your problem is. But you may register a ng-click function like this:
<ul kendo-menu>
<li ng-repeat="item in menuData.dataSource">
<label>{{item.text}}</label>
<ul>
<li ng-click="menuSelected(subitem)" ng-repeat="subitem in item.items/>
<label>{{subitem.text}}</label>
</li>
</ul>
</li>
</ul>
in your controller you have access to the selected item:
$scope.menuSelected = function(selected){
console.log(selected);
}
here is the working PLUNKR
If you populate the menu from a dataSource you can specifiy a select function in your menuData:
$scope.menuData = {
select: function(e) {
console.log(e);
console.log(e.item.textContent);
},
dataSource: [ ... ] };
e.item.textContent is the value that you have provided in your dataSource as text.

Resources