Vue.Draggable for tables with more than one tbody - javascript

I have table with difficult structure. The real structure of my table is much more difficult.
I try to show it by a simple example.
<table>
<thead>
<th>id</th>
<th>name</th>
</thead>
<tbody>
<tr>
<td>1</td>
<td>1</td>
</tr>
<tr colspan="2">
<td>1</td>
</tr>
</tbody>
<tbody>
<tr>
<td>1</td>
<td>1</td>
</tr>
<tr colspan="2">
<td>1</td>
</tr>
</tbody>
</table>
I use vuejs, and I need to have sortable table (I use vuedraggable component https://github.com/SortableJS/Vue.Draggable).
I have item component with template like this.
<template>
<tbody class="item">
<tr>
<td>{{ item.id }}</td>
<td>{{ item.name }}</td>
</tr>
<tr colspan="2">
<td>{{ item.description }}</td>
</tr>
</tbody>
</template>
And I use it with draggable.
<draggable v-model="items" :element="'table'" :options="{draggable: '.item'}">
<item-component v-for="(item, index) in items" :item="item" :key="item.id">
</item-component>
</draggable>
The Draggable component create outer 'table' element. Everything is working, but how can I add 'thead'?
I try to create one more component - items:
<template>
<table>
<thead>
<th>1</th>
<th>2</th>
</thead>
<slot></slot>
</table>
</template>
But this is not working:
<draggable v-model="items" :element="items-component" :options="{draggable: '.item'}">
<item-component v-for="(item, index) in items" :item="item" :key="item.id">
</item-component>
</draggable>

Since VueDraggable is a custom component, when using the DOM as your template eg. table you will be subject to some restrictions that are inherent to how HTML works, because Vue can only retrieve the template content after the browser has parsed and normalized it.
This will lead to issues when using custom components with elements that have such restrictions
A workaround is to use the is special attribute:
https://v2.vuejs.org/v2/guide/components.html#DOM-Template-Parsing-Caveats
<table>
<thead>
<th>1</th>
<th>2</th>
</thead>
<div is="draggable" element="div" v-model="items">
<tbody v-for="i in items">
<tr>
<td>{{i.id}}</td>
<td>{{i.name}}</td>
</tr>
<tr colspan="2">
<td>{{ item.description }}</td>
</tr>
</tbody>
</div>
</table>

Related

How to push/pass table data from one component to another in angular 9?

I want to push/pass data of table (itemName, Quantity, retailRate and totalQuantity , totalPrice ) to another component(getDataComponent) when I click button (pushData()) also navigate to receive.
I am not able to send table data in controller. Is this approach is good to send data from one component to another with navigation...
HTML: * send.html*
<table class="table table-hover table-sm"
*ngIf="secondTableData.length">
<thead>
<tr class="table-primary">
<td># </td>
<td>Item</td>
<td>Quantity</td>
<td>Price</td>
<td class="pull-right">Action</td>
</tr>
</thead>
<tbody>
<tr *ngFor="let newdata of secondTableData let i=index;">
<td>{{i+1}}</td>
<td>{{ newdata.itemName }}</td> <!--this data to push in receiveComponent -->
<td class="text-center">{{ newdata.Quantity }}</td> <!--this data to push in receiveComponent -->
<td>{{ newdata.retailRate }}</td> <!--this data to push in receiveComponent -->
</tr>
</tbody>
<thead>
<tr class="table-secondary">
<td>#: {{ secondTableData.length }}</td>
<td></td>
<td class="text-center">TQ: {{ totalQuantity }}</td> <!--this data to push in receiveComponent -->
<td>TP: {{ totalPrice }}</td> <!--this data to push in receiveComponent -->
<td></td>
</tr>
</thead>
</table>
<div>
<hr>
<button class="btn btn-primary pull-right" (click)="pushData()">
<i class="fa fa-check" aria-hidden="true"></i> OK
</button>
</div>
</div>```
**Component.ts:** *sendComponent.ts*
```tabeTata:any
pushData(){
let data:any = this.tabeTata.values;
this.routerService.navigate(['./receive'],{
queryParams:{data:JSON.stringify(data)}
})
}```
**receive.Html** *here i am using random data for demo. I want to place received data to respective places*
```<table class="table table-bordered table-sm">
<thead>
<tr>
<th>SN</th>
<th>Product</th>
<th>Unit</th>
<th>Price</th>
<th>Total</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Custom oil </td>
<td>10</td>
<td>34</td>
<td>340</td>
</tr>
<tr>
<td>2</td>
<td>Digital illustraion </td>
<td>12</td>
<td>50</td>
<td>600</td>
</tr>
<tr class="small" style="height: 10px;">
<td colspan="3" style="border: none;"></td>
<td>Gross Amount:</td>
<td>1100</td>
</tr>
<tr class="small">
<td colspan="3" style="border: none;"></td>
<td>Discount:</td>
<td>100</td>
</tr>
<tr class="small">
<td colspan="3" style="border: none;"></td>
<td>VAT</td>
<td>30</td>
</tr>
<tr class="small">
<td colspan="3" style="border: none;"></td>
<td>Net Amont</td>
<td>1030</td>
</tr>
</tbody>
</table>
```
**receivecomponent.ts**
```data:any;
ngOnInit(): void {
// To get data from biling component
this.route.queryParams.subscribe((params)=>{
this.data = JSON.parse(params.data);
console.log(params);
})
}```
**Any one is there to help, May be this one is complex**
try using sharedService between components.
here is an example of 'Component Intercommunication' through services:
https://stackblitz.com/edit/angular-communication-3?file=app%2Fside-bar%2Fside-bar.service.ts
For more information resd this article '3 ways to communicate between Angular components'

Multiple table rows as single component

What would be a way to have multiple table rows in a single Angular component ?
I would like to display two rows per item of a given list, and have it in an HTML table.
I tried using ng-template with a component as attribute to avoid having a component tag breaking the table flow, but the input won't work in that case. Ideally I'm looking for a way to remove the component tag from the dom...
<table>
<thead>
<th>Name</th><th>City</th>
</thead>
<tbody>
<ng-container app-located-person
*ngFor="let person of persons"
[person]="person">
</ng-container>
</tbody>
</table>
App located person
<tr>
<td>{{ person.name }}</td>
<td>{{ person.city }}</td>
</tr>
<tr *ngIf="details">
<td>Last connection</td>
<td>{{ person.lastConnection }}</td>
</tr>
I finally made it not to break the table dom flow by using display: table-row-group; on the component node :)
Why don't you include the tr's inside the ng-container tag?
<table>
<thead>
<th>Name</th><th>City</th>
</thead>
<tbody>
<ng-container
*ngFor="let person of persons"
[person]="person">
<tr>
<td>{{ person.name }}</td>
<td>{{ person.city }}</td>
</tr>
<tr *ngIf="details">
<td>Last connection</td>
<td>{{ person.lastConnection }}</td>
</tr>
</ng-container>
</tbody>
</table>
If you want to use a component:
<table>
<thead>
<th>Name</th><th>City</th>
</thead>
<tbody>
<ng-container
*ngFor="let person of persons">
<app-located-person [person]="person"></app-located-person>
</ng-container>
</tbody>
</table>
Try the following:
<table>
<thead>
<th>Name</th><th>City</th>
</thead>
<tbody>
<ng-container *ngFor="let person of persons">
<tr>
<td>{{person.name}}</td>
<td>{{person.city}}</td>
</tr>
<tr *ngIf="person.lastConnection">
<td>Last connection</td>
<td>{{person.lastConnection}}</td>
</tr>
</ng-container>
</tbody>
</table>
Stackblitz: Link

rowspan for 3 columns using angularJS

I have a category list that contains name and subject list.
The subject list contains name and course list.
The course list contain name.
I want to display this data in table that will rowspan category or subject if they are the same. For example:
Category Subject Course
cat1 sub1 ''
sub2 cour1
cour2
sub3 ''
cat3 ''
Currently I have it working for two columns using this:
<table class="curvetable5" style="width:99%">
<thead>
<tr>
<th width="30%">Category</th>
<th width="30%">Subject</th>
</tr>
</thead>
<tbody ng-repeat="category in organization">
<td rowspan="{{category.subjectList.length+1}}">{{category.categoryName}}</td>
<tr ng-repeat="subject in category.subjectList">
<td>{{ subject.name }}</td>
</tr>
</tbody>
</table>
However, I am having trouble doing it for 3 columns. This is the code I have that is not working. The course name are not being displayed and subject name become listed in column order instead of row order. Any suggestion:
<table class="curvetable5" style="width:99%">
<thead>
<tr>
<th width="30%">Category</th>
<th width="30%">Subject</th>
<th width="40%">Course</th>
</tr>
</thead>
<tbody ng-repeat="category in organization">
<td rowspan="{{category.subjectList.length+1}}">{{category.categoryName}}</td>
<tr ng-repeat="subject in category.subjectList">
<td rowspan="{{subject.courseList.length+1}}">{{ subject.name }}</td>
<tr ng-repeat="course in subject.courseList">
<td>{{ course.name }}</td>
</tr>
</tr>
</tbody>
</table>
Sample Data:
[
{"id":95,"categoryName":"A new catagory",
"subjectList":[{"id":112,"subjectname":"2ndnewcat","curcount":0,
"courseList":"[{\"name\":\"-\",\"curcount\":0}]"},
{"id":76,"subjectname":"ZZZZZZZZZZZZZZZZZZ_class","curcount":0,
"courseList":[{"coursename":"thiswillbenew111111111112","curcount":1}]}]},
{"id":93,"categoryName":"David Test",
"subjectList":[{"id":75,"subjectname":"This is a test","curcount":1,
"courseList":[{"coursename":"newewst1","curcount":0}]}]},
{"id":116,"categoryName":"New Category",
"subjectList":[{"id":79,"subjectname":"New Subject","curcount":2,
"courseList":[{"coursename":"ISO training part 2","curcount":0}]}]},
{"id":0,"categoryName":"cat1",
"subjectList":[{"id":15,"subjectname":"test","curcount":4,
"courseList":"[{\"name\":\"-\",\"curcount\":0}]"}]},
{"id":11,"categoryName":"cat2",
"subjectList":[{"id":68,"subjectname":"asdasd","curcount":5,
"courseList":[{"coursename":"david1","curcount":0},{"coursename":"thisisatest","curcount":0}]}]},
{"id":12,"categoryName":"cate3",
"subjectList":[{"id":12,"subjectname":"newest1","curcount":6,
"courseList":[{"coursename":"cous1","curcount":0}]}]},
{"id":163,"categoryName":"emptylist",
"subjectList":"[{\"name\":\"-\",\"curcount\":0}]"}
]
This is current code I am testing. It will will rowspan the category, display each subject once and then display all the courses for each subject in list in a single cell. I would prefer to rowspan subject too, but this is what I got working so far.
<table class="curvetable5" style="width:99%">
<thead>
<tr>
<th width="30%">Category</th>
<th width="30%">Subject</th>
<th width="40%">Course</th>
</tr>
</thead>
<tbody ng-repeat="category in organization">
<td rowspan="{{category.subjectList.length+1}}">{{category.categoryName}}</td>
<tr ng-repeat="subject in category.subjectList">
<td>{{ subject.subjectname }}</td>
<td> <li ng-repeat="course in subject.courseList" >{{ course.coursename }} </li></td>
</tr>
<td ng-if="category.subjectList.length==27"> </td>
<td ng-if="category.subjectList.length==27"> </td>
</tbody>
</table>
Thanks,
AB
The two column case should be:
<tbody ng-repeat="dept in org.deptList">
<tr ng-repeat="subj in dept.subjList">
<td rowspan="dept.subjList.length+1">
{{dept.name}}
</td>
<td>
{{subj.name}}
</td>
</tr>
</tbody>
For the three column case, nest a <table> in the <td> element:
<tbody ng-repeat="dept in org.deptList">
<tr ng-repeat="subj in dept.subjList">
<td rowspan="dept.subjList.length+1">
{{dept.name}}
</td>
<td>
<table>
<tr ng-repeat="class in subj.classList">
<td rowspan="subj.classList.length+1">
{{subj.name}}
</td>
<td>
{{class.name}}
</td>
</tr>
</table>
</td>
</tr>
</tbody>

How to create a table with alternate colspan with angular?

I want to create a table that look like that:
|¯¯¯¯|¯¯¯¯|¯¯¯¯|¯¯¯¯|¯¯¯¯|
|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|
|¯¯¯¯|¯¯¯¯|¯¯¯¯|¯¯¯¯|¯¯¯¯|
­­­­­­­­­­­­­­­­­|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
with angular, using ng-repeat.
I tried to do it with this html but it doesn't work.
<div ng-controller="MyCtrl">
<table>
<thead>
<tr>
<th>col1</th>
<th>col2</th>
<th>col3</th>
<th>col4</th>
<th>col5</th>
</tr>
</thead>
<tbody>
<div ng-repeat="item in items">
<tr>
<td>{{item.val1}}</td>
<td>{{item.val2}}</td>
<td>{{item.val3}}</td>
<td>{{item.val4}}</td>
<td>{{item.val5}}</td>
</tr>
<tr>
<td colspan="5">QWERTY</td>
</tr>
</div>
</tbody>
</table>
</div>
You can use ng-repeat-start and ng-repeat-end when you can't accomplish what you're after by placing ng-repeat on a single element. Something like:
<tbody>
<tr ng-repeat-start="item in items">
<td>{{item.val1}}</td>
<td>{{item.val2}}</td>
<td>{{item.val3}}</td>
<td>{{item.val4}}</td>
<td>{{item.val5}}</td>
</tr>
<tr ng-repeat-end>
<td colspan="5">QWERTY</td>
</tr>
</tbody>

Create multiple elements in loop Angular2

Edit: About the possible answer: I came across that question/answer too and implemented it that way. However, with the new version of Angular2 the syntax is different. The documentation about ngFor wasn't updated (this is where I looked). So I wrote the wrong code. The documentation about ngFor is updated in the Template Syntax - ngFor. Günter wrote a correct example on how to use it in the newer versions of Angular2 (beta17 or higher).
I'd like to create multiple elements in a loop. This is what I have now:
<table>
<thead>
<th>ID</th>
<th>Name</th>
</thead>
<tbody>
<tr *ngFor="let item of items" class="info">
<td>{{ item['id'] }}</td>
<td>{{ item['name'] }}<td>
</tr>
</tbody>
</table>
What I'd like is under ever tr another tr with details. The desired output should look like this in the browser:
<table>
<thead>
<th>ID</th>
<th>Name</th>
</thead>
<tbody>
<tr class="info">
<td>1</td>
<td>Item 1<td>
</tr>
<tr class="details">
<!-- More detailed info about item 1 -->
</tr>
<tr class="info">
<td>2</td>
<td>Item 2<td>
</tr>
<tr class="details">
<!-- More detailed info about item 2 -->
</tr>
</tbody>
</table>
How can I achieve the desired result?
<template ngFor [ngForOf]="items" let-item> is the canonical for of *ngFor and allows to repeat more than one element.
import {Component} from '#angular/core'
#Component({
selector: 'my-app',
providers: [],
template: `
<div>
<h2>Hello {{name}}</h2>
<table>
<thead>
<th>ID</th>
<th>Name</th>
</thead>
<tbody>
<template ngFor [ngForOf]="items" let-item>
<tr class="info">
<td>{{ item['id'] }}</td>
<td>{{ item['name'] }}<td>
</tr>
<tr class="details">
<td>{{ item['description'] }}<td>
</tr>
</template>
</tbody>
</table>
</div>
`,
directives: []
})
export class App {
items = [
{name: 'name1', id: 1, description: 'description1'}
{name: 'name2', id: 2, description: 'description2'}
{name: 'name3', id: 3, description: 'description3'}
];
constructor() {
this.name = 'Angular2 (Release Candidate!)'
}
}
Plunker example
In contrary to Polymer (for example), using <template> within <tbody> (or other table elements <tr>, ...) also works fine in IE with Angular2, because Angular2 processes the template internally and never adds it to the DOM. In Polymer this would not work because IE removes "unexpected" tags from table elements (which breaks Poymers <template is="dom-repeat">)
See also http://caniuse.com/#search=template
Use following component code:
import { Component } from '#angular/core';
#Component({
selector: 'demo-app',
templateUrl: 'app/app.component.html',
pipes: []
})
export class AppComponent {
constructor() {
this.items = [
{id: 1, name: 'Bob', details: 'Bob details'},
{id: 2, name: 'Sarah', details: 'Sarah details'},
{id: 3, name: 'Sam', details: 'Sam details'},
{id: 4, name: 'Susan', details: 'Susan details'}
];
}
}
With following app.component.html file:
<table>
<thead>
<th>ID</th>
<th>Name</th>
</thead>
<tbody>
<template ngFor [ngForOf]="items" let-item>
<tr class="info">
<td>{{ item['id'] }}</td>
<td>{{ item['name'] }}<td>
</tr>
<tr class="details">
<td colspan=2>{{ item['details'] }}</td>
<!-- More detailed info about item -->
</tr>
</template>
</tbody>
</table>
Result is something like this:
<table>
<thead>
<th>ID</th>
<th>Name</th>
</thead>
<tbody>
<tr class="info">
<td>1</td>
<td>Bob</td><td>
</td></tr>
<tr class="details">
<td colspan="2">Bob details</td>
</tr>
<tr class="info">
<td>2</td>
<td>Sarah</td><td>
</td></tr>
<tr class="details">
<td colspan="2">Sarah details</td>
</tr>
<tr class="info">
<td>3</td>
<td>Sam</td><td>
</td></tr>
<tr class="details">
<td colspan="2">Sam details</td>
</tr>
<tr class="info">
<td>4</td>
<td>Susan</td><td>
</td></tr>
<tr class="details">
<td colspan="2">Susan details</td>
</tr>
</tbody>
</table>
For more information read https://coryrylan.com/blog/angular-2-ng-for-syntax
You can achieve this by looping on <tbody> instead of <tr>, as tables with mutiple tbody is valid in html refer to.
So your code will be like
<table>
<thead>
<th>ID</th>
<th>Name</th>
</thead>
<tbody *ngFor="let item of items; #idx = index">
<tr class="info">
<td>{{idx}}</td>
<td>Item {{idx}}<td>
</tr>
<tr class="details">
<td>{{ item['id'] }}</td>
<td>{{ item['name'] }}<td>
</tr>
</tbody>
</table>
</table>
Since Angular v4 <template> tag is deprecated.
Use <ng-template> instead, as described in tutorial:
ng-template-element

Categories

Resources