Add multi-row items to a table with a directive - javascript

This is my model:
$scope.orders = [
{
id: 234324,
created: '2015-05-01T13:53:25.366Z',
orderedBy: 'John Smith',
items: [
{
itemNumber: '225-3',
count: 3,
state: 'Sent'
},
{
itemNumber: '3423-1',
count: 1,
state: 'Waiting from supplier'
}
]
},
{
id: 423423,
created: '2015-06-01T13:53:25.366Z',
orderedBy: 'Eva Andersson',
items: [
{
itemNumber: '423-3',
count: 1,
state: 'Sent'
},
{
itemNumber: '234-3',
count: 3,
state: 'Sent'
}
]
}
]
Its a list with orders where each order has an array with items.
I want to show this in table.
I tried do nest ng-repeats but it proved to be difficult with the static html syntax of a table. I think I manually have to add the subelements somehow. I'm not really sure how.
JsFiddle: http://jsfiddle.net/hadey1cf/4/
Any ideas?

You can have multiple tbody so it's easy to do:
JSFiddle
<tbody ng-repeat="order in orders">
<tr class="active">
<td><b>{{order.id}}</b></td>
<td><b>{{order.orderedBy}}</b></td>
<td>{{order.created | date:'yyyy-MM-dd'}}</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr ng-repeat="item in order.items">
<td></td>
<td></td>
<td></td>
<td>{{item.itemNumber}}</td>
<td>{{item.count}}</td>
<td><span class="label label-success label">{{item.state}}</span></td>
</tr>
</tbody>

Why don't you use nested repeats? Do your first repeat on the tbody and inside it repeat over the rows for the items:
http://jsfiddle.net/mcgraphix/kfnvLts0/1/
<table class="table">
<thead>
<tr>
<th>Order Id</th>
<th>Orderd By</th>
<th>Created</th>
<th>Item id</th>
<th>Count</th>
<th>State</th>
</tr>
</thead>
<tbody ng-repeat="order in orders">
<tr class="active">
<td><b>{{order.id}}</b></td>
<td><b>{{order.orderedBy}}</b></td>
<td>{{order.date | date:'yyyy-MM-dd'}}</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr ng-repeat="item in order.items">
<td></td>
<td></td>
<td></td>
<td>{{item.itemNumber}}</td>
<td>{{item.count}}</td>
<td><span class="label label-success label">{{item.state}}</span></td>
</tr>
</tbody>
</table>

An alternative approach if you for some reason don't want more than one tbody in your table is to use the ng-repeat-start and ng-repeat-end directives as shown here:
<table class="table">
<thead>
<tr>
<th>Order Id</th>
<th>Orderd By</th>
<th>Created</th>
<th>Item id</th>
<th>Count</th>
<th>State</th>
</tr>
</thead>
<tbody>
<!-- repeat will start with this but won't end with the closing tr tag
Instead it will end at the ng-repeat-end directives closing tag. see below-->
<tr class="active" ng-repeat-start="order in orders">
<td><b>{{order.id}}</b></td>
<td><b>{{order.orderedBy}}</b></td>
<td>{{order.date | date:'yyyy-MM-dd'}}</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr ng-repeat="item in order.items">
<td></td>
<td></td>
<td></td>
<td>{{item.itemNumber}}</td>
<td>{{item.count}}</td>
<td><span class="label label-success label">{{item.state}}</span></td>
</tr>
<!-- the outer repeat will end when this tag is closed. I'm seeting "display:none" so that it doesn't show a gap in your table -->
<tr ng-repeat-end><td colspan="6" style="display:none"></td></tr>
</tbody>
</table>
I think my first answer is a better way to go though since logically you have groups of content in your table which is what tbody is for. It is valid html to have more than one as the HTML DTD states:
<!ELEMENT table
(caption?, (col*|colgroup*), thead?, tfoot?, (tbody+|tr+))>
However, it is good to understand how the ng-repeat-start and ng-repeat-end works as there are many cases where this is useful.

You can use the ng-repeat-start and ng-repeat-end directive.
You can find more information about it here
Please see working example
<script type="text/ng-template" id="orders.tmpl.html">
<h2 class="page-header">Orders-directive</h2>
<table class="table">
<thead>
<tr>
<th>Order Id</th>
<th>Orderd By</th>
<th>Created</th>
<th>Item id</th>
<th>Count</th>
<th>State</th>
</tr>
</thead>
<tbody>
<tr class="active" ng-repeat-start="order in orders">
<td><b>{{order.id}}</b></td>
<td><b>{{order.orderedBy}}</b></td>
<td>{{order.date | date:'yyyy-MM-dd'}}</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr ng-repeat-end="" ng-repeat="item in order.items">
<td></td>
<td></td>
<td></td>
<td>{{ item.itemNumber }}</td>
<td>{{ item.count }}</td>
<td><span class="label" data-ng-class="{'label-success':item.state=='Sent', 'label-primary':item.state=='Waiting from supplier'}">{{ item.state }}</span></td>
</tr>
</tbody>
{{content}}
</script>

Related

problem with vue draggable width in table?

I'm using vuedraggable inside a Bulma table, but it creates a styling problem:
It's not a problem of the Bulma table. I used this in my own table, and the same issue occurs.
Here is my code:
<table class="table is-fullwidth is-bordered">
<thead>
<tr>
<th></th>
<th>Name</th>
<th>brand</th>
<th>Date Created</th>
<th colspan="2">Actions</th>
</tr>
</thead>
<tfoot>
<tr>
<th></th>
<th>Name</th>
<th>brand</th>
<th>Date Created</th>
<th colspan="2">Actions</th>
</tr>
</tfoot>
<tbody>
<tr>
<td colspan="5" v-if="featureds.length == 0">0 Models Found</td>
</tr>
<draggable v-model="furds" :options="{group:'furds'}" #start="drag=true" #end="drag=false" #change="onChnage">
<tr class="dragndrop" v-for="featured in furds">
<td class="drag-icon"><i class="fa fa-arrows"></i></td>
<td>{{ featured.name }}</td>
<td>{{ featured.brand.name }}</td>
<td>{{ featured.created_at | moment("MMMM Do, YYYY") }}</td>
<td><a :href="`/manage/featured/${featured.id}`">View</a></td>
<td><a :href="`/manage/featured/${featured.id}/edit`">Edit</a></td>
</tr>
</draggable>
</tbody>
</table>
Instead of wrapping tr with draggable,pass tbody as draggable element.
<draggable element="tbody" v-model="furds">
See the link for better understanding:
https://jsfiddle.net/dede89/L54yu3L9/ (Example with table) (found in vue draggable official doc)
[[Update: full code(based on question)]]
<table class="table is-fullwidth is-bordered">
<thead>
<tr>
<th></th>
<th>Name</th>
<th>brand</th>
<th>Date Created</th>
<th colspan="2">Actions</th>
</tr>
</thead>
<tfoot>
<tr>
<th></th>
<th>Name</th>
<th>brand</th>
<th>Date Created</th>
<th colspan="2">Actions</th>
</tr>
</tfoot>
<draggable element="tbody" v-model="furds"> <!-- change here -->
<tr>
<td colspan="5" v-if="featureds.length == 0">0 Models Found</td>
</tr>
<tr class="dragndrop" v-for="featured in furds">
<td class="drag-icon"><i class="fa fa-arrows"></i></td>
<td>{{ featured.name }}</td>
<td>{{ featured.brand.name }}</td>
<td>{{ featured.created_at | moment("MMMM Do, YYYY") }}</td>
<td><a :href="`/manage/featured/${featured.id}`">View</a></td>
<td><a :href="`/manage/featured/${featured.id}/edit`">Edit</a></td>
</tr>
</draggable>
</table>
<script>
import draggable from "vuedraggable";
export default {
components: {
draggable
},
...
}
</script>
The styling issue occurs because vuedraggable uses a <div> as its root element by default, and that <div> (along with its contents) is stuffed into the first column of the table.
Solution: vuedraggable allows changing its root element with the tag property, so you could set it to tbody, replacing the existing <tbody> in the <table>:
<table>
<!-- FROM THIS: -->
<!--
<tbody> 👈
<draggable> 👈
<tr v-for="featured in furds">
...
</tr>
</draggable>
</tbody>
-->
<!-- TO THIS: -->
<draggable tag="tbody">
<tr v-for="featured in furds">
...
</tr>
</draggable>
<table>

AngularJS - ng-repeat show header just once

I have 2 lists (persons and animals) that I'm displaying with ng-repeat. I want to show these two lists in one table with a heading.
Here is an example how I want to show the data.
I already tried it with ng-show="$first", but that is not the result I want to achieve.
<thead>
<tr>
<th>ID</th>
<th>BIRTHDAY</th>
<th>NAME</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="ps in $ctrl.persons" ng-if="$ctrl.valuePersons == true">
<th ng-show="$first">PERSONS</th>
<td>{{ ps.id }}</td>
<td>{{ ps.birthday | date: 'dd.MM.yyyy'}}</td>
<td>{{ ps.name }}</td>
</tr>
<tr ng-repeat="an in $ctrl.animals" ng-if="$ctrl.valueAnimals == true">
<th ng-show="$first">ANIMALS</th>
<td>{{ an.id }}</td>
<td>{{ an.birthday | date: 'dd.MM.yyyy'}}</td>
<td>{{ an.name }}</td>
</tr>
<tbody>
This will work, as per the documentation for ng-repeat.
...
<tr ng-repeat-start="ps in $ctrl.persons" ng-if="$ctrl.valuePersons == true && $first">
<th>PERSONS</th>
<td></td>
<td></td>
</tr>
<tr ng-repeat-end ng-if="$ctrl.valuePersons == true && !$first">
<td>{{ ps.id }}</td>
<td>{{ ps.birthday | date: 'dd.MM.yyyy'}}</td>
<td>{{ ps.name }}</td>
</tr>
...
This is long but can help you...
<table>
<tr>
<th>ID</th>
<th>BirthDay</th>
<th>NAME</th>
</tr>
<tr>
<td>Persons</td>
<td></td>
<td></td>
</tr>
<tr ng-repeat="ps in $ctrl.persons">
<td>{{ps.id}}<td/>
<td>{{ps.bday}}<td/>
<td>{{ps.name}}<td/>
</tr>
<tr>
<td>Animals</td>
<td></td>
<td></td>
</tr>
<tr ng-repeat="ps in $ctrl.animals">
<td>{{ps.id}}<td/>
<td>{{ps.bday}}<td/>
<td>{{ps.name}}<td/>
</tr>
</table>
var app = angular.module("Profile", [] );
app.controller("ProfileCtrl", function($scope) {
$scope.items = [{'title':'PERSON','data':[{'birth_day':'1/1/2011','name':'a1'},{'birth_day':'1/1/2011','name':'a2'},{'birth_day':'1/1/2011','name':'a3'}]},{'title':'ANIMALS','data':[{'birth_day':'1/1/2011','name':'a1'},{'birth_day':'1/1/2011','name':'a2'},{'birth_day':'1/1/2011','name':'a3'}]}]
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="Profile" ng-controller="ProfileCtrl">
<table class="table" border="1">
<thead>
<tr>
<th>ID</th>
<th>BIRTHDAY</th>
<th>Name</thu>
</tr>
</thead>
<tbody>
<tr ng-repeat-start="item in items" ng-init="main_ind= $index">
<td colspan="3">{{item['title']}}</td>
</tr>
<tr ng-repeat-end ng-repeat="val in item['data']">
<td>{{$index+1}}</td>
<td>{{val['birth_day']}}</td>
<td>{{val['name']}}</td>
</tr>
</tbody>
</table>
</body>

HTML table complex header

Im pretty new to web dev, so please excuse my probable stupidity. and ive got a small display thing. I have a table with a table in it as one of the tds. I want the inner table part of it to have like a composite heading. In the example below the heading would be Hobbies, and the under it the headings of the hobbies table that would NUMBER, HOBBY and DESCRIPTION. So if you look at the entire table the headings are NAME, SURNAME, JOB and then on a level higher HOBBIES with the sub headings on the same level as the first ones. I hope this makes sense. How can i achieve something like this
<table>
<thead>
<tr>
<th>Name</th>
<th>Surname</th>
<th>Job</th>
<th>Hobbies</th>
</tr>
</thead>
<tbody>
<tr>
<td>John</td>
<td>McJohnson</td>
<td>Dentist</td>
<td>
<table>
<tbody>
<tr>
<td>1</td>
<td>Lego</td>
<td>I like to play Lego</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
Something like this? could be styled better but you get the idea...you will have to use js I think if you want the heading moved up seperate from the second table
td table{display:none;}
tr td:nth-child(4){background-color:gray;}
td:hover table{position:absolute;left:200px;background-color:yellow;display:block;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<thead>
<tr>
<th>Name</th>
<th>Surname</th>
<th>Job</th>
<th>Hobbies</th>
</tr>
</thead>
<tbody>
<tr>
<td>John</td>
<td>McJohnson</td>
<td>Dentist</td>
<td>Hover Me
<table>
<thead>
<tr>
<th>Number</th>
<th>Hobby</th>
<th>Comment</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Lego</td>
<td>I like to play Lego</td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr>
<td>John</td>
<td>McJohnson</td>
<td>Dentist</td>
<td>Hover Me
<table>
<thead>
<tr>
<th>Number</th>
<th>Hobby</th>
<th>Comment</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Lego</td>
<td>I like to play Lego</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
/th

angularjs table : tr with category using ng-repeat with list

Given the following model :
[{categoryName: "category1", items:[{name:"item1.1"}{name:"item1.2"},...]},
{categoryName: "category2", items:[{name:"item2.1"},...]},...]
I'd like to create this table :
<table>
<tr>
<th>category1</th>
</tr>
<tr>
<td>item1.1</td>
</tr>
<tr>
<td>item1.2</td>
</tr>
...
<tr>
<th>category2</th>
</tr>
<tr>
<td>item2.1</td>
</tr>
...
</table>
How would you do it using angularjs instructions ?
Nested repeats and the new ng-repeat-start/ng-repeat-end and remembering that it is OK for a <table> to have many bodies and heads:
<table>
<thead ng-repeat-start="x in data">
<tr><th>{{x.categoryName}}</th></tr>
</thead>
<tbody ng-repeat-end>
<tr ng-repeat="y in x.items">
<td>{{y.name}}</td>
</tr>
</tbody>
</table>
Relevant fiddle: http://jsfiddle.net/kGZt8/
Documentation: ngRepeat

How to make a html-table sortable while not sorting specific rows?

I have a html-table, that has a header, that is supposed to be clickable to sort the rows on the clicked column. The tricky part here is, that there are some rows in the table, that shouldn't be sorted and the rows, that belong to that specific row should remain under that row. Here is some code so you get what I'm talking about.
<table>
<thead>
<tr>
<th>User</th>
<th>Item</th>
<th>Price</th>
</tr>
</thead>
<tbody>
<tr>
<th colspan="5" style="text-align:left;">Peter</th>
</tr>
<tr>
<td></td>
<td>Apple</td>
<td>10</td>
</tr>
<tr>
<td></td>
<td>Pineapple</td>
<td>15</td>
</tr>
<tr>
<th colspan="5" style="text-align:left;">Stan</th>
</tr>
<tr>
<td></td>
<td>Banana</td>
<td>7</td>
</tr>
<tr>
<td></td>
<td>Orange</td>
<td>10</td>
</tr>
</tbody>
</table>
So if I click for example on the Item-Header, the Apple + Pineapple rows should remain between the Peter and the Stan row while being sorted. If I click on the User-Header, Peter and Stan should be sorted, while the Items Apple + Pineapple remain under the Peter row and the Banana and Orange Items remain under the Stan row ... I hope you get what I mean.
I have already tried it with the jquery tablesorter-plugin but I couldn't find any solution that was working for me.
You'll need to enclose each block of rows in a separate tbody.
Then clicking on User will only sort the tbodys, and clicking on the other ths will sort each tbody separately.
EDIT
The table should look like this:
<table>
<thead>
<tr>
<th>User</th>
<th>Item</th>
<th>Price</th>
</tr>
</thead>
<tbody>
<tr>
<th colspan="5" style="text-align:left;">Peter</th>
</tr>
<tr>
<td></td>
<td>Apple</td>
<td>10</td>
</tr>
<tr>
<td></td>
<td>Pineapple</td>
<td>15</td>
</tr>
</tbody>
<tbody>
<tr>
<th colspan="5" style="text-align:left;">Stan</th>
</tr>
<tr>
<td></td>
<td>Banana</td>
<td>7</td>
</tr>
<tr>
<td></td>
<td>Orange</td>
<td>10</td>
</tr>
</tbody>

Categories