Best practice for Angular ng-repeat with nested data - javascript

I have the following code that I admit looks pretty gross. Anyone have a suggest for cleaning it up and making it a bit more scalable without using nested tables?
<tr data-ng-repeat="data in displayData">
<td data-ng-show="data.name">
{{data.name}}
</td>
<td data-ng-show="data.cols[0]" data-ng-repeat="value in data.cols[0]">
{{value}}
</td>
<td data-ng-show="data.cols[1]" data-ng-repeat="value in data.cols[1]">
{{value}}
</td>
<td data-ng-show="data.cols[2]" data-ng-repeat="value in data.cols[2]">
{{value}}
</td>
<td data-ng-show="data.cols[3]" data-ng-repeat="value in data.cols[4]">
{{value}}
</td>
<td data-ng-show="data.cols[4]" data-ng-repeat="value in data.cols[3]">
{{value}}
</td>
</tr>

I think this is what you're trying to achieve, but I'm not entirely sure by looking at your code.
<tr data-ng-repeat="data in displayData">
<td data-ng-show="data.name">
{{data.name}}
</td>
<td data-ng-show="column" data-ng-repeat="column in data.cols">
{{ column.value }}
</td>
</tr>

What I did was actually flatten data.cols to one array in the controller. Something like this:
var merged = [].concat.apply([], row.cols);
row.cols = merged;
$scope.displayData.push(row);

Related

How to dynamically load the nested array attributes in html table using angularjs?

This is the code that I tried but only values of cardno and cardtype why am I not able to access the rest of them? Any suggestions?
<tr ng-repeat="data in myData17.layouts">
<td ng-show="$index==1">{{data.name}}</td>
<td ng-show="$index==1">
<table>
<tr ng-repeat="card in data.cards">
<td>{{card.cardNo}}</td>
</tr>
</table>
</td>
<td ng-show="$index==1">
<table>
<tr ng-repeat="card in data.cards">
<td>{{card.cardType}}</td>
</tr>
</table>
</td>
<td ng-show="$index==1">
<table>
<tr ng-repeat="card in data.cards.ports">
<td>{{card.portNo}}</td>
</tr>
</table>
</td>
<td ng-show="$index==1">
<table>
<tr ng-repeat="card in data.cards.ports">
<td>{{card.portName}}</td>
</tr>
</table>
</td>
<td ng-show="$index==1">
<table>
<tr ng-repeat="card in data.cards.ports">
<td>{{card.portType}}</td>
</tr>
</table>
</td>
<td ng-show="$index==1">
<table>
<tr ng-repeat="card in data.cards.ports">
<td>{{card.portspeed}}</td>
</tr>
</table>
</td>
<td ng-show="$index==1">
<table>
<tr ng-repeat="card in data.cards.ports">
<td>{{card["ds-scheduler-node-profile"]}}</td>
</tr>
</table>
</td>
</tr>
This is the my data.
{
"name": "twoCardOneEthportAndOne10G",
"cards": [{
"cardNo": "1",
"cardType": "Ethernet",
"ports": [{
"portNo": "1",
"portName": "LAN1",
"portType": "ethernetCsmacd",
"portspeed": "eth-if-speed-1gb",
"ds-scheduler-node-profile": "default"
}]
},
{
"cardNo": "10",
"cardType": "Ethernet",
"ports": [{
"portNo": "1",
"portName": "10GE",
"portType": "ethernetCsmacd",
"portspeed": "eth-if-speed-10gb",
"ds-scheduler-node-profile": "default"
}]
}]
}
data.cards.ports isn’t a thing.
The ports property is of a singular card and cards is an array.
It would have to be accessed like so:
data.cards[0].ports
So, how would this be structured in your code? You would need something like this (this isn’t a solution to your exact implementation just a visual guide to help you access your data in the way you require)
<div ng-repeat=“data in myData17.layouts”>
{{ data.name }}
<div ng-repeat=“card in data.cards”>
{{ card.cardNo }}
<div ng-repeat=“port in card.ports”>
{{ port.portNo }}
</div>
</div>
</div>
Hope that this gives you a better understanding and good luck

Double *ngFor in a table - Angular 2

I need to create a table based in two loops. I have tried the following:
<tbody *ngIf="testCases">
<tr class="pointer" *ngFor="let car of cars; let bike of bikes">
<td class="center">{{car?.id}}</td>
<td class="center">{{bike?.id}}</td>
</tr>
</tbody>
I know the I get the data because I have tried it in typescript with console.log but when I display it in HTML I print null for bike
You can use <ng-container>. It is a helper element that allows to use *ngFor, *ngIf, or other structural directives but doesn't actually create HTML content.
<ng-container *ngFor="let car of cars">
<tr class="pointer" *ngFor="let bike of bikes">
<td>{{car.id}} {{bike.id}}</td>
</tr>
</ng-container>
If both have same no of records , you can do it like
<tr class="pointer" *ngFor="let car of cars; let i = index;">
<td class="center">{{cars[i]?.id}}</td> // or <td class="center">{{car?.id}}</td>
<td class="center">{{bikes[i]?.id}}</td>
</tr>
In your typescript code you can do this:
vehicles = (<any[]>cars).concat(<any>[bikes]);
And then in your view you can bind it easily like:
<tr class="pointer" *ngFor="let vehicle of vehicles">
<td *ngIf="vehicle.vehicleType === 'car'" class="center">{{vehicle.id}} is car</td>
<td *ngIf="vehicle.vehicleType === 'bike'" class="center">{{vehicle.id}} is bike</td>
</tr>
You cannot use on the same line, try it as separate rows
<tbody *ngIf="testCases">
<tr class="pointer" *ngFor="let car of cars ">
<td class="center">{{car?.id}}</td>
</tr>
<tr class="pointer" *ngFor="let bike of bikes">
<td class="center">{{bike?.id}}</td>
</tr>
</tbody>
EDIT
if you want on the same row use index which will hold the array value
<tr class="pointer" *ngFor="let car of cars; let x = index;">
<td class="center">{{cars[x]?.id}}</td>
<td class="center">{{bikes[x]?.id}}</td>
</tr>

Simple jQuery selector isn't working

I'm trying to parse this HTML:
<tr id="a">
<td class="classA">
<span class="classB">Toronto</span>
</td>
<td class="classC">
<span class="classD">Winnipeg</span>
</td>
</tr>
<tr id="b">
<td class="classA">
<span class="classB">Montreal</span>
</td>
<td class="classC">
<span class="classD">Calgary</span>
</td>
</tr>
I have a variable team. I want to find the <span> that contains team. Then I want to navigate up to the <tr> and pull the id from it.
I tried:
var team = "Toronto";
var id = $("span:contains(" + team + ")").parent().parent().attr('id');
But it comes back undefined. I know the selector is right, because $("span:contains(" + team + ")").attr('class') comes back with classB. So I can't figure out what's wrong with my query. Can anyone help?
Edit: Here's the JSFiddle.
Your html is invalid but your selector is correct, you need to put tr in table tag for valid html. You better use closest("tr") instead of .parent().parent()
Live Demo
<table>
<tr id="a">
<td class="classA"> <span class="classB">Toronto</span>
</td>
<td class="classC"> <span class="classD">Winnipeg</span>
</td>
</tr>
<tr id="b">
<td class="classA"> <span class="classB">Montreal</span>
</td>
<td class="classC"> <span class="classD">Calgary</span>
</td>
</tr>
</table>
It's not working becuase the browser's automatically fixing your HTML. You can't have a TR without a table so it's just throwing it away. All that's actually part of the DOM by the time your JavaScript runs is the spans.
Wrap it in a <table> and your code will work. Even better wrap it in <table><tbody> because the browser will still be making a tbody for you with just a table & that might cause confusion next (If you look at the parent of the TR).
Currently your HTML markup is invalid, you need to wrap <tr> element inside <table>:
<table>
<tr id="a">
<td class="classA"> <span class="classB">Toronto</span>
</td>
<td class="classC"> <span class="classD">Winnipeg</span>
</td>
</tr>
<tr id="b">
<td class="classA"> <span class="classB">Montreal</span>
</td>
<td class="classC"> <span class="classD">Calgary</span>
</td>
</tr>
</table>
Also, it's better to use .closest() as well as .prop() instead of .parent() and .attr()
var id = $("span:contains(" + team + ")").closest('tr').prop('id');
Fiddle Demo
try:
var id = $("span:contains(" + team + ")").parent('td').parent('tr').attr('id');
Your code works good.Just wrap your code into <table></table>
HTML
<table>
<tr id="a">
<td class="classA">
<span class="classB">Toronto</span>
</td>
<td class="classC">
<span class="classD">Winnipeg</span>
</td>
</tr>
<tr id="b">
<td class="classA">
<span class="classB">Montreal</span>
</td>
<td class="classC">
<span class="classD">Calgary</span>
</td>
</tr>
</table>
Script
var team = "Toronto";
var id = $("span:contains(" + team + ")").closest('tr').prop('id');
console.log(id)
http://jsfiddle.net/7Eh7L/
Better use closest()
$("span:contains(" + team + ")").closest('tr').prop('id');

How to get everything that inside tbody using jquery?

I have my html table: this is part of it
<tbody id="summaryBody">
<tr class="summaryRow">
<td class="summaryPerson" colspan="2">
Super Man
</td>
<td class="summaryFromDate">
11/21/2013
</td>
<td class="summaryToDate">
11/21/2013
</td>
<td class="summaryOriginalRecords">
1
</td>
<td class="summaryOriginalHours">
2.00
</td>
<td class="summaryExcludedHours">
0
</td>
<td class="summaryTotalHours">
2.00
</td>
</tr>
<tr class="summaryRow">
<td class="summaryPerson" colspan="2"> … </td>
<td class="summaryFromDate"> … </td>
<td class="summaryToDate"> … </td>
<td class="summaryOriginalRecords"> … </td>
<td class="summaryOriginalHours"> … </td>
<td class="summaryExcludedHours"> … </td>
<td class="summaryTotalHours"> … </td>
</tr>
<tr class="summaryRow">
<td class="summaryPerson" colspan="2"> … </td>
<td class="summaryFromDate"> … </td>
<td class="summaryToDate"> … </td>
<td class="summaryOriginalRecords"> … </td>
<td class="summaryOriginalHours"> … </td>
<td class="summaryExcludedHours"> … </td>
<td class="summaryTotalHours"> … </td>
</tr>
</tbody>
I want to get everything that is inside tbody element with all attributes and texts. How to do this using jquery?
I know only way when I can loop through each tr
$('tbody > tr').each()
but in this case I will need to select every attr and class and text and etc... It seems pretty hard. Is it any good way to get all elements? Maybe collection of tr element as text?
Help please=)
You can get the html contents of the tbody using .html()
var html = $('tbody').html();//using the id $('#summaryBody').html()
It's pretty simple:
$("tbody").html();

jQuery Traversing

My page has this design.
<tr id="master">
<td id="row1"> <textbot> </td>
<td id="row2"> <linkbutton> </td>
</tr>
I am cloning the same TR onclick of the link button and the current link button will be hidden. so a new row will be created.
consider I have cloned thrice
<tr id="master">
<td id="row1"> <textbot> </td>
<td id="row2"> <linkbutton> </td>
</tr>
<tr id="master">
<td id="row1"> <textbot> </td>
<td id="row2"> <linkbutton> </td>
</tr>
<tr id="master">
<td id="row1"> <textbot> </td>
<td id="row2"> <linkbutton> </td>
</tr>
Now I want to show the second row's link button.
I am trying with
$(this).parents('#master :last').prev().children('#row2).show();
But its not working.
You can't/shouldn't clone elements that have IDs, because IDs are supposed to be unique in a document. Although a browser will happily let you have the same ID twice, Javascript and jQuery do not forgive you for this and things will not work as expected. The proper way to group elements is by classes.
So if you switch your code to this:
<tr class="master">
<td class="row1"> <textbot> </td>
<td class="row2"> <linkbutton> </td>
</tr>
Your selector might look like this:
$('tr.master').eq(1).find('td.row2').show();
you know, ID must be unique .. so i recommend to change all id to class.
i think the syntax for parrent should :
$('#master:parent');

Categories

Resources