Ng-Show & Ng-Hide, what is the difference? - javascript

I'm teaching myself Angular-JS and I can't find any sort of definitive answer on what the difference between ng-show and ng-hide is. To me they appear to be functionally equivelant.
I understand the difference between them and ng-if as ng-if actually removes the watchers etc. whereas show and hide seem to serve the same purpose.
Is there any kind of performance gain using one over the other or is there situations where one is preferable over the other OR is it just two sides of the same coin and you use whichever makes more logical sense to you?
Apologies if this has been asked/answered elsewhere but I couldn't find it.

They do the opposite of each other and can be used as you want.
I think this comes down to coding preference, as some people like to write their code so that they use the method if the value is going to be true, instead of using not false!
<div ng-show="true">
instead of :
<div ng-hide="!true">

This directives differs in one row:
ngShowDirective:
$animate[value ? 'removeClass' : 'addClass'](element, NG_HIDE_CLASS, {
tempClasses: NG_HIDE_IN_PROGRESS_CLASS
});
ngHideDirective:
$animate[value ? 'addClass' : 'removeClass'](element,NG_HIDE_CLASS, {
tempClasses: NG_HIDE_IN_PROGRESS_CLASS
});
Just opposite applying of ng-hide CSS class.
As you can see, there is NG_HIDE_IN_PROGRESS_CLASS.
It's ng-hide-animate css class which temporary applied in both cases.
You can use it to animate element appear/disappear.
You should use two selectors to implement bidirectional animation:
.animate-hide for appear
.animate-hide.ng-hide for hide

ng-show and ng-hide just set the display to 'None' but ng-if actually removes the element from DOM.
As for as performance is concerned, I think it does not make any huge difference but since ng-if removes all event handlers attached to this element and its children and also the DOM element so I think ng-show or ng-hide will be faster.

ng-show and ng-hide applies display: none !important to your html with one of these directives. There is no difference between ng-show and ng-hide: it is only semantic and your choice.
So, let's suppose you have next html:
<div ng-show='condition'><p>{{text}}</p></div>
<div ng-hide='condition'><p>{{text}}</p></div>
So the in this case if your condition is true then first line of code will shows your html and hides it if your condition is false. Second line with ng-hide will do the same things but with opposite conditions: it will hides your html if your condition is true and shows it if condition is false

Related

Accessibility and Angular: proper way to use aria-expanded and aria-controls - what options are acceptable among several described

If I validate this code on accessibility issues here https://validator.w3.org/nu/#textarea , then I don't have any errors:
<button aria-controls="t1" aria-expanded="false">Show</button>
<div id="t1">Some text</div>
Unfortunately, I use conditions ( *ngIf in Angular) which removes the <div> from the DOM until aria-expanded is true (myBoolValue is false when page loads):
<button aria-controls="t1" aria-expanded="myBoolValue">Show</button>
<div *ngIf="myBoolValue" id="t1">Some text</div>
As result, when validating, I get an error:
Error: The aria-controls attribute must point to an element in the same document.
which is clear: no id="t1" is in the DOM.
I should use some technique to make it different.
As far as I understand, there might be several options (please correct):
Option 1 (to use an additional div as wrapper which always is in the DOM):
<button aria-controls="t1" aria-expanded="myBoolValue">Show</button>
<div id="t1"><div *ngIf="myBoolValue">Some text</div></div>
Option 2 (display: none; instead of removing from DOM):
<button aria-controls="t1" aria-expanded="myBoolValue">Show</button>
<div *ngClass="{hidden: !myBoolValue}" id="t1">Some text</div>
where .hidden {display: none;}
Option 3 (no aria-control - no errors):
<button aria-expanded="myBoolValue">Show</button>
<div *ngIf="myBoolValue">Some text</div>
Are Option 1, 2, 3 good enough?
Is Option 3 valid at all? Is it an acceptable approach in case if Option 1 and Option 2 can't be easily implemented?
It's better to have the aria-controls attribute and have it always pointing to an existing element if you can keep it that way.
But all of your solutions are acceptable, even your #3.
Currently, assistive tools don't actually use aria-controls a lot. Some of them provide shortcut to quickly switch from controlling to controlled element and back, but that's almost all.
Therefore it's not a big loss if you must remove it completely as in your solution #3.
However, we can never imagine what aria-controls may be used for in the future, and so, solutions #1 and #2 would certainly be better than #3 at long term, if you can do it.
Just in case.
Solution #2 is maybe slightly better than #1 because you are sure to don't break anything. It could have an importance if the controlled element is interactive and focusable.
Focusing the parent instead wouldn't make sense and it could cause subtle focus issues afterwards.
IN the other hand, you are guaranteed by the standard that display:none always means never rendered at all, whatever the kind of rendering it could be (screen, speech, braille, or whatever hasn't yet been invented).
So, by order of preference, I would recommend #2, #1, #3.

Angular 2 ng-if fails

Trying to apply css styles dynamically for the element which has ng-if condition.
Works fine, if the condition is true. Is there any way that I can modify the element even if the condition fails. I know I can find the element (by getElementsByClassName) and modify but is there any other better solution other than this?
ex:
<span *ngIf="orderBy=='asc'" [ngStyle]="{'height': value+ '%'}"></span>
<span *ngIf="orderBy=='desc'" [ngStyle]="{'height': value+ '%'}"></span>
You can use ngClass for that. Add class based on the conditional value.
[ngClass]="{orderBy=='asc'? 'someclass': 'otherclass'}"
You can write seperate styles for each of the class.
You can use ng-class to achieve this
ng-class="{'classname':orderBy==='asc',
'classname':orderBy==='desc'}"

Using jqLite to hide and show html elements

Like any normal person creating a web application using AngularJS, I initially tried using ng-hide/ng-show to make certain elements visible under certain conditions. For some reason, this doesn't want to work, and the code is too complex for me to recount it here. I figured it would be easy to use jQuery (or at least as much jQuery as Angular has built into it). This is what I have so far:
angular.element(document.querySelector([ELEMENT ID])).off();
The above line works for the purposes of hiding, but I can never get it back. In case you're wondering, I'm trying to hide buttons for otherwise unrelated actions. Using ".on()" for the code above doesn't work. How does this line need to be written in order for the element to disappear? More importantly, How do I make it reappear?
ng-show and ng-hide work with boolean values. Don't use jQuery inside the controllers. If you are needy to use that, create directives for that purpose.
Create flag variable in scope of controller. Set it to true or false
Now ng-show will show the element if it receives boolean value as true and will hide if it receives false.
Vice versa for ng-hide, it will hide if it received true and show if receives false.
So decide between either one of them, don't use both. So considering flag name is active and it is set to true and you want to show button in beginning. The code can be:
angular.module('demo', []).controller('DemoCtrl', function($scope){
$scope.active = true;
});
And the template will look like:
<div ng-app="demo">
<div ng-controller="DemoCtrl">
<button type="button" ng-click="active = false" ng-show="active">Hide Me</button>
<button type="button" ng-click="active = true" ng-hide="active">Reset</button>
</div>
</div>
We need a small css for this purpose:
.display-hide {
display: none;
}
Lets say there is an validation summary we are showing on the page;
<div class="alert alert-danger display-hide">
<button class="close" data-close="alert"></button>
<span>
#Html.ValidationSummary(false)
</span>
</div>
And with using jQuery;
jQuery(document).ready(function () {
#if(!ViewData.ModelState.IsValid) {
<text>
$('.alert span').parent().removeClass("display-hide");
</text>
}
else
{
<text>
$('.alert span').parent().addClass("display-hide");
</text>
}
});
You can use this trick for any html element.
on and off methods are not for showing/hiding elements but for adding and removing event listeners. I think by accident your element was already hidden and that led you to believe off hides element.
If you really can't use ng-hide/ng-show I suggest you use addClass and removeClass (instead of off and on) to add/remove 'hidden' class to your element. This class could would set the elements display to none.
However I encourage you to show the angular code so we can help you solve this using ng-show.

How to account for ng-if when verifying if an element is present?

I have a div on my page that is hidden by ng-if sometimes. I want to devise a test that checks whether the element is present ONLY when it should be present. ng-if completely removes the element from the DOM if the test fails.
I tried to write an if statement in protractor that evaluated the same thing that my ng-if is evaluating and then expect a value only if that evaluated to true but it looks like protractor isn't aware of non-dom elements, which makes sense but leaves me a little stumped as to what to do. Any ideas?
There is .isPresent() method that checks for presence of an element in the DOM:
expect(elm.isPresent()).toBe(false);
You can also use .evaluate() to evaluate the ng-if value:
expect(elm.evaluate("ng_if_value")).toBe(false);
For this solution, we need to check first, element is present or not
<div id="status" ng-if="data.isDeleted">
<span id="delete_status"> Deleted </span>
</div>
If data.isDeleted is true than we do expect further
var statusId= element(by.id('status'));
statusId.isPresent().then(function (present){
if(present){
expect(statusId.evaluate("data.isDeleted")).toBeTruthy();
expect(statusId.element(by.id("delete_status")).getText()).toContain("Deleted");
}
});

Difference between using hide, prop, attr or css to hide an element with JQuery

I have set up 4 divs to test the different results of using:
$("#div1").hide();
$("#div2").prop("hidden", true);
$("#div3").css("display","none");
$("#div4").attr("hidden", true);
I can see that the result is (I am using version 1.11.3):
<div id="div1" style="display: none;">Something</div>
<div id="div2" hidden="">Something</div>
<div id="div3" style="display: none;">Something</div>
<div id="div4" hidden="hidden">Something</div>
It seems kind of confusing to me to have four different ways of achieving pretty much the same result. I have seen some explanation in .hide() or display: none? jQuery but I wonder if someone can provide more information and mainly, when should I use which??
//this is a wrapper function. simply adds display none inline. for ease of use
$("#div1").hide();
//prop is used to manipulate any property on the object. hidden is a property. so it doesn't stop you from doing it.
$("#div2").prop("hidden", true);
//css is a wrapper for the style attribute. display is a valid css property so it won't stop it
$("#div3").css("display","none");
//this one seems odd. i thought it would be hidden="hidden" but anyway. attr() is used to change the attributes on the markup. hidden is a valid attribute so it doesn't stop you
$("#div4").attr("hidden", true);
It's all about your style of coding. If they all work, you get to use the one that you like best. Just try to be consistent if possible, imho.
There sure is a difference, but I'm not going to cover them all.
A real life story:
I just had a project, in which I needed to filter DOM elements by their display property.
Same DOM elements was set to 'none', by using .hide() and shown by setting .show()
This usage, while short and neat, made problems filtering by display property, as it always showed 'none' in a console output. Even if the element list showed 'block'.
So a caching occours using .hide()
You don't just wanna use whatever you like best. Only if you like best what works for your specific needs ;)

Categories