ngFor hide unhide details - javascript

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

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.

angular material mat-checkbox binding problem

I am using angular material for checkbox.
in component.ts
dataList: any[] = [
{ name: 'EmployeeName', flag: true, 'label': 'Employee Name'},
{ name: 'EmployeeDepartment', flag: false, 'label': 'Employee Department'},
{ name: 'EmployeeExperience', flag: false, , 'label': 'Employee Experience'}
]; // will have 30+ element in array
html (this opens as modal)
<div *ngFor="let data of dataList">
<section>
<mat-checkbox [checked]="data.flag" (change)="onChange($event, data)">{{data.label}}</mat-checkbox>
</section>
</div>
<div>
<button (click)="onClose()">
Close
</button>
<button(click)="onApply()">Apply</button>
</div>
some of the checkbox will be pre-checked, if checked than behind modal there we will be filter dropdown for checked object.
problem is if I check the object(eg- Employee Department), than behind the modal that object(Employee Department) will be added instantly and the change in UI will be visible. what I want is add that filter object (user can select multiple object at a time) only after clicking apply button and changes in UI should be visible. if I click on close that nothing should be added.
html for behind modal page
//<ngx-select-dropdown> whole config is not listed
<div class="grid-container">
<ng-container *ngFor="let data of dataList">
<div class="grid-item" *ngIf="data.flag">
<div>
<p>{{data.name }}</p>
</div>
<ngx-select-dropdown [config]="config">
</ngx-select-dropdown>
</div>
</ng-container>
</div>
I tried keeping checkbox values in another object and set value only on click of apply but the problem persisted. what should I do in onChange($event, data) and onApply() so that I can achieve the behavior I want.
Thanks in Advance
You could simply save the checkbox values in another object and once the user hits the apply button then have your function for example
onApply() that will assign the new values from the checkbox to your data

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]);
});

Click button to copy text to another div with angularjs

I have a list of Items with different button with them. Plunker
Quick View:
I want something like if I click on any of the buttons, related text will be copy to the div above. Also if I click on the button again it will removed from the Div.Same for each of the buttons. [I added manually one to show how it may display ]
I am not sure how to do that in Angular. Any help will be my life saver.
<div ng-repeat="item in csTagGrp">
<ul>
<li ng-repeat="value in item.csTags">
<div class="pull-left">
<button type="button" ng-class='{active: value.active && !value.old}' class="btn btn-default btn-xs">{{value.keys}}</button>
<span>=</span>
</div>
<div class="pull-left cs-tag-item-list">
<span>{{value.tags}}</span>
</div>
</li>
</ul>
</div>
The simplest thing would be to use $scope.tags object to store selected tags and add/remove them with the scope method similar to this:
$scope.tags = {};
$scope.toggleTag = function(tag) {
if (!$scope.tags[tag]) {
$scope.tags[tag] = true;
}
else {
delete $scope.tags[tag];
}
};
Demo: http://plnkr.co/edit/FrifyCrl0yP0T8l8XO4K?p=info
You can use ng-click to put in your scope the selected value, and then display this value instead of "Win".
http://plnkr.co/edit/IzwZFtRBfSiEcHGicc9l?p=preview
<div class="myboard">
<span>{{selected.tags}}</span>
</div>
...
<button type="button" ng-click="select(value)">{{value.keys}}</button>

ng-repeat: showing an item on click and hiding the others

I have a ng-repeat which display a list of divs and when I click on one it shows an aditionnal div for the clicked item.
This is working
<div ng-repeat="item in items">
<div ng-click="showfull = !showfull">
<div>
<h1>{{item.title}}</h1>
<p>{{item.content}}</p>
</div>
</div>
<div ng-show="showfull">
<p>{{item.info}}</p>
</div>
<hr/>
</div>
My items are loaded from a json containing a list of item and each item have a default attribut showfull set to false in this json. This is working, but now I want to hide all others item in the list when an item is clicked. I've tryied something like this :
This is not working
<div ng-repeat="item in items">
<div ng-click="expand(item)">
<div>
<h1>{{item.title}}</h1>
<p>{{item.content}}</p>
</div>
</div>
<div ng-show="showfull">
<p>{{item.info}}</p>
</div>
<hr/>
</div>
and in the controller I've added a function :
$scope.expand = function(e) {
e.showfull = !e.showfull;
//TODO: put here a foreach logic to hide all other items
}
But even without the foreach logic this is not working, the item don't show the additionnal div when clicked. I have two question :
I suppose this is due to item being "passed by copy" in the expand function or some kind of scope isolation issue but can you explain me why in detail ?
SOLVED
How can I hide all the additional div of other items when I click an item and show the additionnal content for this item ? Do I need to do a directive ?
NOT SOLVED
Thanks
I think you're on the right track. You need to set the showfull on the item and then use ng-show or ng-if to hide it, or as Gavin mentioned, use a class.
On ng-click you can call your expand function, where you pass the item, toggle it and set all others to hidden.
Template:
<div ng-repeat="item in items>
<div ng-click="expand(item)">
<div>
<h1>{{item.title}}</h1>
<p>{{item.content}}</p>
</div>
</div>
<div ng-show="item.showfull">
<p>{{item.info}}</p>
</div>
<hr/>
</div>
Controller:
$scope.expand = function (item) {
angular.forEach($scope.items, function (currentItem) {
currentItem.showfull = currentItem === item && !currentItem.showfull;
});
};
Your expand method is modifying the item, so your ng-show needs to reference the item:
<div ng-show="item.showfull">
<p>{{item.info}}</p>
</div>
To hide all of your items you need to do something like
$scope.expand = function(item) {
angular.forEach(items, function(i) {
if (i === item) {
i.showfull = !i.showfull;
} else {
i.showfull = false;
}
});
};
Shouldn't the second div you want to show be referencing the item?
<div ng-repeat="item in items>
<div ng-click="expand(item)">
<div>
<h1>{{item.title}}</h1>
<p>{{item.content}}</p>
</div>
</div>
<!-- Added item to ng-show -->
<div ng-show="item.showfull">
<p>{{item.info}}</p>
</div>
<hr/>
</div>

Categories