Pass a unique identifier into AngularJS collapse? - javascript

I have a table, within which I have a span element which I want to collapse expand when I click on the top row of the table. I am using the anuglar function collapse
So far this is working fine but if I have three identical tables, clicking one top row collapses all three of them.
Can I pass some unique identifier into the collpase function somehow?
HTML
<div ng-repeat="detail in details.detail">
<div class="my_table">
<table>
<tbody>
<tr class="top_row" ng-click="isCollapsed = !isCollapsed">
<td colspan="2">
<span class="f_name">
{{ details.f_name }}
</span>
<span class="l_name" >
{{ details.l_name }}
</span>
</td>
</tr>
<tr>
<td class="detail">
<span class="_address" collapse="isCollapsed">
{{ details.address }}
</span>
</td>
</tr>
</tbody>
</table>
</div>
</div>
JS
function CollapseCtrl($scope) {
$scope.isCollapsed = false;
}

You can use special variable $index in ng-repeat and also use array for model
<div ng-repeat="detail in details.detail">
<div class="my_table">
<table>
<tbody>
<tr class="top_row" ng-click="isCollapsed[$index] = !isCollapsed[$index]">
<td colspan="2">
<span class="f_name">
{{ details.f_name }}
</span>
<span class="l_name" >
{{ details.l_name }}
</span>
</td>
</tr>
<tr>
<td class="detail">
<span class="_address" collapse="isCollapsed[$index]">
{{ details.address }}
</span>
</td>
</tr>
</tbody>
</table>
</div>
</div>
function CollapseCtrl($scope) {
$scope.isCollapsed = [];
}

Related

How can I create expand/collapse function for each row of table? Angular6

So I need to be able to expand some details on each row of a table. Right now I'm having two issues:
Clicking the expand/collapse toggle will trigger the action for every row in the table.
The first row always puts the details above it.
Here's the code segment:
<tbody>
<tr *ngFor="let client of clients">
<td class="details-control">
<a class="btn btn-link" (click)="collapsed1=!collapsed1">
<i class="material-icons">
expand_more
</i>
</a>
</td>
<td>{{client.firstName}}</td>
<td>{{client.lastName}}</td>
<td>{{client.company}}</td>
<td><input type="checkbox"></td>
</tr>
<div *ngIf="!collapsed1">
<p>Details</p>
</div>
</tbody>
And what it looks like:
Toggling
Also I had my *ngFor statement in the tag earlier but I realized I can't hit individual client objects if I build a separate for details.
Let me know how I can improve!
It's a very common pattern.
The best and quick solution is to use some ID instead of just a boolean in your collapsed1 variable.
<tbody>
<tr *ngFor="let client of clients">
<td class="details-control">
<a class="btn btn-link" (click)="collapsed1 = collapsed1 ? 0 : client.id ">
<i class="material-icons">
expand_more
</i>
</a>
</td>
<td>{{client.firstName}}</td>
<td>{{client.lastName}}</td>
<td>{{client.company}}</td>
<td><input type="checkbox"></td>
<div *ngIf="collapsed1=client.id">
<p>Details</p>
</div>
You need a boolean array collapsed[] and use index in your ngFor, so you can use collapsed[i]. Take a look here for using index in ngFor:
ngFor using Index
Let me know if you need more info. Wellcome
Nevermind, here is the code that solved it.
<tbody>
<tr *ngFor="let client of clients; let i = index">
<td class="details-control">
<a class="btn btn-link" (click)="client.hideme=!client.hideme">
<i class="material-icons" *ngIf="!client.hideme">
expand_more
</i>
<i class="material-icons" *ngIf="client.hideme">
expand_less
</i>
</a>
</td>
<td width="30%">{{client.firstName}}
<tr *ngIf="client.hideme">
<td>Hey, I'm a bunch of details!</td>
</tr>
</td>
<td>{{client.lastName}}</td>
<td>{{client.company}}
<tr *ngIf="client.hideme">
<td>More Issuer details</td>
</tr>
</td>
<td><input type="checkbox"></td>
</tr>
</tbody>

Repeat parent row in nested ng-repeat Angularjs?

I have a table which is displaying nested ng-repeat values. The HTML looks like this.
<table class="table">
<thead class="bgThead">
<tr>
<th>Environment</th>
<th>Configurations</th>
<th>Servers</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="environment in serverList.environments" ng-class-odd="''" ng-class-even="'dataTableOdd'">
<td>{{environment.Environment}}</td>
<td ng-repeat="servertypeinfo in environment.ServerTypeInfo">{{servertypeinfo.Type}}</td>
<td ng-repeat="servertypeinfo in environment.ServerTypeInfo">
{{servertypeinfo.ServerConfigInfo.length}}
<td ng-repeat="servers in servertypeinfo.ServerConfigInfo">{{servers.ServerName}}</td>
</td>
</tr>
</tbody>
</table>
Now, when there are multiple values in child ng-repeat, the TDs are getting repeated, instead I want the whole row to be repeated, with the same values, except the new children value. Same goes with further nested ng-repeats. I made a plunk which shows what I am aiming for.
http://plnkr.co/edit/vLw6MCO8NGoFYxaCKeJ0?p=preview
Example without table, may not be what you are looking for
<div class="form-group" ng-repeat="environment in serverList.environments track by $index">
<div class="col-md-4">
<span ng-bind="environment.environment"></span>
</div>
<div class="col-md-8">
<ul class="list-group">
<li id="{{$index}}" ng-repeat="servertypeinfo in environment.serverTypeInfo track by $index">
Server Type: <span style="font-size: 16px;" class="no-margin" ng-bind="servertypeinfo.type">{{servertypeinfo.serverConfigInfo.length}}</span>
<p class="no-margin" ng-repeat="server in servertypeinfo.serverConfigInfo">
Server Name: {{server.serverName}}
</p>
</li>
</ul>
</div>
</div>
use the format like this
<tbody>
<tr ng-repeat="environment in serverList.environments" ng-class-odd="''" ng-class-even="'dataTableOdd'">
<td>
<table>
<tr ng-repeat="servertypeinfo in environment.ServerTypeInfo">
<td>{{environment.Environment}}</td>
<td>{{servertypeinfo.Type}}</td>
<td>
{{servertypeinfo.ServerConfigInfo.length}}
<td ng-repeat="servers in servertypeinfo.ServerConfigInfo">{{servers.ServerName}}</td>
</td>
</tr>
</table>
</td>
</tr>
</tbody>

Not getting the expression value in the table

I am new to angularjs. So , I have a contextmenu for the table data.
<div contextmenu-container="meta.contextmenu">
<table class="table table-striped table-bordered report-table" fixed-header>
<thead class="text-center text-info">
<th class="text-center">Annotation</th>
<th class="text-center">Field</th>
<th class="text-center">Message</th>
<th class="text-center">Score</th>
</thead>
<tr ng-repeat="report in reports.data">
<td class="text-center">{{ report.attributes.annotation }}</td>
<td class="td-report-field" contextmenu-item="row">{{ report.attributes.field }}</td>
<td>
<input type="checkbox" ng-if="report.attributes.message && showcheckbox"
ng-bind="report.attributes.message" ng-click="getcheckedData(report.attributes.message)">
<span ng-if="report.attributes.message" contentEditable ng-model="report.attributes.message">
{{ report.attributes.message }}
</span>
<span ng-if="!report.attributes.message">{{ report.attributes.message }}</span>
</td>
<td class="text-center">{{ report.attributes.score }}</td>
<div contextmenu="meta.contextmenu" class="dropdown contextmenu ">
<ul class="dropdown-menu dropdown-content" role="menu">
<li>
<a role="menu" href
data-ng-click="deleteAnnotation(report.attributes.field)">
<span>delete</span>
</a>
</li>
</ul>
</div>
</tr>
</table>
</div>
In this,when I try to use the report.attributes.field in the deleteAnnotation method then It gives undefined . So,How can I solve it?
You can get each repeated object inside '$itemScope'.In your case it will be '$itemScope.report', after that you can perform whatever operations you want on that data.
In angular contextmenu , "meta.contextmenu.item" will point to "contextmenu-item". Hope this helps.
ui bootstrap contextmenu
HTML
<div ng-app="HelloWorldApp" class='container'>
<div ng-controller="HelloWorldController">
<table class='table table-striped'>
<tr>
<td><b>NAME</b></td>
<td><b>ADDRESS</b></td>
</tr>
<tr ng-repeat="obj in objects" >
<td>{{obj.name}}</td>
<td context-menu="menuOptions">{{obj.address}}</td>
</tr>
</table>
<div ng-bind="selected"></div>
</div>
</div>
JS
angular.module('HelloWorldApp', ['ui.bootstrap.contextMenu'])
.controller('HelloWorldController', function($scope) {
$scope.greeting = "Hello World";
$scope.objects = [{
name: 'person1',
address: 'India'
},
{
name: 'any name',
address: 'any address'
}];
$scope.menuOptions = [
['Select', function ($itemScope, $event, modelValue, text, $li) {
$scope.selected = $itemScope.obj.address;
}]
];
});
angular-contextmenu
HTML
<div ng-app="HelloWorldApp" class='container'>
<div ng-controller="HelloWorldController">
<div contextmenu="meta.contextmenu" class="dropdown contextmenu">
<ul class="dropdown-menu" role="menu">
<li class="dropdown-header">
{{ meta.contextmenu.item.address }}
</li>
<li>
<a role="menuitem" href
ng-click="delete(meta.contextmenu.item)"
>
<span>Delete</span>
</a>
</li>
</ul>
</div>
<table class='table table-striped' contextmenu-container="meta.contextmenu">
<tr>
<td><b>NAME</b></td>
<td><b>ADDRESS</b></td>
</tr>
<tr ng-repeat="obj in objects" contextmenu-item="obj" >
<td>{{obj.name}}</td>
<td context-menu="menuOptions">{{obj.address}}</td>
</tr>
</table>
Data to delete :
<pre>{{selected.name}}</pre>
<pre>{{selected.address}}</pre>
</div>
</div>
JS
angular.module('HelloWorldApp', ['io.dennis.contextmenu'])
.controller('HelloWorldController', function($scope) {
$scope.greeting = "Hello World";
$scope.objects = [{
name: 'person1',
address: 'India'
},
{
name: 'any name',
address: 'any address'
}];
$scope.delete = function(data){
console.log(data);
$scope.selected = data;
}
});
**you will need to include necessary libs for ui-bootstrap contextmenu and/or angular contextmenu
** And again, sorry for bad formatting.
You are calling deleteAnnotation after ending <tr> which has the ng-repeat
The variable report is in the ng-repeat scope so u need to call the deleteAnnotation function inside ng-repeat
<tr ng-repeat="report in reports.data">
<td class="text-center">{{ report.attributes.annotation }}</td>
<td class="td-report-field" contextmenu-item="row">{{ report.attributes.field }}</td>
<td>
<input type="checkbox" ng-if="report.attributes.message && showcheckbox"
ng-bind="report.attributes.message" ng-click="getcheckedData(report.attributes.message)">
<span ng-if="report.attributes.message" contentEditable ng-model="report.attributes.message">
{{ report.attributes.message }}
</span>
<span ng-if="!report.attributes.message">{{ report.attributes.message }}</span>
</td>
<td class="text-center">{{ report.attributes.score }}</td>
</tr>
Here the scope is ended.
So you cannot access report
Also do not embed div in table tag
<table class="table table-striped table-bordered report-table" fixed-header>
<thead class="text-center text-info">
<th class="text-center">Annotation</th>
<th class="text-center">Field</th>
<th class="text-center">Message</th>
<th class="text-center">Score</th>
</thead>
<tr ng-repeat="report in reports.data">
<td class="text-center">{{ report.attributes.annotation }}</td>
<td class="td-report-field" contextmenu-item="row">{{ report.attributes.field }}</td>
<td>
<input type="checkbox" ng-if="report.attributes.message && showcheckbox"
ng-bind="report.attributes.message" ng-click="getcheckedData(report.attributes.message)">
<span ng-if="report.attributes.message" contentEditable ng-model="report.attributes.message">
{{ report.attributes.message }}
</span>
<span ng-if="!report.attributes.message">{{ report.attributes.message }}</span>
</td>
<td class="text-center">{{ report.attributes.score }}</td>
<td>
<div contextmenu="meta.contextmenu" class="dropdown contextmenu ">
<ul class="dropdown-menu dropdown-content" role="menu">
<li>
<a role="menu" href="#"
data-ng-click="deleteAnnotation(report.attributes.field)">
<span>delete</span>
</a>
</li>
</ul>
</div>
</td>
</tr>
</table>
Try this. Also check report has a attributes.field property in that loop.

Access table cell with javascript in chrome console

I have this table and I want to access the prod_sku value and define it as a variable:
<tr class="border first last" id="order-item-row-386470">
<td><h3 class="product-name">prod_name</h3>
</td>
<td data-rwd-label="SKU">prod_sku</td>
<td class="a-right" data-rwd-label="Preço">
<span class="price-excl-tax">
<span class="cart-price">
<span class="price">prod_price</span>
</span>
</span>
<br>
</td>
</tr>
I get this table with this line:
data = document.getElementsByClassName("odd")[0].innerHTML;
From this tbody
<tbody class="odd">
<tr class="border first last" id="order-item-row-386470">
<td><h3 class="product-name">prod_name</h3>
</td>
<td data-rwd-label="SKU">prod_sku</td>
<td class="a-right" data-rwd-label="Preço">
<span class="price-excl-tax">
<span class="cart-price">
<span class="price">prod_price</span>
</span>
</span>
<br>
</td>
<td class="a-right" data-rwd-label="Qtd">
<span class="nobr">
Solicitado: <strong>1</strong><br>
</span>
</td>
<td class="a-right last" data-rwd-label="Subtotal">
<span class="price-excl-tax">
<span class="cart-price">
<span class="price">prod_price</span>
</span>
</span>
<br>
</td>
</tr>
</tbody>
How can I access prod_sku?
You can use a query selector to match the data-rwd-label attribute.
document.querySelector('td[data-rwd-label=SKU]').innerHTML
If you don't have to support stone age browsers, then you can use querySelector to grab your td based on data attribute. If you have to support a myriad of outdated browsers and you need to d a lot of these types of lookups, then jquery is quite good at it.
var data = document.querySelector('td[data-rwd-label="SKU"]').innerHTML;
But would be more interesting to improve the html structure of your table.

AngularJS - How to creates a deep copy of source, which should be an object or an array

I'm building an app using sailjs and angularjs, I've a problem on form when to try input a data to database. Here is my form
If I'm input attibute a copy of the object or and array created and a fieldset attributes created on form sub attribute.
$scope.productcustom.templateAttribute = angular.copy($scope.templateAttribute);
_.each($scope.productcustom.variant, function (variant, index) {
//variant.type = 'variant';
variant.index = index;
if (variant.attribute.length > 0) {
_.each(variant.attribute, function (attribute, $index) {
attribute.key = $scope.productcustom.templateAttribute[$index];
})
}
})
and this my view
<div class="grid-100 form-group">
<table class="table">
<tr ng-repeat="template in templateAttribute">
<td>{{template}}</td>
<td>
<button type="button" class="button button-xs button-error button-labeled"
ng-click="removeItem( $index, templateAttribute )">
<span class="button-label"><i class="icon icon-minus-circled"></i></span>
delete
</button>
</td>
</tr>
<tr>
<td>
<input class="form-control input-small" placeholder="attribute name" ng-model="attributeKey"/>
</td>
<td>
<button type="button" class="button button-small button-default button-labeled"
ng-click="addItem(attributeKey, templateAttribute)">
<span class="button-label"><i class="icon icon-plus-circled"></i></span>
add
</button>
</td>
</tr>
</table>
</div>
<div class="grid-100" ng-repeat="template in templateAttribute">
<div class="panel panel-info">
<div class="panel-heading">
<h2 class="panel-title">{{template}}</h2>
</div>
<div class="panel-body">
<table class="table" ng-repeat="variant in productcustom.variant">
<thead>
<tr>
<th>name</th>
<th>additional price</th>
<th colspan="2">file</th>
</tr>
</thead>
<tbody>
<tr>
<td colspan="2">
<input class="form-control input-small" placeholder="name" ng-model="variant.attribute[$index].name" />
</td>
<td>
<input class="form-control input-small" placeholder="tambahan harga" ng-model="variant.attribute[$index].value" />
</td>
<td rowspan="2">
<button type="button" class="button button-small button-default button-labeled"
ng-click="addItem( product.materials, material)">
<span class="button-label"><i class="icon icon-plus-circled"></i></span>
add
</button>
</td>
</tr>
<tr>
<td colspan="3">
<file-uploader
class="form-control"
max-size="1000"
allowed-extensions="png,jpeg,jpg"
result-model="variant.attribute[$index].gallery"
ng-required="true">
</file-uploader>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
I tried to input some sub attributes data not create. This is my partial code controller. So how to insert data like an above form ? please advance
Straight from the docs:
Usage
angular.copy(source, [destination]);
https://docs.angularjs.org/api/ng/function/angular.copy
So do this:
angular.copy($scope.templateAttribute, $scope.productcustom.templateAttribute);
Note, that Destination must be of the same type as source (so both are Arrays or both are Objects). If it's the case that they don't match up, you may have to copy to a new variable and continue the transformation with the new var.

Categories

Resources