Display count of selected options using ng-select - javascript

I am using ng-select component to allow users to select multiple options from a list.
When 1 option is selected I want the option to be visible like normal. But, when 2 or more options are selected I want my custom template to display a summary like 2 Selected. Visual example:
My attempt at the custom layout in the template code is this:
<ng-template ng-multi-label-tmp let-items="items" let-clear="clear">
<div *ngIf="selectedCounter >= 1" class="ng-values-list">
<div class="ng-value" *ngFor="let item of items | slice:0:1">
<span class="ng-value-label">{{item.name}}</span>
<span class="ng-value-icon right" (click)="clear(item)">×</span>
</div>
</div>
<div *ngIf="selectedCounter > 1" class="ng-summary-list">
<div class="ng-value">
<span class="ng-value-label">{{ selectedCounter }} Selected</span>
</div>
</div>
</ng-template>
Which currently shows both the selected option, and the summary like this:
Is there anything I can do inside the template code to show only the summary when there is more than 1 option selected?

Shouldn't the first div be :
<div *ngIf="selectedCounter == 1" class="ng-values-list">
when selectedCounter = 2 both your if are true.

Related

How to collapse only selected row ? Angular

I want to toggle only the selected row, but I can't do that?
Check my code all and demonstration is here: https://stackblitz.com/edit/test-trainin-2-gv9glh?file=src%2Fapp%2Fapp.component.scss
I'm currently toggle all the row and I only want the row where it was clicked.
Here 90 line of code. Here is start:
<div class="column-holder" *ngFor="let training of trainingExercises; let i = index;">
<div class="single-exe" [class]="{ 'collapse-row' : collapse}">
<h1 class="exerciseNameAbsolute"> {{ training.exerciseName }}</h1>
<i (click)="collapse = !collapse" class="dx-icon-collapse dx-icon-custom-style"></i>
<div class="column-holder" *ngFor="let training of trainingExercises; let i = index;">
<div class="single-exe" [class]="{ 'collapse-row' : training.collapse}">
<h1 class="exerciseNameAbsolute"> {{ training.exerciseName }}</h1>
<i (click)="training.collapse = !training.collapse" class="dx-icon-collapse dx-icon-custom-style"></i>
This is the suggestion I made from the comment. Add a collapse property to each of your training variables and default it to true/false depending upon what state you want them to start out in. Change your [class] to look at that scoped variable, and when you click the element that toggles the collapse, toggle that variable on the training variable.

How can I show and hide a div based on what's clicked in another div in Vue js?

I have 2 divs, one that shows the names of the products(Product 1, Product 2... etc) and the other that shows the product articles(Product 1: Article 1, Product 2: Article 1, Product 2: Article 2... ). I would like to have a functionality where I click Product 1 and then Product 1's articles should appear. When I click another product, let's say Product 2 then Product 1's articles should be hidden and Product 2's articles are shown.
Like this:
CASE 1: When Product 1 is clicked
Product 1
Product 1's articles <--- Show div when page is loaded.
Product 1: Article 1
Product 1: Article 2
Product 2
Product 3
Product 4
CASE 2: When Product 2 is clicked
Product 1 <--- Hide div
Product 2
Product 2's articles <--- Show div
Product 2: Article 1
Product 2: Article 2
Product 3
Product 4
I have tried using the accordion by Boostrap Vue but this did not suit my needs in other requirements. This is what I have so far:
<div class="container">
<div
v-for="(product, productIndex) in productsandarticles"
:key="productIndex"
>
<div class="articlelistingdesktop">
<div class="productlisting"> <--- Product Names Div
{{ product[0].productNames['en'] }}
</div>
<div class="articlelisting"> <--- Product Articles Div
<h4>{{ product[0].productNames['en'] }} 's articles</h4>
<div
v-for="(productInner, productInnerIndex) in product"
:key="productInnerIndex"
>
<nuxt-link :to="'/' + productInner.title_slug"> . <--- Link to the articles
{{ productInnerIndex + 1 }}. {{ productInner.title['en'] }}
</nuxt-link>
</div>
</div>
</div>
</div>
</div>
All my data is coming from a JSON file and currently, my code shows all product names and their respective articles. I am trying to also avoid using jquery for my project. I would appreciate if someone could help.
Thanks!
Just use reactive property to track index of "active" product...
In your component:
data() {
return {
activeProductIndex: null
}
}
<div class="container">
<div
v-for="(product, productIndex) in productsandarticles"
:key="productIndex"
>
<div class="articlelistingdesktop">
<div class="productlisting" #click="activeProductIndex = productIndex">
{{ product[0].productNames['en'] }}
</div>
<div class="articlelisting" v-if="activeProductIndex === productIndex">
<h4>{{ product[0].productNames['en'] }} 's articles</h4>
<div
v-for="(productInner, productInnerIndex) in product"
:key="productInnerIndex"
>
<nuxt-link :to="'/' + productInner.title_slug"> . <--- Link to the articles
{{ productInnerIndex + 1 }}. {{ productInner.title['en'] }}
</nuxt-link>
</div>
</div>
</div>
</div>
</div>
Changes in template explained:
<div class="productlisting" #click="activeProductIndex = productIndex"> - using click event to assign current product index into activeProductIndex variable
<div class="articlelisting" v-if="activeProductIndex === productIndex"> - render article listing only if product is "active"

How to show only one ul at a time in angular using ngFor

I have the above image which has Add Person button, on click of Add person, Person 1 row gets created and so on. On the right end of each row, I have a share icon, on click of an icon, I wanted to open a ul element. The problem is the number of popups that gets displayed depends on the number of rows. If 5 rows are added, then 5 popups are displayed. Ideally, I need only one popup to be displayed, for Person 4 row it should be the popup with 33( basically the popup the is present for that particular row). I tried to add *ngIf = i> 1 condition, but the popup with 00 is only displayed every time which is not correct because the popup position will always be in parallel to Person 1 position.
<div>
<div *ngFor="let person of persons; let i = index">
<div>
<div class="userIcon">
<div>
<img class="person-img" src="assets/images/person.png" alt="My Profile">
</div>
<div>
<input id="form3" class="form-control" type="text">
<label for="form3" class="">{{person.name}}</label>
</div>
</div>
</div>
<div>
<div>
<input id="form5" class="form-control" #enteramount type="text">
<a class='dropdown-trigger sharebtn' href='#' data-target='dropdown{{i}}' (click)="shareIconClicked($event, i, enteramount)"></a>
{{i}}
<ul id='dropdown{{i}}' [ngClass]="{'popupShare': showPopup == true}" class='dropdown-content sharebtn-content'>
<li> {{i}}
Copy Message
</li>
<li>Whatsapp</li>
<li>Email</li>
</ul>
</div>
</div>
</div>
</div>
Below image represents the single popup after adding ngIf = 'isFirst'. I have clicked the Person 4 share icon. If I click the Person 3 share or Person 5 share icon, the popup is always positioned on the first row.
Just add check for first using *ngFor like this -
<div *ngFor="let person of persons; first as isFirst">
....
<ul id='dropdown{{i}}' *ngIf='first' [ngClass]="{'popupShare': showPopup == true}" class='dropdown-content sharebtn-content'>
...</ul>
</div>
For more in details refer official docs -
https://angular.io/api/common/NgForOf
You should try angular Mat-menu feature like this.
<div *ngFor="let person of persons; first as isFirst">
.... code
<button mat-button [matMenuTriggerFor]="menu">Share</button>
<mat-menu #menu="matMenu">
<button mat-menu-item (click)="sharteWithFacebook(person)">Facebook</button>
<button mat-menu-item (click)="shareWithWhatapp(person)">Whatsapp</button>
</mat-menu>
</div>

ngFor hide unhide details

I have the following json array
users= [
{'name':'cliff'
'age':'44'
'bloodtype':'A'
'hobby':'Golf'
},
{'name':'andy'
'age':'30'
'bloodtype':'b'
'hobby':'running'
}]
and i have the following code which will loop through all users and display its details
<div *ngFor='let user of users >
<div>Name:{{user.name}}</div>
<div>Age:{{user.age}}</div>
<div>BloodType:{{user.bloodtype}}</div>
<div>Hobby:{{user.hobby}}</div>
More
</div>
What i want to do is to hide 'bloodtype', 'hobby' field on initial load for all users and unhide individual user details when the 'More' link is clicked. How can i accomplish this?
I have tried the following but clicking 'More' link will unhide all users details
<div *ngFor='let user of users >
<div>Name:{{user.name}}</div>
<div>Age:{{user.age}}</div>
<div [hidden]=isHidden>
<div>BloodType:{{user.bloodtype}}</div>
<div>Hobby:{{user.hobby}}</div>
<div>
<a href="#" (click)='isHidden=!isHidden'>More</a>
</div>
Have a seperate array which holds the current state:
additionalInfo: Array<boolean> = [ false, false ];
users: Array<any> = [
{'name':'cliff'
'age':'44'
'bloodtype':'A'
'hobby':'Golf'
},
{'name':'andy'
'age':'30'
'bloodtype':'b'
'hobby':'running'
}]
And modify your HTML template like this. Add the index variable in your *ngFor and then add the *ngIf on the divs and the anchor and also a (click) event to toggle the state.
<div *ngFor="let user of users; let i=index" >
<div>Name:{{user.name}}</div>
<div>Age:{{user.age}}</div>
<div *ngIf="additionalInfo[i]">BloodType:{{user.bloodtype}}</div>
<div *ngIf="additionalInfo[i]">Hobby:{{user.hobby}}</div>
<a *ngIf="!additionalInfo[i]" (click)="additionalInfo[i] = true">More</a>
</div>
Try with below ngFor :
<div *ngFor="let user of users" >
<div>Name:{{user.name}}</div>
<div>Age:{{user.age}}</div>
<div *ngIf="user.isMore">
<div>BloodType:{{user.bloodtype}}</div>
<div>Hobby:{{user.hobby}}</div>
</div>
<a *ngIf="!user.isMore" (click)="user.isMore = !user.isMore">More</a>
</div>
Use *ngIf
Implement click function, that return current person.
And then yo can do this. In this div you can add your field, that you want hide
<div *ngIf="currentPerson">
//your info
</div>
You can find full answer and exemple here

Checkboxes count selected checkboxes, sometimes returns an error

I am using an accordion, divided into 5 categories, showing several rows of checkboxes. When the visitor selects a checkbox, it returns the amount of selected checkboxes per category. Nothing is shown when none of the checkboxes are selected. E.g.
Category 1: 2 checkboxes selected
Category 2: 1 checkboxes selected
Category 3:
Category 4: 10 checkboxes selected
Category 5:
This works, so when the visitor adds another one in category 4 it will show "11 checkboxes selected". Also when one is turned off, it of course shows "9 checkboxes selected".
However, this works 95% of the time. When I randomly click the checkboxes, it sometimes returns an error in the log
Uncaught TypeError: undefined is not a function studiezoeker:487Request studiezoeker:487(anonymous function) studiezoeker:479v.event.dispatch ScriptResource.axd?d=dNZi6RW_20g0sp3isLHt5GoHGXYiqvO1u3-FU9wcgPXyQCu1rmFi0RuSIwIzaJjczNe7S8D3OTnoIX…:2o.handle.u
The counter in this case will be stuck at whatever it was. In this example, category 4 will be stuck at 10. However, when I now click another one, the results are correct again. 12 selected will be shown.
I've searched for hours, but I just can't find it.
The Javascript-part where it goes wrong. It goes wrong within the first 4 lines.
$(".filtercontainer .accordionitem").each(function () {
$(".beefup-body [type='checkbox']", this).change(function () {
var count = $(this).parent().parent().parent().delay(100).find($("[type='checkbox']:checked")).length;
console.log(count);
$(this).parent().parent().parent().siblings("h2").find(".checkCount").text(count + " geselecteerd");
if (count == 0) {
$(this).parent().parent().parent().siblings("h2").find(".checkCount").hide();
}
else {
$(this).parent().parent().parent().siblings("h2").find(".checkCount").show();
}
});
The HTML (stripped down all checkboxes and all categories, so it's easier to read
<div class="filtercontainer">
<div class="Accordion">
<div class="AccordionInner">
<article class="taxonomy accordionitem open" data-taxonomy="school" role="article">
<h2 class="beefup-head">school <span class="checkCount">14 selected</span></h2>
<div class="beefup-body" style="display: block;">
<div class="columncount">
<div class="taxa" title="ade08e3b-77bc-6478-97b6-ff00006ae40d" data-taxa-id="ade08e3b-77bc-6478-97b6-ff00006ae40d">
<input id="ade08e3b-77bc-6478-97b6-ff00006ae40d" type="checkbox" name="ctl00$Content$C022$cbFilter">
<label class="coverCheckBox" for="ade08e3b-77bc-6478-97b6-ff00006ae40d"><span></span></label>
<span class="filterName">One checkbox as an example</span>
<!-- More checkboxes below this one, upto 40 per category -->
</div>
<div class="taxa" title="afe08e3b-77bc-6478-97b6-ff00006ae40d" data-taxa-id="afe08e3b-77bc-6478-97b6-ff00006ae40d"></div>
</div>
</div>
</article>
<article class="taxonomy accordionitem" data-taxonomy="vorm" role="article">
<h2 class="beefup-head">vorm <span class="checkCount"></span></h2>
<div class="beefup-body" style="display: none;">
<div class="columncount">
<!-- Checkboxes in this category as well -->
</div>
</div>
</article>
<!-- More categories containing their own checkboxes here as well -->
</div>
</div>
</div>

Categories