I am new to angular. I have a set of rows(tr) in the table generated using *ngFor, for each table row(tr) i have a click event, when user clicks on the tr i have expand/collapse functionality to show the data in table format below the tr
Now when the user clicks on the tr, i am calling an API which provides me the data specific to the clicked tr, I am setting that data in the variable which i am using to display in the expanded tr functionality. Until now everything works fine, but when i click on the next tr the data for the previously clicked tr also gets changed and displays the data for the current tr.
<ng-container *ngFor="let data of pageData">
<tr (click)="toggleTable(data.id)">
<td>{{data.x}}</td>
<td>{{data.y}}</td>
<td>{{data.z}}</td>
<td>{{data.a}}</td>
<td>{{data.b}}</td>
</tr>
<tr *ngIf="data.id===currDataid && openTable">
<td colspan="8" [ngClass]="{'p-2': true}">
<div>
...
<tr *ngFor="let idApiData of allApiData"> //problem here: id API data remains same for all parent tr when the user clicks on any parent tr
</tr>
</div>
</td>
</tr>
</ng-container>
All i need is the tr with *ngIf should display the data specific to the id passed, but when the user clicks on multiple tr, data for all the expanded functionality gets changed and displays data with respect to variable set.
is there any way by which i can maintain the data previously clicked tr ?
Add an expanded property to object to handle the expand collapse functionality. And you have to define a method to filter the details of the clicked row
<ng-container *ngFor="let data of data1">
<tr (click)="data.expanded = !data.expanded">
<td> {{ data.expanded ? '–' : '+'}} {{data.name}} </td>
<td> {{data.place}} </td>
<td> {{data.phone}} </td>
<td> {{data.hobbies}} </td>
<td> {{data.profession}} </td>
</tr>
<ng-container *ngIf="data.expanded">
<tr *ngFor="let details of subData(data)">
<td> {{details.datades.name}} </td>
<td> {{details.datades.hobbies}} </td>
<td> {{details.datades.profession}} </td>
</tr>
</ng-container>
</ng-container>
Filter data using the below function or you can create a pipe for that
subData(data) {
return this.data.filter(x => x.id=== data.id);
}
Related
So let's skip the the table headers to my table body. I have a populated table:
HTML:
<tbody>
<tr *ngFor="let e of emails; let i = index">
<td <input type="checkbox" id="email-checkbox" (change)="addToSelectedList($event, e)"></input></td>
<td id="subject-{{i}}">{{e.sender}}</td>
<td id="subject-{{i}}">{{e.subject}}</td>
<td id="subject-{{i}}">{{e.date}}</td>
</tbody>
I want the table whole row to display a CSS class when the user checks the checkbox. And then the color should go back to normal when the user deselects. Just UI stuff to show the user that an email has been selected. I currently have an empty CSS and .ts file.
The way you have done it here is more involved because presumably you have some logic inside addToSelectedList event that will add/remove the email depending on the checked state. The easiest way is to add a property on the email entity isSelected, and do this:
<input ... [checked]="e.isSelected" >
On your tr add the ngclass binding as suggested by others as follows:
<tr [ngClass]="{ 'selectedcssclass' : e.isSelected }"...
Other observation in your code there isn't a closing tr that should be wrapping around all the tds.
Not an Angular expert, but you can achieve just that using a JS onchange event bound to your checkbox:
$(".box").on("change", function() {
$(this).parents("tr").toggleClass("highlight");
});
.highlight {
background-color: #ffff00;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<tr>
<td>Label 1</td>
<td><input type="checkbox" class="box"/></td>
</tr>
<tr>
<td>Label 2</td>
<td><input type="checkbox" class="box"/></td>
</tr>
</table>
I have a table which has multiple rows and a link on the end.
I want to click on the link in the row which has the text I'm looking for. Example:
<table class="repeater large">
<tbody>
<tr>
<td headers="Cardholder ID" nowrap="nowrap">1234</td>
<td headers="Cardholder Name">JONATHAN</td>
<td headers="Client Name">Some Company</td>
<td headers="CardStatus">Closed</td>
<td headers="Card Last Four">1234</td>
<td headers="View" nowrap="nowrap"><a id="button" title="Activity" href="#">Activity</a></td>
</tr>
<tr class="alternaterow">
<td headers="Cardholder ID" nowrap="nowrap">5555</td>
<td headers="Cardholder Name">JONATHAN</td>
<td headers="Client Name">Some Company</td>
<td headers="CardStatus">Active</td>
<td headers="Card Last Four">555</td>
<td headers="View" nowrap="nowrap"><a id="button" title="Activity" href="#">Activity</a></td>
</tr>
</tbody>
</table>
I want to click the anchor on the row where Cardholder ID is '5555' I'm curious on how this would be done with CapserJS and finding the specific selector to do this.
I've tried breaking down the table into a array and getting the specific child number.
I was trying to create a way to get to that specific link in the table.
function getLinks() {
var links = document.querySelectorAll('#page > table');
return Array.prototype.map.call(links, function(e) {
return e.getAttribute('id');
});
}
I simple need to get that link on the row of my choice.
You could iterate over the table rows then get the id from the first element.
If the text equals the ID you are looking for then get the last element and click();
var rows = document.querySelectorAll('table tbody tr');
[].forEach.call(rows, function(tr) {
var td = tr.querySelector('td:first-child');
if (td.innerText === '5555')
tr.querySelector('td:last-child').click();
});
See the fiddle here
I have a Vue project with Firebase. I am using v-for for getting data from Firebase database and I have a "description" value. When users click anywhere on tr I want to expand and show only clicked value's description. But in my code; when I click tbody expand all description values. How can I fix this?
My code:
<tbody v-for="item in items" :key="item.id" #click="isClicked = !isClicked">
<tr >
<td>
{{item.name}}
</td>
<td>
{{item.surname}}
</td>
<td>
{{item.explanation}}
</td>
<td>
<span #click="isDelete(item)">X</span>
</td>
</tr>
<tr v-if="isClicked === true">
{{item.desc}}
</tr>
</tbody>
Thank for helping.
Get the index of the loop:
v-for="(item, index) in items"
Make a function which accepts the index as an argument:
setActiveRow(index)
Assign the index to the isClicked variable:
setActiveRow(index) {
this.isClicked = index
}
Now use that as your click function and compare the isClicked variable in your row:
<tbody v-for="(item, index) in items" :key="item.id" #click="setActiveRow(index)">
And then only show the specific row if the index matches:
<tr v-if="isClicked === index">
<td> {{ item.desc }} </td>
</tr>
First you need to understand what actually your code is doing, you are listening to click at tbody, and on click of that you are setting the flag isClicked as true/false, and all your items are v-if(ed) at single flag i.e., isClicked. So whenever the flag changes every v-if will also react, that is why every description is shown, which definitely is not desired.
Listening to click on tbody is wrong you should listen to click at every tr-s, so that you can actually know which tr is clicked. Now on click of any tr, store the id of that tr and display the description of the respective item.
Well there is a small work around you can actually do in your code to make it work as you wanted.
Here is the modified code.
<tbody v-for="item in items" :key="item.id">
<tr #click="isClicked = item.id">
<td>
{{item.name}}
</td>
<td>
{{item.surname}}
</td>
<td>
{{item.explanation}}
</td>
<td>
<span #click="isDelete(item)">X</span>
</td>
</tr>
<tr v-if="isClicked === item.id">
{{item.desc}}
</tr>
</tbody>
I hope it helps.
I have a smaller table with multiple tr and td elements which is part of bigger table bgtable .When I click on that smaller table I have a anchor tag to redirect to some page (this must have to be on click on smaller table). Now my onclick event on this table returning Data1 , Data2 and Data3 all together. How can I capture only last td data which is Data3 always using Jquery ?
my below code returning all td data which I don't want.
so
<a href="www.example.com">
<table>
<tr>
<td> Data1 </td>
</tr>
<tr>
<td> Data2 </td>
</tr>
<tr>
<td> Data3 </td>
</tr>
</table>
</a>
then my JQ :
$(document).ready(function() {
$(".bgtable td").on("click", function() {
console.log($(this).text());
});
});
Note: I can't change my onclick but I have to get the "Data3". Tried ($("td:last".text() ). Not helpful and returns nothing
Okay ... finally it is working with below :
$(this).find("td:last").text() ;
Do anybody knows how to get the one element before last one ?
I have the following HTML
<tbody class="t_bdy">
<tr class="Quotation_List_td">
<td class="item"><a class="button2 crm_insert" href="#">Insert</a><a class="button2 crm_delta" href="#">Delete</a></td>
<td class="Quotation_List_ItemTD description"> </td>
<td class="quantitiy"> </td>
<td class="unit_price"> </td>
<td class="discount"> </td>
<td class="total"> </td>
</tr>
<tr class="Quotation_List_td">
<td class="item"><a class="button2 crm_insert" href="#">Insert</a><a class="button2 crm_delta" href="#">Delete</a></td>
<td class="Quotation_List_ItemTD description"> </td>
<td class="quantitiy"> </td>
<td class="unit_price"> </td>
<td class="discount"> </td>
<td class="total"> </td>
</tr>
</tbody>
I need to insert new <tr> when I click on button with .crm_insert class.
When .crm_insertis clicked, it need to insert a new row at the current location. All
other rows will move down. For example, if insert against row 3 is clicked then
row 3 will be new row inserted and current row 3 etc will move down to become
row 4 etc.
How can I achieve this ?
All answers are good, but I can only accept one : Thanks all
I'd try something like this using closest() and before()
$('a.crm_insert')
.click(function()
{$(this).closest('tr.Quotation_List_td').before(htmlcodeofyounewTRhere);}
)
Hope this will help
Assuming:
Your new row is in the same structure as your current row
You want the new row to also have the 'Insert' functionality
You want a click event handler which does something to this effect:
$('.crm_insert', '#table').on('click', function() {
var currentRow = $(this).closest('tr');
currentRow.clone(true).insertBefore(currentRow);
});
Where #table is the id of your table.
Here's a simple example
If you are inserting something completely different, then you do not need to use on() or clone(), and the code becomes simpler:
$('.crm_insert').click(function() {
var currentRow = $(this).closest('tr');
$('<tr />').insertBefore(currentRow);
});
Where <tr /> would be whatever you are trying to insert.
This might work for you. It'll find the parent tr of the button you just clicked, clone it (including the onClick functionality of the button) and insert that before the parent tr. This will result in a new row containing the same information as the target row though. Depending on what results you want to show in the new row, you might want to alter the code to clear out any copied values too.
$(".crm_insert").live("click", function(){
var tr = $(this).parents("tr.Quotation_List_td");
tr.clone().insertBefore(tr);
});
You can try this
$('.crm_insert').live('click', function(){
var self = $(this);
self.parents('tr.Quotation_List_td').before('add your row here');
});
The latest versions of jquery employ on instead of live.