Angular 6: How to detect table data change in Angular? - javascript

I am generating a very simple table by binding a table to an array. And I use the contenteditable="true" so I can edit each cell data on the client side. Here is my code:
<table class="table">
<tr>
<th>Id</th>
<th>Value</th>
<th></th>
</tr>
<tr *ngFor="let item of keys">
<td>{{ item.id }}</td>
<td contenteditable="true">
{{ item.Value }}
</td>
<td>
<button type="button" (click)="printContent()" class="btn btn-primary">Print</button>
</td>
</tr>
</table>
How can I detect the text changes on the cell that has contenteditable set to true

Related

how to dynamically add row after cell 5 vue.js

I am currently working on my app. I am using vue v2
I'm trying to create a dynamic table where I can add rows and Sub rows on button click.
Currently i can insert row without problem but if 1 cell has long text that took 2 rows it messed up
I am trying to achieve this:
Here is my current result:
<button #click="addMe">add row</button>
<table>
<thead>
<tr title="first">
<th style="width:50px">cell1</th>
<th style="width:150px">cell2</th>
<th>cell3</th>
<th>cell4</th>
<th>cell5</th>
<th>cell6</th>
<th>cell7</th>
<th>cell8</th>
<th>cell9</th>
<th>cell10</th>
</tr>
</thead>
<tbody>
<tr v-for="item in data" :key="item.id">
<td>{{ item.id }}</td>
<td>{{ item.name }}</td>
<td>{{ item.score }}</td>
<td>{{ item.profile }}</td>
<td class="new-td">
<tr v-for="item in list" :key="item">
<td>
row1
superlongtextcell5
</td>
</tr>
</td>
<td class="new-td">
<tr v-for="item in list" :key="item">
<td>
row1
cell6
</td>
</tr>
</td>
<td class="new-td">
<tr v-for="item in list" :key="item">
<td>
row1
cell7
</td>
</tr>
</td>
<td class="new-td">
<tr v-for="item in list" :key="item">
<td>
row1
cell8
</td>
</tr>
</td>
<td class="new-td">
<tr v-for="item in list" :key="item">
<td>
row1
cell9
</td>
</tr>
</td>
<td class="new-td">
<tr v-for="item in list" :key="item">
<td>
row1
cell10
</td>
</tr>
</td>
</tr>
</tbody>
</table>
data() {
return {
list: [1],
data: [
{ name: "row1 cell1" },
{ name: "row2 cell1" },
{ name: "row3 cell1" },
{ name: "row4 cell1" },
{ name: "row5 cell1" }
]
}
},
methods: {
addMe() {
this.list.push(1);
}
}
is it possible to do?
thank you
I don't think the problem lies in Vue, you may just have to vertically align the cells or whatever you prefer and clean up the HTML.
Vertical align
Replace vertical-align:bottom with vertical-align:top here to see:
https://www.w3schools.com/tags/tryit.asp?filename=tryhtml_td_valign_css
Use table for extra tr tags
You are mixing td and tr in an incorrect way. A tr tag may never be inside a td tag.
<td class="new-td">
<tr v-for="item in list" :key="item">
<td>
row1
superlongtextcell5
</td>
</tr>
</td>
If you need the rows for layout reasons, you should put a table inside the table:
<td class="new-td">
<table>
<tr v-for="item in list" :key="item">
<td>
row1
superlongtextcell5
</td>
</tr>
</table>
</td>
You can give the table inside the table a design with no borders, margins or paddings and that will create as many rows within the cell as you like.
thank you for you suggestion, i refactor it as per my need
i can achieve it by putting new table inside outer table
<table>
<thead>
<tr title="first">
<th>cell1</th>
<th>cell2</th>
<th>cell3</th>
<th>cell4</th>
<th>cell5</th>
<th>cell6</th>
</tr>
</thead>
<tbody>
<tr v-for="item in data" :key="item.id">
<td>{{ item.id }}</td>
<td>{{ item.name }}</td>
<td>{{ item.score }}</td>
<td>{{ item.profile }}</td>
<template>
<table>
<td>vertically-align1</td>
<td>vertically-align2</td>
</table>
</template>
</tr>
</tbody>
</table>

How to use Accordion under <td> tag? Angular 9

I have a table , when I will click on any of row when a new table should be stretched under the same . I tried to use accordian of ngx-bootrap but I failed.
Basically I need a expandable table inside table. When I will click to any of row I will call a service which will give data for expanding table.
Use this code to get the same table.
sample.component.html
<table class="table">
<tbody>
<ng-container *ngFor="let item of topItem; let i = index">
<tr>
<td width="5%" (click)="toggle(item, i)">
<i aria-hidden="true" class="fa fa-{{ i }}-icon" [ngClass]="{'fa-expand-icon': visible,'fa-compress-icon': !visible}"
></i>
</td>
<td width="20%">{{ item.Name }}</td>
<td width="15%">{{ item.mobile }}</td>
</tr>
<tr class="d-none row-num-{{ i }}">
<td *ngIf="showTable" colspan="2">
<div class="row">
<table class="table">
<tbody>
<tr *ngFor="let item of subsItem; let i = index">
<td>sample data</td>
<td>sample data</td>
</tr>
</tbody>
</table>
</div>
</td>
</tr>
</ng-container>
</tbody>
</table>
Use typescript file sample.component.ts
toggle(item, index) {
let selector = `.row-num-${index}`;
document.querySelector(selector).classList.toggle('d-none');
this.showTable = true;
}

Html datatables data to be accessed in typescript component

I want to access the chosen mfRowsOnPage. For example now it is 10.
Later the user might choose 5 or 15. I need this data in component. I
even want to get which page data is shown to the user. Example 1st
page or 2nd page , so on.
this is my table.
<table class="table" [mfData]="stacklist_table| selectedcolumn | search : searchQuery | filter: addFilter : selected" #stacklist="mfDataTable" [mfRowsOnPage]="10">
<thead>
<tr>
<th *ngFor="let colValues of stacklist.data | column: '' : ''">
<mfDefaultSorter by="{{colValues}}">{{colValues|translate}}</mfDefaultSorter>
</th>
</tr>
</thead>
<tbody>
<tr draggable *ngFor="let stack of stacklist.data" [dragOverClass]="'drag-over-border'" [dragData]="stack" [class.active]="checkIfStackElementIsSelected(stack)" (click)="setStacklistRow(stack, $event)">
<td *ngFor="let rowValues of stack | row">{{ rowValues }}</td>
</tr>
</tbody>
<tfoot>
<tr style="height: 50px;">
<td colspan="6">
<mfBootstrapPaginator [rowsOnPageSet]="[50,100,150]" style="position:fixed; margin-top: -15px"></mfBootstrapPaginator>
<!-- <mfBootstrapPaginator [hidden]='!hideElement' (dblclick)="eventEmitDoubleClick($event)" [rowsOnPageSet]="totalVisibleCount"></mfBootstrapPaginator> -->
<!-- <input [hidden]='hideElement' [(ngModel)]="newCount" (click)="doneEditing(newCount)" autofocus /> -->
</td>
</tr>
<tr (click)="loadMoreStackElements()">Load more</tr>
</tfoot>
</table>
How do I go about it?
I am new to it and not understanding the way to access this data.
https://www.npmjs.com/package/angular2-datatable
Can you try [attr.mfRowsOnPage]='10' and check if that works.

How to show inline details for html table with a toggle button using typescript

I need to create a toggle button for my table (to show/hide) more details of selected row.
Given this is my table:
<table>
<tr>
<th>Company</th>
<th>Contact</th>
<th>Country</th>
</tr>
<tr *ngFor='let c of companies'>
<td><button id="{{c.companyId}}" (click)="showDetail()">Details</button> </td>
<td>{{ c.company}}</td>
<td>{{ c.contact}}</td>
<td>{{ c.country }}</td>
</tr>
</table>
When I click on "Details" button, need to show details inline in the table. This is kind of master detail grid approach in Kendo Grid. Any better approach using Angular2 & typescript to show details in easy way?
A small change from birwin's answer, as you cannot use template here without a directive, so use ng-container instead.
<ng-container *ngFor='let c of companies'>
<tr>
<td><button id="{{c.companyId}}" (click)="c.details = !c.details">Details</button> </td>
<td>{{ c.company}}</td>
<td>{{ c.contact}}</td>
<td>{{ c.country }}</td>
</tr>
<tr *ngIf="c.details">
<td>Details</td>
</tr>
</ng-container>
Demo
You could try something like this:
<table>
<tr>
<th>Company</th>
<th>Contact</th>
<th>Country</th>
</tr>
<ng-container *ngFor='let c of companies'>
<tr>
<td><button id="{{c.companyId}}" (click)="c.details = !c.details">Details</button> </td>
<td>{{ c.company}}</td>
<td>{{ c.contact}}</td>
<td>{{ c.country }}</td>
</tr>
<tr *ngIf="c.details">
<td>Details go here</td>
<td>More details</td>
<td>More details</td>
</tr>
</ng-container>
</table>

Get first value in the first row in ng repeat

View Source:
<div class="well tile single-tile">
<thread></thread>
<table class="table table-hover table-striped table-clickable">
<tbody>
<tr>
<th>Make</th>
<th>Model</th>
<th>Color</th>
<th>Doors</th>
<th>MPG</th>
</tr>
</tbody>
<tbody>
<!-- ng-repeat: car in cars -->
<tr ng-repeat="car in cars" ng-click="car result" class="ng-scope">
<td class="ng-binding">Toyota</td><!--{{car.Make}} -->
<td class="ng-binding">Corolla</td><!--{{car.Model}} -->
<td class="ng-binding">White</td>
<td class="ng-binding">4</td>
<td class="ng-binding">21</td><!--{{car.MPG}} -->
</tr>
<tr ng-repeat="car in cars" ng-click="car result" class="ng-scope">
<td class="ng-binding">Toyota</td><!--{{car.Make}} -->
<td class="ng-binding">Camry</td><!--{{car.Model}} -->
<td class="ng-binding">Black</td>
<td class="ng-binding">4</td>
<td class="ng-binding">20</td><!--{{car.MPG}}
</tr>
</tbody>
</table>
Protractor:
I was able to print all values in first row using
element.all(by.repeater('car in cars')).first().getText().then(function(text){and console.log(text)
and in console I saw "Toyota Corolla White 4 21" successfully.
But I want to print only the first value from first row and second row which is "Toyota". I tried using first().get(1).getText().then(function(text) and first('["$index==1"]').getText() but it's not working. My test is to verify if there is a value other than "Toyota" in first row and second row, it should fail..
Chain and extend Binding on the item.key locators
element.all(by.repeater('car in cars')).first().element(by.binding('car.Make')).getText();
for all elements
element.all(by.repeater('car in cars')).each(function(element, index) {
element(by.binding('car.Make')).getText().then(function(text) {
console.log(text);
});
}); //there might be a better way to do this

Categories