Filtering Data Table in PrimeNG - angular5

How can I get the number of rows after filtering using PrimeNG's default filters in data table.
[totalRecords]="totalRecords" always shows the records count which is fetched initially.
Even though after filtering, totalRecords value remains same and does not change after filtering.
Example:
initially totalRecords is 50 and after filtering, no.of records it shows in data table is 15. But I cannot get the value 15, instead getting 50.
Is there any way ?

Supposing you have a reference to your datatable component, just ask totalRecords property on it :
<p-dataTable [value]="cars" [rows]="10" [paginator]="true" [globalFilter]="gb" #dt>
...
</p-dataTable>
{{ dt.totalRecords }} records
Demo

The above answer is correct and I'm adding up a little thing to it.
If you want to bind the totalRecords value to your typescript .ts file, then use an (onFilter) event and trigger a function with parameters as $event and dt.totalRecords
In my case, i have given
<p-table #dt [value]="personListData" [columns]="columns" (onPage)="onPageChange($event)" [resizableColumns]="true" [paginator]="true" [rows]="rowsCount" selectionMode="multiple" [(selection)]="selected_data" [loading]="loading" [totalRecords]="totalRecords" class="table table-hover table-responsive table-bordered" [responsive]="true" (onFilter)="handleFilter($event,dt.totalRecords)">
In short,
(onFilter)="handleFilter($event,dt.totalRecords)"
Function in .ts file ,
handleFilter(e,filteredRecordCount){
console.log("filteredRecordCount");
}
NOTE: If you want to use the filtered records count value, then you
can assign it to any variable and use anywhere in your typescript
file.

I'm on Angular 8, and my table is not paginated. dt.totalRecords is always the full amount. So if I have 20 rows, and I get it filtered down to 2 on-screen, dt.totalRecords still = 20.
What I ended up doing was using the onFilter, passing in the entire dt, then using dt.filteredValue:
onFilter(event: any, table: any): void {
if(!!table.filteredValue) {
this.visibleRows$.next(table.filteredValue.length);
}
}
You have to check for null, because if you change the filter but don't filter out any additional rows, filteredValue is null.

html:
<p-dataTable #dt (onFilter)="handleFilter()" [value]="cars" [rows]="10" [paginator]="true" >
...
</p-dataTable>
{{ dt.totalRecords }} records
ts:
#ViewChild('dt', { static: true }) dt: Table;
handleFilter() {
if (this.dt.filteredValue != null)
this.dt.totalRecords = this.dt.filteredValue.length;
else
this.dt.totalRecords = this.cars.length;
}

Related

Not able to put tag column value on monday item

I am trying to use python to automation common Monday tasks. I am able to create an item in the board but the column (type=tag) is not updating.
I used this tutorial:
https://support.monday.com/hc/en-us/articles/360013483119-API-Quickstart-Tutorial-Python#
Here is my graphql code that I am executing:
query = 'mutation ($device: String!, $columnVals: JSON!) { create_item (board_id:<myboardid>, item_name:$device, column_values:$columnVals) { id } }'
vars = {'device': device,
'columnVals': json.dumps({
'cloud_name6': {'text': cloudname} # this is where i want to add a tag. cloud_name6 is id of the column.
})
}
data = {'query' : query, 'variables' : vars}
r = requests.post(url=apiUrl, json=data, headers=headers) print(r.json())
I have tried changing id to title as key in the Json string but no luck. I fetched the existing item and tried to add exact json string but still no luck. I also tried below json data without any luck
'columnVals': json.dumps({
'cloud_name6': cloudname
})
Any idea what's wrong with the query?
When creating or mutating tag columns via item queries, you need to send an array of ids of the tags ("tag_ids") that are relating to this item. You don't set or alter tag names via an item query.
Corrected Code
'columnVals': json.dumps({
'cloud_name6': {'tag_ids': [295026,295064]}
})
https://developer.monday.com/api-reference/docs/tags

Angular 8 update text field in response to another field change

The image above represents a project I'm working on. Of the 3 fields, only purchase price data is manually entered. I use the following markup and TS code to set the Outstanding mortgage field to a percentage of the previously provided figure:
<input type="number" class="form-control" min='0' id="purchaseValueInput" formControlName="purchase_value" (ngModelChange)='setPercentages()'>
...
setPercentages() {
this.mortgage = this.analysisForm.value.market.purchase_value * 0.75;
}
My challenge is I need to do a similar thing for the mortgage payments field but as a percentage of the outstanding mortgage value. Because that value is not manually provided the ngModelChange strategy is not working.
How can I resolve that last step?
Update
In my setPercentages() function, I have attempted to set a variable for mortgage payments but I get the following error:
The specified value "NaN" cannot be parsed, or is out of range.
I suspect it's because the field is regarded as empty even though visually it has data in it. I used the following code:
setPercentages() {
this.mortgage = this.analysisForm.value.market.purchase_value * 0.75;
this.mortgagePayments = (this.analysisForm.value.market.outstanding_mortgage * 0.03) / 12;
}
<input type="number" class="form-control" min='0' id="mortgagePaymentValueInput" formControlName="mortgage_payments" [value]="mortgagePayments">
You could try to bind the mortgage payments to a member variable and in the setPercentages function of the other input, you also update the model via that variable.
If ngModelChange doesn't work for some reason you can try to set the value attribute of that input:
<input type="text" value="$300"></input>
I was assigning my percentage values to variables and interpolation to assign the variable as the value of my input field. That proved to the the wrong approach.
What does work is using form patchValue as shown below:
this.analysisForm.patchValue({
market: {
outstanding_mortgage: this.analysisForm.value.market.purchase_value * 0.75,
}
});

Dynamically calculate percentage in a datatable

How can I dynamically calculate a percentage in a datatable when a search is applied ?
The result should be like this :
<tr>
<td>10%</td><td>100</td>
<td>90%</td><td>900</td>
</tr>
The percentage should be based on the total of rows shown.
The following example shows you a basic approach.
The end result looks like this - note you may get a small rounding error when summing the percentages:
The code is as follows:
UPDATE - There was a problem with my original solution - it used jQuery to populate DataTable cells with the calculated percentages. That meant DataTables did not respond to sorting/filtering for the percentages column. It's better to use DataTables functions to populate the data cells.
<body>
<div style="margin: 20px;">
<table id="example" class="display dataTable cell-border" style="width:100%">
<thead>
<tr><th>ID</th><th>Amount</th><th>Percent</th></tr>
</thead>
<tbody>
<tr><td>1</td><td>123.4</td><td class="percent"></td></tr>
<tr><td>2</td><td>234.5</td><td class="percent"></td></tr>
<tr><td>3</td><td>543.21</td><td class="percent"></td></tr>
<tr><td>4</td><td>76</td><td class="percent"></td></tr>
<tr><td>5</td><td>87</td><td class="percent"></td></tr>
</tbody>
</table>
</div>
<script type="text/javascript">
$(document).ready(function() {
var table = $('#example').DataTable({
// wait for table and data to finish being initialized:
"initComplete": function( settings, json ) {
populatePercentages();
}
});
function populatePercentages() {
var total = 0.0;
// first calcuate the total:
$('#example').DataTable().rows().every( function ( rowIdx, tableLoop, rowLoop ) {
// assumes amounts are not null, all numeric, and are in column 2:
total = total + Number(this.data()[1]);
});
// then calculate the percentage for each row:
$('#example').DataTable().rows().every( function ( rowIdx, tableLoop, rowLoop ) {
var amount = this.data()[1];
// calculate percent to 2 decimal places:
var percentage = Math.round((amount / total) * 10000) / 100;
var cells = $('#example').DataTable().cells(rowIdx, 2);
cells.every( function () {
this.data(percentage);
});
});
}
});
</script>
</body>
Points to note:
1) It uses a "percent" class for the cells where percentages will be shown. This makes selection easier.
2) You can do something similar as (1) for the amounts cells also. I did not, here.
3) The code loops through the table data twice: Once to calculate the grand total amount; and again to calculate the percentages.
4) You would need to adjust assumptions about column offsets to fit your table design.
5) There is more validation which should really be added, to handle missing or non-numeric data, to make the code less brittle.
Handling the case when a search is applied:
Filtering:
The above solution can be enhanced to re-calculate percentages when data is filtered.
1) There are two places where the rows() function is used. In both places change this to the following: rows( { search: 'applied' } ). This will ensure only visible rows are considered when percentages are calculated.
2) Add a new section of code to handle keyup events for the search (filter) box. In my case the selector for this input control is as shown below - but this will need to be edited for other datatables with different IDs (my example table's ID is example):
<script type="text/javascript">
$(document).ready(function() {
var table = $('#example').DataTable({
...
});
function populatePercentages() {
...
}
// catch filter events and re-calculate percentages accordingly:
$('div#example_filter.dataTables_filter > label > input').keyup(function (e) {
populatePercentages();
});
});
</script>
With these changes, a filtered list will look like this:

Empy list on return

I have this in my qweb report
<span t-esc="formatLang(get_routing_data(o)[-1]['total'] , digits=3)"/>
it works ok, but sometimes it returns an empty list and then i get error index tuple out of range. how can i avoid it?
You could set the return value of the call to get_routing_data into a variable and make check the value using t-if conditions before use it, like:
<t t-set="routing_data" t-value="get_routing_data(o)"/>
<span t-if="routing_data and len(routing_data) > 0 and routing_data[-1].get('total', False)" t-esc="formatLang(routing_data[-1]['total'], digits=3)"/>

Get 'data-sort' orthogonal value from DataTables within search.push function

I am looping the rows within $.fn.dataTable.ext.search.push function to select some rows based on many criteria. I am setting some values on the TD of the tables known as orthogonal data. I am trying to get the value of the 'data-sort' but I don't know how. I am able to get the cell's inner data via data[2] (for column 2), but not the 'data-sort' or 'data-filter'. Any ideas?
$.fn.dataTable.ext.search.push(
function (settings, data, dataIndex) {
var iRating = parseFloat(data[2]) || 0; // this works
var datasort = //somehow get the data-sort from the TD
);
HTML
<td data-sort="57000" class=" seqNum">.....</td>
Looks like this way I can get the value. If there are any other better ways please advice:
$(settings.aoData[dataIndex].anCells[2]).data('sort')
Yes there is an easier way.
The data parameter is the "search data" for the row. i.e. the values for "filter" data for each col - not your "sort" data / anything else.
But you also have access to the full data object for the row i.e. the 4th parameter - rowData.
So you need to use rowData at the index of the column you want (you say 'for column 2', zero based so - 2 would be for the 3rd column).
Then you should find a property called 'sort' :
function(settings, searchData, index, rowData, counter){
var dataSort = rowData[1]['sort'];
console.log(`This should be the value you want : ${dataSort}`);
}
As per the documentation here