Tricky Nested ng-repeat - angularjs

https://jsfiddle.net/n4qq4vxh/97/
I am building tables to describe packages selected when making a car. The dark grey is the whole package(ie luxury package), the lighter grey is the items that are currently included in the package. Lastly, the rows with carrots are the 'alternative' options that can replace something that is currently in the package. For example, you can click the 'Leather Dakota Saddle Brown Stitching' and it would replace the 'Oyster Dakota Leather'. Everything works correctly but i need to display it differently.
I need to show the alternatives for each currently selected item(if applicable) under its correct parent, as opposed to just a list of all alternatives at the end. For example, the alternative rims should be displayed directly under the selected rims, the alternative leathers should be displayed directly under the selected leather, etc.
I am not sure that posting my code will help much but please see below. Basically what i am looking for is to find out if there is a way to start repeating through current package content, then compare the alternatives to see if it is a leather, wheel, etc as the parent is...if it is, repeat over the alternatives. Once finished repeating over the alternatives, move back to the next item that is selected in the package. I have tried messing around with this and cannot seem to find a solution/strategy.
How i would like it to appear:
Luxury package
package item: 18" rims
Alt Rim 1
Alt Rim 2
Alt Rim 3
package item: dakota leather
Alt leather 1
Alt leather 2
Alt leather 3
<tbody ng-repeat="package in allOptions | orderBy: 'listPrice'" ng-if="package.isPackage">
<tr class="hover" ng-class="{'selected':isSelected(package)}" ng-click="addRemoveOption(package)" **MAIN PACKAGE **>
<td> {{ package.code }} </td>
<td> {{ package.name }} </td>
<td> {{ package.listPrice | currency }} </td>
<td> {{ package.disclaimer }} </td>
<td> {{ package.salesGroup.name }} </td>
<td> {{ package.optionPrev }} </td>
<td> {{ package.familyCode }} </td>
</tr>
<tr ng-repeat="item in package.packageItems" ng-class="{'nested-selected':isSelected(package)}" id="nested" ** CURRENT PACKAGE CONTENT **>
<td> {{ item.code }} </td>
<td> {{ item.name }} </td>
<td> {{ item.comboPrice | included }} </td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<!-- ng-if="hasAlternatives(package.packageItems)" -->
<tr ng-if="package.packageItems.alts.length" class="nested-alt" ng-repeat="alt in package.packageItems.alts" ng-click="addPackageOption(alt,package)" ng-hide="!isSelected(package)">
** ALTERNATIVES **
<td><span class="glyphicon glyphicon-menu-right" ng-click="addPackageOption(alt,package)"></span></td>
<td> {{ alt.code }} </td>
<td> {{ alt.name }} </td>
<td> {{ alt.price | included }} </td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody>

I was able to fix this with the following code. Basically, what it came down to was not using a table but instead making my own table with div's. This way i was able to provide the full scope 3 layers down the table, while with a standard table i was only able to go two 2 layers deep.
<h3>{{ tableName }}</h3>
<div class="flx flx-column hover packageTable"
ng-repeat="package in list | orderBy: 'listPrice' track by $index"
ng-class="{'selected': package.isSelected}"
ng-click="addRemoveOption(package)">
<div class="flx flx-row" id="anchor{{$index}}">
<div class="flx-cell-1">{{ package.code }}</div>
<div class="flx-cell-1">{{ package.name }}</div>
<div class="flx-cell-1">{{ package.listPrice | currency}}</div>
<div class="flx-cell-2">{{ package.disclaimer }}</div>
<div class="flx-cell-1">{{ package.salesGroup.name }}</div>
<div class="flx-cell-1">{{ package.optionPrev }}</div>
<div class="flx-cell-1">{{ package.familyCode }}</div>
</div>
<br>
<div class="flx flx-column" ng-repeat="item in package.packageItems track by $index"
ng-class="{'package-nested-selected': package.isSelected}"
>
<div class="flx flx-row" id="nested">
<div class="flx-cell-1">{{ item.code }}</div>
<div class="flx-cell-1">{{ item.listPrice | included }}</div>
<div class="flx-cell-2">{{ item.name }}</div>
<div class="flx-cell-1"></div>
<div class="flx-cell-1"></div>
<div class="flx-cell-1"></div>
</div>
<div class="flx flx-row package-nested-alt"
ng-if="item.alts.hasOwnProperty(item.code)"
ng-hide="!package.isSelected"
ng-repeat="alt in item.alts[item.code] track by $index"
ng-click="addPackageOption(alt, package, $event)"
>
<div class="flx-cell-1" id="packageArrow"><span class="glyphicon glyphicon-menu-right" /></div>
<div class="flx-cell-1">{{ alt.code }}</div>
<div class="flx-cell-1">{{ alt.price | included }}</div>
<div class="flx-cell-2">{{ alt.name }}</div>
<div class="flx-cell-1"></div>
<div class="flx-cell-1"></div>
<div class="flx-cell-1"></div>
<!--<div class="flx-cell-1"></div>-->
</div>
</div>
</div>

Related

Converting ng-repeat table to card

i was woundering how i can convert this type of complex ng-repeat from using table to repeat in AngularJS material design.
My markup looks like this now:
<div class="table-responsive">
<table class="table">
<thead>
<tr>
<th>AccountName</th>
<th>AccountID</th>
<th>ContainerID</th>
<th>ContainerName</th>
<th>Path</th>
<th>Favorite</th>
<th>Hide</th>
<th>Count</th>
</tr>
</thead>
<tbody ng-repeat="(k,v) in containers">
<tr ng-repeat="(k1,v1) in v" ng-if="v1.accountId!= null || v1.accountId == ''">
<td>{{ k }}</td>
<td>{{ v1.accountId }}</td>
<td>{{ v1.containerId }}</td>
<td>{{ v1.name }}</td>
<td>View Container</td>
</tr>
</tbody>
</table>
Ive tried using this markup for md-cards but it gets all wrong:
<md-card ng-repeat="(k,v) in containers">
<md-card-content ng-repeat="(k1,v1) in v">
<h2 class="md-title">{{ v1.name }}</h2>
<p>
{{ v1.accountId }}
</p>
</md-card-content>
</md-card>
If you can see the images the request and the ng-repeat it dont look like a table where you have each row for each account/container:
If you don't want to repeat the Acccount value, you can do something like this:
<md-card ng-repeat="(k,v) in containers">
<md-card-content ng-repeat="(k1,v1) in v">
<h2 class="md-title" ng-if="$first">{{ v1.name }}</h2>
<p>
{{ v1.accountId }}
</p>
</md-card-content>
</md-card>
I got it working with this code:
<div class='md-padding' layout="row" flex>
<div layout="row" flex>
<div class="parent" layout="column" ng-repeat="(k,v) in containers">
<md-card ng-repeat="(k1,v1) in v" ng-if="v1.accountId!= null || v1.accountId == ''">
<md-card-content>
AccountName: {{k}}<br>
Accountid: {{ v1.accountId }} <br>
ContainerName: {{ v1.name }}
</md-card-content>
<div class="md-actions" layout="row" layout-align="end center">
<md-button>Save</md-button>
<md-button>View</md-button>
</div>
</md-card>
</div>
</div>
</div>

How to divide rows to two table with angularjs

how to divide rows to two tables with angularjs
<tr ng-repeat="field in node.fields track by $index" ui-tree-node="" class="ng-scope angular-ui-tree-node" collapsed="false" ng-if="$even">
I have tried this but it is not working for drag and drop
<tr data-ng-repeat="element in awesomeThings">
<div ng-if="$even">
<td class="even">
<a href="#">
{{element}}
</a>
</td>
</div>
<div ng-if="$odd">
<td class="odd">
<a href="#">
{{element}}
</a>
</td>
</div>
</tr>

AngularJS ng-repeat group by date formatting issues

I have a JSON array that I need to group by the date.
so using angular-filter I created this:
<ul ng-repeat="(key, value) in controller.collections.data | groupBy: 'plannedCollectionDate'">
Group name: {{ key | date: 'fullDate' }}
<li ng-repeat="item in value">
item: {{ item }}
</li>
</ul>
which is fine, but what I actually want to generate is a table. I tried this:
<div ng-repeat="(key, value) in controller.collections.data | groupBy: 'plannedCollectionDate' | orderBy: 'plannedCollectionDate'">
{{ key | date: 'fullDate' }}
<table class="table table-hover table-light">
<tbody>
<tr ng-repeat="collection in value | filter: controller.filter" ng-click="controller.select(collection)" ng-class="{ active: controller.isSelected(collection), warning: collection.status.id === 2, success: collection.status.id === 4, danger: collection.status.id === 5 }">
<td>
<div>{{ collection.supplierName }} {{ collection.description }}</div>
<div>to be collected by {{ collection.customerName }}</div>
</td>
<td>
<a ui-sref=".collect({ selected: [collection]})">{{ collection.status.name }}</a>
</td>
<td>
<button class="btn btn-danger" ng-click="controller.delete(collection.id)">
<span class="fa fa-close"></span>
</button>
</td>
</tr>
</tbody>
</table>
</div>
which again works fine, it generates a table for each group though. What I would prefer is to have one table with a header for the groupBy dates and then trs for the inner repeat. I imagine I have to do something like ng-repeat-start but I can't get it to work.
Has anyone got any idea how to do what I need?
Actually this wasn't too hard to figure out.
I just changed the way I was thinking about the headers.
This is my solution:
<table class="table table-hover table-light">
<tbody ng-repeat="group in controller.collections.data | groupBy: 'plannedCollectionDate' | toArray: true | orderBy: '-plannedCollectionDate'">
<tr>
<th colspan="3">
{{ group.$key | date: 'fullDate' }}
</th>
</tr>
<tr ng-repeat="collection in group | filter: controller.filter" ng-click="controller.select(collection)" ng-class="{ active: controller.isSelected(collection), warning: collection.status.id === 2, success: collection.status.id === 4, danger: collection.status.id === 5 }">
<td>
<div>{{ collection.supplierName }} {{ collection.description }}</div>
<div>to be collected by {{ collection.customerName }}</div>
</td>
<td>
<a ui-sref=".collect({ selected: [collection]})">{{ collection.status.name }}</a>
</td>
<td>
<button class="btn btn-danger" ng-click="controller.delete(collection.id)">
<span class="fa fa-close"></span>
</button>
</td>
</tr>
</tbody>
</table>

AngularJS filter ng-repeat by index?

I have a table and buttons inside a loop, this picture shows the results of what I get depending on the search
html
<div class="col-sm-4" ng-repeat="x in names">
<div class="panel panel-primary" id= "{{ x.myIndex }}" >
<div class="panel-heading">
<h3 class="panel-title">{{ x.ID }} {{ x.Name }}
<button ng-click="showCommentsWithID(x.ID)" style="float: right;" class="btn btn-xs btn-primary glyphicon glyphicon-comment"> 42</button>
</h3>
</div>
<div class="panel-body">
<table width="" border="0" ng-repeat="c in comments" id= "{{ c.ID}}" ">
<tr>
<td width="30">{{ c.ID }}</td>
<td >{{ c.Comment}}</td>
</tr>
</table>
</div>
</div>
</div><!-- /.col-sm-4 -->
js
function ContactController($scope,$http) {
$scope.showCommentsWithID= function(myID) {
var page = "mySQL.php?func=getComments&id=" + myID;
$http.get(page).success(function(response) {$scope.comments = response;});
}
}
When I click on the comment Button I want to display the comments according to that ID.
This is working fine except that the comments are loaded to all tables and not only to the table with the right ID. In this example I clicked on ID 1 Coka Cola.
Where do I need to apply a filter the js or html? both? ...
![enter image description here][3]stack.imgur.com/gqyPR.jpg
You can simply bind your comments with your product's id in order to make it unique for each product.
What we need to do is to add product's id to $scope.comments as following:
function ContactController($scope,$http) {
$scope.comments = {}; // Init comments object.
$scope.showCommentsWithID= function(myID) {
var page = "mySQL.php?func=getComments&id=" + myID;
$http.get(page).success(function(response) {$scope.comments[myID] = response;});
}
}
Then, you can simply loop through it:
<table width="" border="0" ng-repeat="c in comments[x.ID]" id= "{{ c.ID}}" ">
<tr>
<td width="30">{{ c.ID }}</td>
<td >{{ c.Comment}}</td>
</tr>
</table>

Angular Display NG-Repeat Display

I have the following code to display 3 different types on the page:
Production
Development
Maintenance
And I want the entire section (Production h4 and table/tbody) to disappear if there is no content in filteredResults. (Only appear if there is content)
<span ng-repeat="type in types">
<table class="max-width">
<tbody>
<div class="row" ng-repeat="result in filteredResults = (results | filter:search) | filter: status('status', type)">
<div class="left-header-padding" ng-if="$index==0">
<tr class="pull-left">
<h4 class="title">{{type.charAt(0).toUpperCase() + type.substring(1)}}</h4>
</tr>
</div>
</div>
</tbody>
</table>
</span>
I am currently trying ng-if for content inside the table, checking if ng-repeat occurs and only rendering the if there is content in ng-repeat, but I want the entire section (table included) to disappear when there is no content. Does anyone know how to accomplish this?
if you want hide table put ng-show into table tag ie:
<table class="max-width" ng-show="filteredResults.length >0">
<tbody>
<div class="row" ng-repeat="result in filteredResults = (results | filter:search) | filter: status('status', type)">
<div class="left-header-padding">
<tr class="pull-left">
<h4 class="title">{{type}}</h4>
</tr>
</div>
</div>
</tbody>
add ng-show="filteredResults.length" to your table element
<table ... ng-show="filteredResults.length">
example: http://plnkr.co/edit/WFQzRtXFe3UnvuzA8psa?p=preview
also, iv'e used tr inside tbody instead of div
Try using ng-init to create a local filtered collection and use the ng-if statement to hide the table if there is no items in the filtered collection.
<div ng-repeat="type in types">
<div ng-init="filteredResults = (results | filter:search) | filter: status('status', type)">
<table class="max-width" ng-if="filteredResults.lenght > 0">
<tbody>
<div class="row" ng-repeat="result in >
<div class="left-header-padding" ng-if="$index==0">
<tr class="pull-left">
<h4 class="title">{{type.charAt(0).toUpperCase() + type.substring(1)}}</h4>
</tr>
</div>
</div>
</tbody>
</table>
</div>
</div>
Let me know if you have any questions.

Resources