Create unique variable name inside *ngFor - javascript

I am trying to make a table that, when you click a button, it needs to display the row directly beneath it.
I have had a look at this post, but I could not find an answer from it.
When I have it like below, it works, but the problem is, it displays all other hidden rows since they all share the same collapse variable.
This is the working example, but not 100% correct:
<table>
<thead>
<th>Path out of this queue</th>
<th *ngFor="let role of roles">{{role.RoleName}}</th>>
</thead>
<tbody>
<ng-container *ngFor="let queue of workQueues; let i = index">
<tr>
<td><button (click)="collapse=!collapse">{{queue.WorkQueueName}}</button></td>
<td *ngFor="let role of roles">
<input type="checkbox" />
</td>
</tr>
<tr *ngIf="collapse">
Yay...
</tr>
</ng-container>
</tbody>
I thought I would be able to make the collapse variable unique, by appending the i, which is the index, to it, but then I get the following error:
Parser Error: Got interpolation ({{}}) where expression was expected
Here is my attempt:
<table>
<thead>
<th>Path out of this queue</th>
<th *ngFor="let role of roles">{{role.RoleName}}</th>>
</thead>
<tbody>
<ng-container *ngFor="let queue of workQueues; let i = index">
<tr>
<td><button (click)="{{collapse+i}}={{!collapse+i}}">{{queue.WorkQueueName}}</button></td>
<td *ngFor="let role of roles">
<input type="checkbox" />
</td>
</tr>
<tr *ngIf="{{collapse+i}}">
Yay...
</tr>
</ng-container>
</tbody>
Specifically, in my (click) event, how can I make a unique variable that could be used?

(click)="{{collapse+i}}={{!collapse+i}}"
should be
(click)="this[collapse+i] = !this[collapse+i]"
This allows you to use an indexer to obtain the field on the component. If it actually works depends on how you have collapse fields defined on your component.
Personally I would prefer extending the type contained in the workQueues array with an additional field.
(click)="queue.collapsed = !queue.collapsed"
...
<tr *ngIf="queue.collapsed">
An other alternative is to define a new field in the *ngFor.
<ng-container *ngFor="let queue of workQueues; let i = index; let isCollapsed = true">
<tr>
<td><button (click)="isCollapsed = !isCollapsed">{{queue.WorkQueueName}}</button></td>
<td *ngFor="let role of roles">
<input type="checkbox" />
</td>
</tr>
<tr *ngIf="!isCollapsed">
Yay...
</tr>
</ng-container>
stackblitz

Related

Angular 2: Can I dynamically set the value for template reference variable?

I am using angular2-collapsible to generate a table where each row can be expanded for detailed data. So my approach was to use *ngFor to loop through a list and generate each row and each corresponding detail.
<ng-container *ngFor="let adData of adDataList; let i = index">
<collapsible-table-row [detail]="adDataDetailNameList[i]">
<td>...</td>
<td>...</td>
</collapsible-table-row>
<collapsible-table-row-detail #{{ adDataDetailNameList[i] }}> <----This doesn't work
<div>
testing...
</div>
</collapsible-table-row-detail>
</ng-container>
Below is the demo code in angular2-collapsible:
<collapsible-table [type]="'accordion'" bordered>
<thead>
<collapsible-table-row>
<th>Col #1</th>
<th>Col #2</th>
<th>Col #3</th>
</collapsible-table-row>
</thead>
<tbody>
<collapsible-table-row [detail]="detail1"> <----Assign 'detail1'
<td>Cell(0,0)</td>
<td>Cell(0,1)</td>
<td>Cell(0,2)</td>
</collapsible-table-row>
<collapsible-table-row-detail #detail1> <----Refer to 'detail1'
<table>
<tr>
<td width="75%">Row #1 Detail #1</td>
<td>Row #1 Detail #2</td>
</tr>
</table>
</collapsible-table-row-detail>
</tbody>
</collapsible-table>
So the way that row-detail interact with row is by template reference variable, it seems. Since I am using *ngFor to generate these rows, I wonder if there is a way to assign template reference variables dynamically. If it is impossible (since I read somewhere that template reference variable is supposed to be static), is there any work-around for this problem?
Thanks!

how to combine ng-if , ng-click and ng-show and use them together

Pre-info
I try to sperate Admin and customer in a different stage or view.
so that, admin can modify the table before releasing it to customers.
Questions
In the table -> td there is button to control the staging, release(show) or revert (hide)?
so basically what I wanna do is that every table checked can be shown on the both in admin and customer. if it's unchecked, the data only show to admin.
Currently, the code is disabled whole table-body instead of 1 row.
is there any way to check or uncheck only 1 row?
thanks for the advice.
$scope.showDiv = isAdmin();
$scope.toggleShowDiv = function () {
$scope.showDiv = !isAdmin()&isAdmin();
console.log('fired');
};
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<thead>
<tr>
<th style="width: 80px">foo1</th>
<th style="width: 80px">foo2</th>
<th style="width: 200px">foo3</th>
<th>foo4</th>
<th>foo5</th>
<th>foo6</th>
</tr>
</thead>
<tbody class="auction-group" ng-repeat="a in foos" ng-if="showDiv">
<tr>
<td>abcd1</td>
<td>abcd1</td>
<td>abcd1</td>
<td>abcd3</td>
<td>abcd4</td>
<td>abcd5</td>
//is admin - show only to admin
<td ng-if="::isAdmin()">
<input type="checkbox" ng-click="toggleShowDiv()" />
</td>
</tr>
</tbody>
Take your first ng-if outside ng-repeat
<div ng-if="showDiv">
<tbody class="auction-group" ng-repeat="a in foos">
</div>
second ng-if should be like this,
<td ng-if="isAdmin()">
<input type="checkbox" ng-click="toggleShowDiv()" />
</td>

Get the row index of bootstrap table in click without using jquery

I have a bootstrap table in my react project. I want to get the index of row which I click on. I want to do something like this onclick = {this.handleClick} and in handleClick function I want to get the index of row. Is it possible to do it. Most of the solutions available shows everything using jquery and I don't want to use Jquery. I want to do it using just javascript only. This is my table
<Table className='flags-table' responsive hover>
<thead>
<tr>
<th> </th>
<th> Time In </th>
<th> Time Out </th>
<th> Type </th>
<th> Category </th>
</tr>
</thead>
<tbody>
{
FLAGS_LIST.map((x,i)=> (
<tr key={i}>
<td> <div className='red-box'></div> </td>
<td> {x.time_in} </td>
<td> {x.time_out} </td>
<td> {x.type} </td>
<td> {x.category} </td>
</tr>
))
}
</tbody>
</Table>
You can use code like this:
onclick = {this.handleClick.bind(this, i)};
and handleClick should declare like this:
var handleClick = function(i) {
console.log("key of row", i)
...
};

nested ng-repeat that one depend on the other

I have an issue with angular, I want to use two nested ng-repeat in a data table where the first get the data, and the second get the name of field to be retrieved from the data (retrieved in the first ng-repeat)
here is what I tried to do with code :
<table md-table flex-order-gt-sm >
<thead md-head>
<tr md-row >
//1st : get the name of fields, not a problem
<th md-column ng-repeat="field in fields">{{item.name}}</th>
</tr>
</thead>
<tbody md-body>
<tr md-row ng-repeat="item in items">
<td md-cell ng-repeat="field in fields" >
//here is the problem I want to get the item that it's field name is field
{{item.{{field}} }}</td>
</tr>
</tbody>
</table>
for example if fields contain :{'a','b','c'}
and items contains {'a':'1','b':'2','c':'3'};
I want for example for the 1st iteration of {{item.{{field}} }} to return 1
Use toString() to retrieve the scope data in an scope object.
<tr md-row ng-repeat="item in items">
<td md-cell ng-repeat="field in fields" >
{{item[field.toString()]}}
</td>
</tr>
Here is the plunker
As an alternative you could also use a filter:
<td md-cell ng-repeat="field in fields | filter: { name: 'field' }">
</td>
You need to get fields collection according to item of items collection after
getFieldsByItem(item)
Then you can get field from fields collection
{{field}}

ng repeat in table using Angularjs

The Array I use is [{"cell":["jobcode","resume_number","score"]},{"cell":["jc100","rc1",80]},{"cell":["jc100","rc123",70]}]
And I came up with javascript code as
var cell=response;
for (var i in cell) {
for(var j in cell[i])
{
console.log(cell[i][j]);
profiles.push(cell[i][j]);
$scope.profiles=profiles;
for(k in cell[i][j])
{
resumes.push(cell[i][j]);
console.log("resume length"+resumes.length);
$scope.columns=resumes;
console.log(JSON.stringify($scope.columns));
}
}
}
And html is
<tr ng-repeat="profile in profiles track by $index" >
<td ng-repeat="col in columns track by $index">
<label >{{col.cell}}</label>
</td>
</tr>
And ended up enter image description here
I have no idea to proceed further. I need to organize those data as a table. Please help.
Your data contains an array of objects which contains another array. Therefore, you need to extract each object from outer array and then go down to inner one.
If you need this data only to organise them in a table, then you can simply use the following code:
Your Controller code:
$scope.cell = response;
Your HTML :
<tr ng-repeat="profile in cell track by $index" >
<td ng-repeat="col in profile.cell track by $index">
<label >{{col}}</label>
</td>
</tr>
In case you need to store each array object, then you can use forEach loop:
Your controller code:
var cell=[{"cell":["jobcode","resume_number","score"]}, {"cell":["jc100","rc1",80]}, {"cell":["jc100","rc123",70]}];
angular.forEach(cell, function(data){
$scope.profiles.push(data);
});
Your HTML :
<table>
<tr ng-repeat="profile in profiles track by $index" >
<td ng-repeat="col in profile.cell track by $index">
<label >{{col}}</label>
</td>
</tr>
</table>
Try the following code. Take header as separate part from json and display header first then start ng-repeat from index first
<table border="1">
<tr>
<td>
{{columns[0].cell[0]}}
</td>
<td>
{{columns[0].cell[1]}}
</td>
<td>
{{columns[0].cell[2]}}
</td>
</tr>
<tr ng-repeat="col in columns" ng-if="$index>0">
<td>
{{columns[$index].cell[0]}}
</td>
<td>
{{columns[$index].cell[1]}}
</td>
<td>
{{columns[$index].cell[2]}}
</td>
</tr>
</table>

Categories