ng-show and ng-if lags to hide content - angularjs

I have the following in to show and hide the clear button based upon if the searchQuery is empty or not. When a user starts typing in the input box, the button shows instantly.
However, when the user either clicks the clear button or deletes all input, there is a noticeable lag before the clear button is removed. I have tried ng-show as well, and have received the same results. Any ideas why this lag might exist?
HTML
<button ng-if="search.cardsQuery.length" class="button-icon" ng-click="clearSearchQuery()">
<i class="ion-android-close search-cards"></i>
</button>
CONTROLLER
$scope.clearSearchQuery = function() {
$scope.search.cardsQuery = '';
};

Check the css class on the element you're applying ng-if/ng-show to. Look for the transition effect. If the class has a transition, it may be the cause to the delay:
.button-icon {
transition: all .5s;
}

Its a common problem seen among the developers. Even trying with ng-if causes the same issue. I can suggest a simple solution for you.
Open your css file for the particular html file and add below line.
**.ng-hide { display: none !important }**
Hope, it will help.

$scope.$evalAsync();
Worked for me :)

Related

AngularJS - div still shows even without condition

Ok, I know that title could use some work, but I'm not sure how else to put it.
Here's the setup.
I have a (potentially) massive table that gets generated via an ng-repeat. All the rows need to be editable but, when the dataset is so large, all those bindings slow things to a crawl. I could literally be waiting upwards of 20 seconds for large sets to load!
We noticed that dumping the data in a read-only state significantly decreased the load time. So, we came up with the idea of loading it read-only, but, when the table row was clicked, it became editable. This is accomplished like so. I have two cells output. editableRow is initially false. When the row is clicked, editableRow becomes true. The idea being that, when editableRow becomes true, I see the other cell.
(proprietary code obfuscated)
<TABLE-CELL class="value-col" ng-if="readtime.editableRow === true">
<input type="text"
name="readingTime"
ng-model="<data model>"
ng-disabled="<param>"
ng-change="<function>"
ng-class="<classes>"
/>
</TABLE-CELL>
<TABLE-CELL class="value-col" ng-if="readtime.editableRow === false">
<input type="text"
placeholder="{{<data model>}}"
ng-class="<classes>"
/>
</TABLE-CELL>
The problem is, on the click, for a tiny fraction of a second both cells are visible. It really is only visible on the first click. Subsequent clicks still do it, but it goes so fast that the human eye can't catch it. I know it's there since I slowed everything down with a breakpoint on the mouse click. This also revealed that this happens as the value turns true - turning on the first cell, but the second one doesn't disappear in the same moment. So, it causes a "flicker" of sorts. This seems to happen outside my actual code, inside the jQuery, so I'm not sure how to short circuit it.
I've tried playing with using ng-show/hide instead, which worked a little bit, but also totally negated the time-saving aspect, since it actually renders everything, and it took a long time. I've also tried ng-cloak with no effect whatsoever.
The breakpoint that it keeps stopping on (when I told it to stop on event listeners to do with the mouse click) is the following code in jquery.js:
if ( !(eventHandle = elemData.handle) ) {
eventHandle = elemData.handle = function( e ) {
// Discard the second event of a jQuery.event.trigger() and
// when an event is called after a page has unloaded
return typeof jQuery !== strundefined && jQuery.event.triggered !== e.type ?
jQuery.event.dispatch.apply( elem, arguments ) : undefined;
};
}
It hits that line about 4 times, and, on the last one, both cells are visible. Then, the second one disappears.
I'm out of ideas and would appreciate any thoughts on this.
I finally found an answer that works!
On this page: disable nganimate for some elements the answer right BELOW the accepted answer is what finally worked!
To disable ng-animate for certain elements, using a CSS class, which follows Angular animate paradigm, you can configure ng-animate to test the class using regex.
Config
var myApp = angular.module("MyApp", ["ngAnimate"]);
myApp.config(function($animateProvider) {
$animateProvider.classNameFilter(/^(?:(?!ng-animate-disabled).)*$/);
})
Usage
Simply add the ng-animate-disabled class to any elements you want to be ignored by ng-animate.

Angular fade animation happening at wrong time during load

We have a popup modal in our Angular application which contains, among other things, a <span> element which should appear, and then fade, when a certain button is clicked. This all works as expected. But there is one problem. When the modal first loads, the <span> momentarily appears, then fades out. The behavior is consistent with the <span> having ng-show set to true, but then set to false at the time the modal is loaded, triggering the fade out transition.
Here is the <span>:
<span id="fileLinkCopied" data-ng-show="copyLinkClicked"
class="text-fade float-right">file copied to clipboard</span>
But the varible $scope.copyLinkClicked is set to false when the controller loads, and hence we would expect to never even seen the <span> being rendered at load time.
Here is the relevant CSS:
.text-fade {
transition: all linear 500ms;
opacity: 1;
}
.text-fade.ng-hide {
opacity: 0;
}
This problem was discussed in this SO question, but no definitive solution was given. We have pondered turning off the animation for this element, but this may have problems as well.
Any solution which gets the job done within normative usage of Angular would be greatly appreciated.
One quick workaround would be to add another span tag as the parent of your span element. You can then add an ng-if condition to the parent element and use a variable that is set to false initially in the if condition. This would make sure that the child span is not rendered when the page loads and therefore you wouldn't see the animation. You can then set the value of that variable to true on document ready event.
Here is the <span>:
<span ng-if="firstLoad "><span id="fileLinkCopied" data-ng-show="copyLinkClicked"
class="text-fade float-right">file copied to clipboard</span><span>
In your controller add the following:
$scope.firstLoad = false;
angular.element(document).ready(function () {
$scope.firstLoad = true;
});

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.

Angular: Fading out element and then setting display none

When I click an element, I'd like another element to first fade out, and then be set to display: none.
I have the following code:
Partial:
<div class="main_menu_image" ng-class="{ fadeOut : MenuOpen==true }" /></div>
<div class="button" ng-click="ActivateMenu()"></div>
Then in my controller:
$scope.MenuOpen = false;
$scope.ActivateMenu = function(){
$scope.MenuOpen = $scope.MenuOpen === false ? true: false;
}
So when I click the button, element main_menu_image gets the class fadeOut. So it now fades out. But after the fading animation completes I would also like to set display to none on main_menu_image so it is completely hidden.
I don't want to resort to jQuery. Is there an Angular approved way of doing this?
Yes it's very easy to do:)
Like Svein says, you can use ng-show, and you can use ng-hide.
Working fiddle here
This hides things instantly though. But you can for example set a timeout, via the $timeout service, and set your hiding boolean in that way.
You can also use ng-if, this actually removes the element from the DOM if the condition is not met, rather than just setting display:none.
Update: Here's a more proper fiddle showcasing what you're trying to do
You can use ngShow. If you use the ngAnimate module, you'll have built in support for animations for most built-in Angular directives.
See here for more information:
https://docs.angularjs.org/guide/animations

How to remove draggability from an element with Ext JS?

I have a div that I want to make draggable or not, depending on the state of some other stuff on my page. I seem to be able to easily make it draggable, but I can't seem to figure out how to best remove the draggability from the div.
I am making it draggable with:
var dd = Ext.create('Ext.dd.DDProxy', mydiv, 'myDDGroup', { isTarget: false });
And I've tried to then remove the draggability by removing the only group it's a member of
dd.removeFromGroup('myDDGroup');
and just destroying the dd object with
delete dd;
Neither of these seem to actually keep me from starting a drag on the element. I suspect I should be able to use the b4Drag override in some way to simply cancel a drag of my div before it even begins, rather than toggling the draggable state of the div at all, but I can't seem to find docs on how I might cancel the drag during the b4Drag call.
So, how can I make a div undraggable after I have already made it draggable?
Seems to be working for me.
Here is the JSFiddle http://jsfiddle.net/01gx33h0/
var dd = Ext.create('Ext.dd.DDProxy', 'test123', 'myDDGroup', { isTarget: false });
Ext.fly('btn123').on('click', function() {
dd.removeFromGroup('myDDGroup');
});
Can you give me the sample code where it is not working. And what version of ExtJs are using?
You have to unreg. Not removeFromGroup.
It just removes from group. But events are not removed on that element.
dd.unreg();
https://fiddle.sencha.com/#fiddle/1eun
When looking at something specific that needs to be dragged, you might consider that allowing dragging is something users expect, for general ease of use you might try the ondragstart="return, this could be appended to your images, or links like so:
<a ondragstart="return false" href="#link">link</a>.

Resources