Angular4 adds second tbody element - javascript

I want to represent some data in several tables. But Angular 4 adds many new divs to it and also a new tbody that destroys my table.
Her the template:
<div *ngFor= "let table of qmc.simplificationTable; let myIndex = index">
<table class="table table-bordered col-md-4">
<thead>
<tr>
<th>Group</th>
<th>Vars</th>
<th>Benutzt</th>
</tr>
</thead>
<tbody>
<div *ngFor= "let group of table let groupIndex = index">
<div *ngFor= "let primeImplicant of group">
<tr>
<td>
{{groupIndex}}
</td>
<td>
{{primeImplicant.toString()}}
</td>
<td>
{{primeImplicant._usedForCombination}}
</td>
</tr>
</div>
</div>
</tbody>
</table>
</div>
this is the html result:
https://pastebin.com/z5UneyMf
You can see that angular4 adds a new tbody element to every
<tr>
These tbodies and the new divs destroies my table.
How can I solve this?

Just replace
<div *ngFor
with
<ng-container *ngFor
Thanks yurzui (idea by yurzui in the comments)

Related

How to get width of a table header cell in JavaScript via DOM?

I have the access to this DOM node in temp1.$el.
And here is the content which the above variable has:
<table id="__BVID__730" aria-busy="false" aria-colcount="10" aria-rowcount="14" class="table b-table table-striped table-hover">
<thead class="thead-class-hidden">
<tr>
<th aria-colindex="1" class="">
<div style="white-space: nowrap;">
Header1 Name
</div>
</th>
<th aria-colindex="2" class="">
<div style="white-space: nowrap;">
Header2 Name
</div>
</th>
</tr>
</thead>
<tbody class="">
<tr class="">
<td aria-colindex="1" class="">
<div style="white-space: nowrap;">
Row1 Column1 Value
</div>
</td>
<td aria-colindex="2" class="">
<div style="white-space: nowrap;">
Row1 Column2 Value
</div>
</td>
</tr>
</tbody>
</table>
I'm working in plain JavaScript and what I need to get is the width of the element under:
table thead tr th (child-1)
table thead tr th (child-2)
I tried many things like:
temp1.$el.tHead.firstElementChild.children[0].offsetWidth
temp1.$el.tHead.firstElementChild.children[0].clientWidth
temp1.$el.tHead.firstElementChild.children[0].firstElementChild.offsetWidth
temp1.$el.tHead.firstElementChild.children[0].firstElementChild.clientWidth
But all of them are not working. The table thead tr th widths depends of the actual content inside of them, and I need to take the widths and later to apply them on a different table.
I managed to get them to the variable temp1.$el but from here, I'm not able to success to get the widths that I need.
You could get this done using the ParentNode property children.
The ParentNode property children is a read-only property that returns a live HTMLCollection which contains all of the child elements of the node upon which it was called.
var element = document.getElementById('__BVID__730');
console.log(element.tHead.children[0].children[0].offsetWidth)
<table id="__BVID__730" aria-busy="false" aria-colcount="10" aria-rowcount="14" class="table b-table table-striped table-hover">
<thead class="thead-class-hidden">
<tr>
<th aria-colindex="1" class="">
<div style="white-space: nowrap;">
Header1 Name
</div>
</th>
<th aria-colindex="2" class="">
<div style="white-space: nowrap;">
Header2 Name
</div>
</th>
</tr>
</thead>
<tbody class="">
<tr class="">
<td aria-colindex="1" class="">
<div style="white-space: nowrap;">
Row1 Column1 Value
</div>
</td>
<td aria-colindex="2" class="">
<div style="white-space: nowrap;">
Row1 Column2 Value
</div>
</td>
</tr>
</tbody>
</table>
What exactly is the $el? This looks like jQuery, and not vanilla js.
Based on your code.
// Table
// Or querySelector('table') if you have only one
const table = document.getElementById("__BVID__730");
console.log(table.clientWidth);
// Thead & Tbody
const thead = table.querySelector("thead");
const tbody = table.querySelector("tbody");
console.log(thead.clientWidth);
console.log(tbody.clientWidth);
// Tr th
const theadColumns = thead.querySelectorAll("tr th");
if (theadColumns) {
console.log(theadColumns[0]);
console.log(theadColumns[1]);
// OR
theadColumns.forEach(column => console.log(column.clientWidth));
}
Here is the working demo to get width of first th (Used jQuery 1.8.3):
http://jsfiddle.net/7dg5bvou/
Also this might help you solve your problem:
first include jQuery library in head section of your HTML.
temp1.$el.find("table[id='__BVID__730']").find(".thead-class-hidden").children("tr:first-child").children("th:first-child").width();
Also you can use "eq" to find respective element like: td:eq(1)

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>

How to create simple tree exmpdable/collapsible view using angularjs and specific data structure

I need tree view control it should just appear as below:
http://plnkr.co/edit/JAIyolmqPqO9KsynSiZp?p=preview
+Parent
child
+Parent
child
child
child
child
+Parent
child
child
child
child
child
child
child
I just need simple tree as shown above, just need collapse- expand features and single level.
using angular 1.6 and bootstrap.
My collection data is - "List of Tasks" and each task has - "List Of Items"
how I could bind this and achieve above tree.
went though other links, but it seems complex with more features
please suggest any option.
Since you need a single level, you can use html table and 2 ng-repeats 1 for tasks and the other for child tasks. You can also also add a buttons to show/hide children.
<table class="table table-hover">
<thead>
<tr>
<td><b>ID</b></td>
<td><b>Task</b></td>
<td></td>
</tr>
</thead>
<tbody ng-repeat="task in ListOfTasks" ng-init="task.showChildren = false">
<tr>
<td>
<span class="label label-success">{{$index+1}}</span>
<span>
<a class="label label-danger" ng-show="!post.showChildren" ng-click="task.showChildren = true">+</a>
<a class="label label-primary" ng-show="post.showChildren" ng-click="task.showChildren = false">-</a>
</span>
</td>
<td>
{{task.TASK_NAME}}
</td>
<td class="table-actions"></td>
</tr>
<tr ng-show="task.showChildren">
<td>
<div class="row">
<div class="col-sm-offset-1">
<table class="table table-hover">
<thead>
<tr>
<td>ID</td>
<td><b>Child Task</b></td>
<td></td>
</tr>
</thead>
<tbody>
<tr ng-repeat="childTasks in task.CHILD_TASKS">
<td class="col-sm-1">
<span class="label label-success">{{ $index + 1 }}</span>
</td>
<td>
{{childTasks.CHILD_TASK_NAME}}
</td>
<td class="table-actions"></td>
</tr>
</tbody>
</table>
</div>
</div>
</td>
</tr>
</tbody>
</table>
The table would look like
Also if you don't wont to get all the data at start, you may getchildren on expand click

ASP.NET MVC Jquery dialog with table show details on row click

I have an ASP.NET MVC application that popup a jQuery dialog. Inside the dialog I have a table that I built dynamicly from a Model I get from controller:
This is the dialog table html:
<script type="text/javascript">
$(function () {
$('#btnslide').click(function () {
});
$('#dtnotes tr').click(function () {
var noteUid = $(this).attr("noteuid");
//*******
// here somehow i need to filter my #Model to get the item
// and then update my DIV 'slideinner' with the details data.
//*******
$(".slideinner").slideToggle();
});
});
</script>
<div class="widget widget-table">
<div class="widget-header">
<span class="icon-list"></span>
<h3 class="icon chart">
Notes</h3>
</div>
<div class="widget-content">
<table id="dtnotes" class="table table-bordered table-striped data-table">
<thead>
<tr>
<th>
Subject
</th>
<th style="width: 70px;">
Type
</th>
<th style="width: 70px;">
UserName
</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr class="gradeA" noteuid="#item.NoteUid">
<td>
#item.Subject
</td>
<td>
#item.NoteTypeDesc
</td>
<td nowrap>
#item.UserName
</td>
</tr>
}
</tbody>
</table>
<button id="btnslide">slide it</button>
</div>
<!-- .widget-content -->
</div>
<div class="slideinner">
<p>Subject</p>
<p>Body</p>
</div>
<!-- .widget -->
I have also a div at the bottom that is a slide div. So when the user clicks on a table row then the div slides up.
What I want is to click on that table row and the DIV must show extra detail information from my Model item.
So I guess I have to be able to get the Model item from the table row "item.NoteUid" key, then update using jquery the "slideinner" div with the item model data.
Hope someone can help me. Appreciate
You can render all the model data you need in the table body and hide the ones you need to with css display:none. I hid the #model.body value in a so you can so retrieve with jquery
$('#dtnotes tr').click(function () {
var noteUid = $(this).attr("noteuid");
//*******
$('.slideinner > p.body').html($(this).children('.body').html());
$('.slideinner > p.subject').html($(this).children('.subject').html());
//*******
$(".slideinner").slideToggle();
});
<tbody>
#foreach (var item in Model)
{
<tr class="gradeA" noteuid="#item.NoteUid">
<td class="subject">
#item.Subject
</td>
<td class="body" style="display:none;">
#item.Body
</td>
<td class="notetypedesc">
#item.NoteTypeDesc
</td>
<td nowrap>
#item.UserName
</td>
</tr>
}
</tbody>
<div class="slideinner">
<p class="subject">Subject</p>
<p class="body">Body</p>
</div>

JavaScript insertAfter and insertBefore

I am playing around with the JavaScript functions insertAfter and insertBefore, however I am trying to insertAfter and insertBefore two elements.
For instance, consider the following HTML:
<table>
<tbody>
<tr>
<td>
Item 1
</td>
<td>
<div class="moveUpDown">
<div class="up">
</div>
<div class="down">
</div>
<div>
</div>
</div>
</td>
</tr>
<tr>
<td colspan="2">
<table>
<tr>
<td>
1
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td>
Item 2
</td>
<td>
<div class="moveUpDown">
<div class="up">
</div>
<div class="down">
</div>
<div>
</div>
</div>
</td>
</tr>
<tr>
<td colspan="2">
<table>
<tr>
<td>
1
</td>
</tr>
</table>
</td>
</tr>
</table>
Then I have this JavaScript code snippet:
var row = $(this).parents("tr:first");
if ($(this).is(".up")) {
row.insertBefore(row.prev());
} else {
row.insertAfter(row.next());
}
Basically when the Up class is called, the previous row is moved up and when the Down class is called, the current row is moved down one row.
What I want to do, is move the rows Up/Down 2 rows... meaning something like row.prev().prev() or row.next().next() however this does not seem to work.
Is there an easy way around this?
Would appreciate any help/suggestions.
to go up
row.prev().prev().before(row)
to go down
row.next().next().after(row)
obviously the tr must exist prev/next have to exist
NB you are caching row as the first tr element so row is changing every time the first tr element change
listen to event
$("table").on("click","tr > td > span.moveup", function() {
var row = $(this).parent().parent();
if (row.prev().prev().get(0)) row.prev().prev().before(row)
})

Categories

Resources