Conditionally displaying template content inside ng-repeat - html

I'm using ng-repeat to loop render an angular template potentially thousands of times, and wondering what is the most efficient way to go about conditionally altering it's display. For example, each item in the loop has a 'type', which has a corresponding icon. There are a few ways to go about this:
Purely css/html - this seems the most efficient angular-wise, but will mean a lot more html in the DOM
<li class="{{item.type}}">
<i class="type-1-icon"></i>
<i class="type-2-icon"></i>
<i class="type-3-icon"></i>
</li>
And then in the css:
li i { display:none; }
li.type-1 i.type-1-icon { display:block; }
li.type-2 i.type-2-icon { display:block; }
li.type-3 i.type-3-icon { display:block; }
Using ng-if - tidies up the dom, but could be less efficient evaluating the ng-if for lots of records?
<li>
<i class="type-1-icon" ng-if="item.type == 'type-1'"></i>
<i class="type-2-icon" ng-if="item.type == 'type-2'"></i>
<i class="type-3-icon" ng-if="item.type == 'type-3'"></i>
</li>
Using ng-switch
<li ng-switch on="item.type">
<i class="type-1-icon" ng-switch-when="type-1"></i>
<i class="type-2-icon" ng-switch-when="type-2"></i>
<i class="type-3-icon" ng-switch-when="type-3"></i>
</li>
Using ng-show (same for ng-hide). Similar to #1 I'm guessing
<li>
<i class="type-1-icon" ng-show="item.type == 'type-1'"></i>
<i class="type-2-icon" ng-show="item.type == 'type-2'"></i>
<i class="type-3-icon" ng-show="item.type == 'type-3'"></i>
</li>
Anyway, I realise that all 4 approaches will work fine, but I'd love to learn a bit more about which is best for a potentially large dataset and why. Thanks!

Related

Asp Mvc views with jQuery

I have two views and each view contains an link with data-action attribute to call jQuery function called toggle menu like this:
<div id="hide-menu" class="btn-header pull-right">
<span>
<a href="javascript:void(0);" class="toggleMenu" data-action="toggleMenu" title="Collapse Menu")">
<i class="fa fa-reorder"></i>
</a>
</span>
</div>
jQuery:
toggleMenu: function () {
if (!$.root_.hasClass("menu-on-top")) {
$('html').toggleClass("hidden-menu-mobile-lock");
$.root_.toggleClass("hidden-menu");
$.root_.removeClass("minified");
} else if ($.root_.hasClass("menu-on-top") && $.root_.hasClass("mobile-view-activated")) {
$('html').toggleClass("hidden-menu-mobile-lock");
$.root_.toggleClass("hidden-menu");
$.root_.removeClass("minified");
}
}
one of the views calls the function properly but the another doesn't, What is the possible reason for that??
in fact I haven't known the actual reason of the issue, maybe as Ramesh said in the comments was the problem.
I solved it by putting the function in the same document (not in another js file) and in the element, I have used onClick attribute to execute the function.
<div id="hide-menu" class="btn-header pull-right">
<span>
<a href="javascript:void(0);" class="toggleMenu" onclick="toggle()" title="Collapse Menu">
<i class="fa fa-reorder"></i>
</a>
</span>
</div>
<script>
function toggle() {
if (!$.root_.hasClass("menu-on-top")) {
$('html').toggleClass("hidden-menu-mobile-lock");
$.root_.toggleClass("hidden-menu");
$.root_.removeClass("minified");
} else if ($.root_.hasClass("menu-on-top") && $.root_.hasClass("mobile-view-activated")) {
$('html').toggleClass("hidden-menu-mobile-lock");
$.root_.toggleClass("hidden-menu");
$.root_.removeClass("minified");
}
}
</script>

click event not working in angular 8 in mobile device

A click event is not working on mobile devices. But it's working fine on other devices. If anyone knows please help to find a solution.
app.component.html:
<ul class="resp-tabs-list">
<li *ngFor="let topic of topicsList;let i=index;"(click)="getContentList(topic)" >
<i class="fa fa-book"></i> {{topic.name}}
<div *ngIf="topic.obtainMarks> 0" style="color: black">Competency level : {{topic.obtainMarks}} %
</div>
</li>
</ul>
app.component.ts:
getContentList(topic: Topics): void {
console.log(topic);
}
Try using ng-click instead of (click). I hope it will work.
<li *ngFor="let topic of topicsList;let i=index;" ng-click="getContentList(topic)">

class="js-dropdown" and class="js-dropdown-menu" broke after angular upgrade

We upgraded from Angular 4 to Angular 8.1 and a lot of our drop downs are broken. From what I can tell they all contain these two style classes: the class js-dropdown and js-dropdown-menu. We can't find where these style classes are coming from or how they work. It's hard to search these terms on google because there's no way to have a must-include for hyphens, that I know of. Here's an example of the html:
<div class="select-wrapper" id="searchOption">
<li class="dropdown nav__item is-parent" tabindex="0" style="outline: 0" (blur)="closeDropdown($event)">
<div class="select-dropdown js-dropdown">
<span class="selection">{{ searchType }}</span>
<i class="nav__icon nav__icon--dropdown"></i>
</div>
<ul class="details-search nav__menu js-dropdown-menu">
<li (click)="optionSelected($event, 1)">
<a class="nav__link">Option 1</a>
</li>
<li (click)="optionSelected($event, 2)">
<a class="nav__link">Option 2</a>
</li>
<li (click)="optionSelected($event, 3)">
<a class="nav__link">Option 3</a>
</li>
</ul>
</li>
</div>
Does anyone have any insight to the class js-dropdown and js-dropdown-menu and how to fix them after this upgrade?
Update: so i think i found out where the js-dropdown style class comes from.... it doesn't come from any style... it's just used as a label and component.js looks for that label to show or hide it. The now is that component.js function isn't getting called. Anyone know how to fix this?
$('#app-container').on('click', '.js-dropdown, .js-dropdown-menu > *', function(event){
event.preventDefault();
var that = this;
var parent = $(this).closest('.is-parent');
//is our dropdown open?
if(!parent.hasClass('is-open')){
//... then open it.
parent.addClass('is-open');
//handle clicking away
$(document).one('click', function closeMenu(docEvent){
//if the parent does not contain the clicked element...
if($(parent).has(docEvent.target).length === 0) {
//close it.
parent.removeClass('is-open');
} else {
// else, set up another listener to check the next user click.
$(document).one('click', closeMenu);
}
});
} else {
// ...else we close it.
parent.removeClass('is-open');
}
event.stopPropagation();});
Figured it out. We were not loading a components.js file (as well as other scripts) in the angular.json file. Our previous version of angular did not contain an angular.json file.

ngClass with multiple conditions false condition not working

I'm trying to use [ngClass] with multiple conditions to change the caret of a open/close panel.
Currently the down arrow works flawlessly.
When I click the arrow and the condition changes to false, it changes the icon to a empty box and is not recognizing the correct class name.
<i [ngClass]="{'fa fa-caret-up pull-right': isActive4 == true,
'fa fa-caret-down pull-right': isActive4 == false}"
(click)="section4Click()"></i>
The section4Click() changes isActive4 to true/false depending on what it was before.
When I inspect element of the box that shows up after I click the down caret (which works), I get the following class name...
fa-caret-up
instead of...
fa fa-caret-up pull-right
Anyone know why this occurs? It seems like its doing half the job...
I've also tried just doing isActive4 and !isActive4, and the same happens.
It's hard to tell from looking at your code. But you can try this:
<i class="fa pull-right" [class.fa-caret-up]="isActive4" [class.fa-caret-down]="!isActive4" (click)="section4Click()"></i>
I would also recommend printing the values to see what you get:
<p>{{ isActive4 === true }}</p>
This will work.
<i class="fa pull-right" [ngClass]="{'fa-caret-up': isActive4 == true,
'fa-caret-down': isActive4 == false}"
(click)="section4Click()"></i>

Duplicate id issue, cannot reuse an id

I'm working on the following script :
http://www.andwecode.com/playground-demo/pop-up-login-signup-box-jquery/#
I've modified the Gmail and Facebook boxes in it, and I would like them to present a login form when I click on them. I tried this with Gmail box :
<a href="#1" class="social_box google" id="login_form" >
<span class="icon"><i class="fa fa-google-plus"></i></span>
Basically, I added the ID : (id="login_form") and it worked fine !
The problem is that you can use the ID just once. and when you do that the login button became useless ..
any idea how to make all the boxes go for the login form ?
The reason the functionality works only for one scenario is that 'ID's have to be unique', if you have duplicate ID's it will recognize only the id for the first element and it will ignore the rest.
You can achieve your result in two ways
1) have same class for all the boxes fb box,google box etc.
Example: box-form class for all the boxes
HTML:
<a href="#1" class="social_box google box-form" >
<span class="icon"><i class="fa fa-google-plus"></i></span>
<a href="#1" class="social_box fb box-form" >
<span class="icon"><i class="fa fa-google-plus"></i></span>
Jquery:
$('.box-form').click(function() {
//code
});
2) Apply different id for each box and combine the id's in jquery
HTML:
<a href="#1" class="social_box google" id="login-form" >
<span class="icon"><i class="fa fa-google-plus"></i></span>
<a href="#1" class="social_box fb" id="fb-form">
<span class="icon"><i class="fa fa-google-plus"></i></span>
Jquery:
$('#login-form, #fb-form').click(function() {
//code
});