Hide Bootstrap Table Rows in AngularJS (1.6) - angularjs

I have a long table and I'd like to show only the first three entries by default. I'd like to provide something like the table entitled "Additional Metadata" shown on this page with a 'see more' option. The 'see more' link, once clicked, will show the rest of the rows in the table, and an option will appear at the bottom of the table now that says "see less".
I tried playing around with ng-show/ng-hide but couldn't accomplish the aspect where the "see more" link would show at the bottom of the table once all rows are shown. Any help would be appreciated.

Assuming you are using "ng-repeat" to populate the table, you should select an additional "index" or "row no" field and then use a "filter" to filter where the index is less than 4. clicking "see more" can then just change the filter.

Just use the limitTo filter to show n amount of first entries, when n can a scope variable (this is much the same way pagination is usually done in angular)
$filter('limitTo')(input, limit, begin)
You'll set limit to 3, and begin from 0
Inside your ngRepeat
ng-repeat="row in data | limitTo: showAmount : 0"
And inside your controller
$scope.showAmount = 3;

Related

How to get the filtered value of a column in primeng datatable?

I have a datatable with 10 columns. on change of filter value in a column i have to display the alert message with the filtered value.
<p-dataTable #dt [value]="jobslist" [rows]="30" [paginator]="true" [rowsPerPageOptions]="[30,50,75]" sortMode="multiple" scrollable="true" resizableColumns="true" scrollHeight="350px">
<p-column [style]="{'width':'70px'}" field="org" header ="Org" [sortable]="true" [filter]="true"></p-column>
</p-datatable>
If the user enters Org 2 in the filter , it should display "You have selected Org 2". Can anyone please let me know how to do that ?
//CAN'T COMMENT YET SO I AM GOING TO POST
Did you try (onFilter) function that PrimeNG DataTable has? The function takes in the filtering event and there is also event.filtered (as stated on Prime documentation) so you might want to try that approach.

New bindings in already compiled page

I have a problem using the footable plugin with angular,
the problem is that footable appends new table rows to my table, but it pastes raw html text instead of angular replaced values, I mean {{'COMMENT'|translate}} instead of 'Comment' (see 'appended table image')
appended table image
I added click event, to perform special action to reevaluate, but I am not sure how to rebind the element HTML.
Table html
<th data-hide="phone,tablet" >{{'QUANTITY'| translate}}</th>
...
<tr ng-repeat="item in items | filter:itemsFilter" on-last-repeat ng-click="rowExpanded($event)" >
<td>{{item.Stock}}</td>
...
</tr>
Please let me now if you need more info. I'm quite stuck, tried googling, but i thing I don't know the term of my problem.
EDIT: It seems to me that footable caches table headers on init, and then reuses those values that are not compiled by angular yet, maybe that could help to find the answer.
Problem is that angular doesn't know that details row exist, and bindings inside it aren't replaced with values
expanded first row with console view
I figured out, that I need to recompile next element that is appended to the footable, I added ng-click on table rows:
<tr ng-repeat="item in items | filter:itemsFilter" on-last-repeat ng-click="rowExpanded($event)" >
Then in the controller, I found that currentTarget.nextElementSibling will return, next table row, which happens to be that uncompiled, new details row, so $compile does the trick. However this doesn't work when the row is already expanded and window being is resized, added columns in the details row will be in {{variablename}} syntax. But I guess I can live with that downside
$scope.rowExpanded = function($event){
$timeout(function(){
console.log($event.currentTarget.nextElementSibling);
$compile($event.currentTarget.nextElementSibling)($scope);
});
};
EDIT: Ok this didn't work when I used the <progressbar> template. Because at the time when footable reads data it is just a bunch of divs, and when i ask angular to compile those, it cant compile because bunch of divs isn't a >progressbar<
But yet, I found another solution, I delayed the footable initialization after everything is done on angular side:
TL;DR; I removed class 'footable' from table so it wont initialize automatically and call .footable() on the table element only after all of the ng-repeat rows were added (and compiled) to the table. This solves all my current footable/angular relation problems.
Try spacing out your translation statement, so instead of
{{'COMMENT'|translate}}
try
{{ 'COMMENT' | translate }}

Why is my angular grid so slow?

So, I have made some custom directive which draws kind of a data-grid, based on floated divs (because nested flex implementation in FF sucks - but it's not the point).
How it works :
I pass some data collection to the directive via something like <the-grid data-list="parentController.displayedRows">
Inside this first directive, I have columns via something like <a-grid-column data-value="row.value"></a-grid-column> with many attributes I won't precise here.
The data-value value can be a direct expression, bound to the row on which the the-grid directive controller is ng-repeating in order to display each columns, or a function which have to be $eval-uated in order to display the intended value from the parentController.
In my <the-grid> directive controller, I have the rendering template of my grid which make a nested ng-repeat div (first one on the rows of the data-collection, second one on the columns, created in the directive), it looks like :
<div data-ng-repeat="row in list">
<div data-ng-repeat="cell in theGridColumns"
data-ng-bind-html="renderCell(row, cell)">
</div>
</div>
I have some keyboard nav in order to quickly select a row or navigate within pagination or many tabs, which does nothing more than applying some class on the selected row, in addition to update some "selectedRowIndex".
I'm using angular-vs-repeat in order to have the minimum of row divs in my DOM (because the app is running on slow computers). This works well.
The problem is that every time I'm hitting some "up" or "down" key on my keyboard, Angular is "redrawing" EVERY cells of the list.
So, let's suppose I've 200 rows in my data list, and 7 columns for each rows. First load of the page, it passes ~3000 times in the renderCell() function. Ok , let's accept that (don't really understand why, but ok).
I hit the down key in order to go to the second line of my list. It passes ~1100 times in the renderCell() function.
So yes, the result is very slow (imagine if I let the down arrow key pressed in order to quick navigate within my rows)... I can't accept that. If someone could explain that to me... Any help would be greatly accepted :)
If I make the same thing without a directive (direct DOM manipulation, with columns made by hand and not in a ng-repeat within a ng-repeat), every thing is smooth and clean.
Yes, I've look into every angular grid on the market. No one is satisfying me for my purpose, that's why I've decided to create my own one.
And no, I really can't give you some JSFiddle or anything for the moment. The whole app is really tentacular, isolating this is some kind of complicated).
Try to use bind once (angular 1.3+)
<div data-ng-repeat="row in ::list">
<div data-ng-repeat="cell in ::theGridColumns"
data-ng-bind-html="::(renderCell(row, cell))">
</div>
</div>

Conditional render in ng-repeat

I have an Angular webApp running with Bootstrap's css.
What I'm doing now is render a table based on some data stored in a matrix, but in some cases, some rows have not relevant data to show so what I do is hide those irrelevant rows. Problem comes here: bootstrap table that I'm using adds a grey background in the pair rows and white in the odd rows.
the code in the angular template that I use is the following:
<tr ng-repeat="row in estadisticasT1" ng-hide="row.Noches == 0 && estadisticasT2[$index].Noches == 0">
<directive ng-if="comparar && ((row.Noches - estadisticasT2[$index].Noches) >= 0)" class="comparativa2">+{{row.Noches - estadisticasT2[$index].Noches}}</directive>
<directive ng-if="comparar && ((row.Noches - estadisticasT2[$index].Noches) < 0)" class="comparativa3">{{row.Noches - estadisticasT2[$index].Noches}}</directive>
</tr>
I reduced the code to show only the relevant part, tags are useles for this example, the only interesting part is that I use a ng-hide with a comparsion in order to hide the irrelevant rows of my matrix, but the problem is that in some cases it renders like this:
As you can see the first two rows have a grey background and the next two have a white background. What I need to do is to show a grey background in the odd rows and white in the pair ones, but I canĀ“t do this using the $index variable because it doesn't corresponds to the shown rows but all the rows being shown or not.
Any angular expert have an idea that could help me here ?
Thanks in advance
Instead of ng-hide, use ng-if. The latter removes the nodes entirely from the DOM tree, and as such, it shouldn't interfere with your parity-based CSS rules. See the details of the differences between nghide, ngshow and ng-if for example here, or in the angular docs themselves.

How can I improve the efficiency of an ng-repeat that includes a filter and a reorder?

I have a grid on my page that is populated like this:
<tr data-ng-repeat="row in grid.view = (grid.data | filter:isProblemInRange | orderBy:option.problemOrderBy[option.sProblemOrderBy].key:option.sProblemSortDirection) track by row.problemId">
The grid can have up to 500 rows. Once the data is retrieved it's possible for a user to filter the rows which is where the isProblemInRange filter is used. It's also possible for the user to reorder the rows. As can be expected this all takes time.
Is there anything that I could do to make this more efficient?
Could I take all of this code out of my ng-repeat and put in the part that creates the grid.view in my controller?
Note that the isProblemInRange is dynamic. As a user types into a select box then after debouncing the numbers entered are used in the filter to restrict the rows that appear on the screen.
One more thing. The data in the grid changes only when the user clicks on a row and it opens a modal. After a user clicks save on the modal then one single row of the grid.data is changed. Is there something I could do to stop ng-repeat from watching every field on every row and have it just respond after my modal has done a save which is the only time the grid data numbers change.
Every filter is callable fom JavaScript code directly. See http://docs.angularjs.org/api/ng.filter:filter for an example of the usage of the "filter" filter.
So you could indeed call these filters directly from your controller each time the data or the user-defined order and criteria change, which would avoid the unnecessary watches.
var filteredData = $filter('filter')($scope.grid.data, $scope.isProblemInRange);
var orderedFilteredData = $filter('orderBy')(filteredData,
$scope.option.problemOrderBy[option.sProblemOrderBy].key,
$scope.option.sProblemSortDirection);
$scope.orderedFilteredData = orderedFilteredData;
And then in your view, you just need to iterate on the already filtered and ordered data:
<tr data-ng-repeat="row in orderedFilteredData">

Resources