How to collapse only selected row ? Angular - javascript

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.

Related

Using one global filter pipe in Angular 10

I have a set of items that I want to segment into different sections like section A, B, and C. When the user searches for the name, it updates the view of each section based on their search. This is my component HTML (allItems = [{name:"someName", "items":Items[]}, {name:"someName2", "items":Items[]}, ...]):
<ng-container *ngFor="let itemSection of allItems ">
<div class="section-title">{{itemSection.name}}</div>
<ul class="item-grid">
<ng-container *ngFor="let item of itemSection.items | itemFilter : searchText : searchType">
<li class="item" (click)="addItem(item)">
<div class="item-block">
<div class="bg-black" [ngClass]="isVisibleClass(item)">
<img class="item-img" [src]="item.img" />
</div>
</div>
</li>
</ng-container>
</ul>
</ng-container>
As the number of itemSection's grow, it applies multiple of the same filter pipe to each of those sections, making it laggy because of the constant filter on different items. I would rather apply one itemFilter pipe to all of items, add to it's respective div then render it:
<div id="a"></div>
<div id="b"></div>
<ng-container *ngIf="items$ | async as items">
<ng-container *ngFor="let item of items | itemFilter : searchText : searchType">
if item section == "a", put in div a
else if item section == "b", put in div b
...
</ng-container>
</ng-container>
then render the contents of div a and b
I'm not sure how to make it less laggy with only applying the result of one filter pipe, but also segment the results into different sections. Any suggestions?

Display count of selected options using ng-select

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.

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

Select element with jquery inside a handlebars each iteration

I'm building for exercise a e-shop. I'm displaying a list of product in the HTML, using handlebars.
For every element I'm adding a button that should allow the user to add the item in the shopping cart. It's not working because every time I click on the button I add all the list and not only the single object.
So I know that I'm passing all the list (because I pass 'list' as argument), I was wondering how pass only the current item for every button. I'm not sure how to do it.
html:
<div class="container-fluid">
<script id="list-items" type="text/x-handlebars-template">​
{{#each list}}
<div class="items col-lg-3 col-md-4 col-sm-6 col-xs-12">
Category: {{ category}} </br>
Name: {{ name }} </br>
Price: {{ price }} </br>
Quantity: {{ quantity }}
<button class="addItem" class="btn">Buy</button>
</div>
{{/each}}
</script>
</div>
javascript:
var ShoppingCart = function () {
this.cart = [];
};
ShoppingCart.prototype.addItem = function(item) {
this.cart.push(item);
};
shoppingCart = new ShoppingCart();
$('.addItem').click(function() {
shoppingCart.addItem(list);
});
In your click function you add exactly the whole list:
shoppingCart.addItem(list);
And you do not need to transfer the whole item to be added. As you already have the whole list in the scope, you just need to let your function know what was the selected index.
Possible solution could be to add index by handlebars into button id and then parse it in jQuery and proceed or consider replacing jQuery way to subscribe to on-click event with pure javascript solution and insert the index of the item withe help of handlebars, in the way:
<button class="addItem" class="btn" onclick="addItem({{#index}})">Buy</button>
Where addItem is:
function addItem(index) {
shoppingCart.addItem(list[index]);
}
I guess you could sort this out with an item ID (or index as pointed out elsewhere) :
<button id="{{ #index }}" class="addItem" class="btn">Buy</button>
$('.addItem').click(function() {
shoppingCart.addItem(list[$(this).id]);
});

How to filter a list in AngularJS using several links

I have been going over a lot of tutorials on how to filter a list and can't find an example for my simple use-case.
I have several buttons such as
Name
Age
Height
I have var persons = {...} object and I display it like
<div ng-repeat="person in persons">
{{person.name...}}
</div>
How do I create a filter so each time I will click on one of the buttons the list will be filtered ?
I have tried addingng-repeat="person in persons | filter:filterPersons"
and on the script side to write:
$scope.filterPersons(person){
if (person.name == "John")
return person;
}
but this is only one use-case (how can I filter by another name?) - in other words - How do I connect the links to the filter?
You can bind your filter to scope variables as you do with any other thing. So all you need is to set the appropriated filter to the scope when the user click and bind it to the ng-repeat filter param. See:
<div ng-app>
<span ng-click="myFilter = {type: 1}">Type 1</span> |
<span ng-click="myFilter = {type: 2}">Type 2</span> |
<span ng-click="myFilter = null">No filter</span>
<ul ng-controller="Test">
<li ng-repeat="person in persons | filter:myFilter">{{person.name}}</li>
</ul>
</div>
function Test($scope) {
$scope.persons = [{type: 1, name: 'Caio'}, {type:2, name: 'Ary'}, {type:1, name: 'Camila'}];
}
Notice that the myFilter is changed when the user clicks the filter, and that it's bound to the ng-repeat filter. Fiddle here. You could also create a new filter, but this solution is far better.
My response is very similar to Caio's. I just wanted to show how to filter out an existing array.
In my ng-repeat I have a search filter that goes through the words. I wanted tabs to look for a string match. So I added a additional filter
<tr class="unEditableDrinks" ng-repeat="drink in unEditableDrinkList | orderBy:'-date'|limitTo:400|filter:search |filter:myFilter">
<td>[[drink.name]]</td>
I only have the top part of my table but this should show the strategy. The second filter called myFilter is attached to the buttons below.
<div class="btn-group" role="group">
<button type="button" class="btn btn-primary" ng-click="myFilter={name:'soda'}">Soda</button>
</div>
<div class="btn-group" role="group">
<button type="button" class="btn btn-primary" ng-click="myFilter={name:'energy'}">Energy Drinks</button>
</div>
On each button I am able to add a ng-click that goes through myFilter and searches the td with drink.name. In each ng-click I can set the value of name to search. So every title containing soda or energy can be filtered through.

Categories