angular only generate part when actually shown - angularjs

I am using angular to show render a bigger dataset. In data.data there are several keys and to each key corresponds an array with around 3000 lines. When the user first open the page all of showraw[key]-s are set to false, so they actuall on get a list of the possible keys in panel-heading-s and when they click on the heading is when they actually get to see the data. Before I added this part the page loaded very fast, now it takes considerable time (few seconds, and it is not because of fetching the data, as the whole dataset was fetched previously also, I just didn't show it all). As far as I can tell, angular basically renders everything even though its not shown (although I guess it might not store it, because every time I click one of the heading to show the data, it still takes a second or two for it to appear).
<div class="panel panel-default">
<div class="panel-heading"><h2>Raw data</h2></div>
<span ng-repeat="(key,val) in data.data">
<div class="panel-heading" ng-click="showraw[key] = ! showraw[key]"><b>{{key}}</b></div>
<table class="table table-striped table-hover table-responsive" ng-show="showraw[key]">
<tbody>
<tr ng-repeat="line in val track by $index" ><td ng-repeat="l in line.split(' ') track by $index">{{l}} </td></tr>
</tbody>
</table>
</span>
</div>
My question is the following: what would be the best practice in speeding up page loads? I do not wish to make the user wait for rendering of data that is not shown to her.

Related

When does duplicate digest computations warrant redesign in AngularJS?

I have been working with AngularJS for a while now and this is one subject I still am not sure about. Let me start with an example. In my site I have a table with data. I want to be able to search/sort/filter this data in a number of ways. We have a search box that utilizes the built in "filter" filter to search the data. We also have a number of other filters that allows the user to check checkboxes and get different views (think Amazon).
The issue is because things like pagination need to know about these filters and must apply its computations based off the filtered view of data, not the original data set.
Doing so makes our HTML look like this:
<div class="row paginationInfo clearfix">
<div class="col-xs-3 showResultsWrap">
<span data-name="summary"><b>{{ getPageStart2((model.IndividualMailboxes.filtered | pipe:model.IndividualMailboxes.filters.functions:model.IndividualMailboxes.filters.values), model.IndividualMailboxes.currentPage, model.IndividualMailboxes.resultsPerPage) }} - {{ getPageEnd2((model.IndividualMailboxes.filtered | pipe:model.IndividualMailboxes.filters.functions:model.IndividualMailboxes.filters.values), model.IndividualMailboxes.currentPage, model.IndividualMailboxes.resultsPerPage) }}</b> of <b>{{ (model.IndividualMailboxes.filtered | pipe:model.IndividualMailboxes.filters.functions:model.IndividualMailboxes.filters.values).length }}</b></span>
</div>
<div class="col-xs-6 text-xs-center">
<div max-size="5" boundary-links="true" first-text="«" last-text="»" previous-text="‹" next-text="›" uib-pagination ng-show="(model.IndividualMailboxes.filtered | pipe:model.IndividualMailboxes.filters.functions:model.IndividualMailboxes.filters.values).length > 10" total-items="(model.IndividualMailboxes.filtered | pipe:model.IndividualMailboxes.filters.functions:model.IndividualMailboxes.filters.values).length" ng-model="model.IndividualMailboxes.currentPage" items-per-page="model.IndividualMailboxes.resultsPerPage" class="pagination-md"></div>
</div>
<div class="col-xs-3 resultsPerPageWrap form-inline text-xs-right">
<span>View</span>
<select sk-id-gen="resultsPerPage" name="ResultsPerPage" class="form-control m-l-1" ng-model="model.IndividualMailboxes.resultsPerPage" ng-options="val as val for val in [10, 20, 50, 100]">
</select>
</div>
</div>
The important thing to notice here is how many times we have to do (hereIsMyArray | pipe:param1:param2).length over and over again for the pagination to work.
So correct me if I am wrong, but I believe every digest cycle we are running these pipes/filters 5+ times. This is probably OK with a small dataSet, but if I start having to filter 10,000 items then I'm sure I will see performance issues.
It would be much more efficient if we only had to do the pipe/filtering 1 time and each of these HTML components could just use that single instance of the filtered data set.
The issue with not doing it directly in the HTML is you no longer have automatic watches setup to see when data changes and updates the view.
If any of my statements are wrong please let me know. I am curious if anyone has had this issue before and has a solution?
Thanks

Change display text based upon value

I am displaying Errors on my Html page using Angular JS. The problem is I am receiving only error codes from the HTML . What are the various ways in which i can change the error code to the the Error text i like
<table>
<tr ng-repeat='item in errorsd'>
<td align="left" class="validationMsg"> {{item.message}}</td></tr>
</table>
If my item.message has one . I would like to display Beginner ,if its 2 Intermediate like that and so on . Should i use ng-if ? should i use ng-switch or should i input some logic on the controller side .
Should i use ng-if ?
ng-switch is more readable and hence a better option. Later when you look back at the code it will be intuitive to you and other developers about what this code does.
should i input some logic on the controller side .
Why put a logic in controller-side if the framework already provides a solution for such use-case?
I would do it like:
<table>
<tr ng-repeat='item in errorsd'>
<td ng-switch="item.message" align="left" class="validationMsg">
<span ng-switch-when="1">Beginner</span>
<span ng-switch-when="2">Intermediate</span>
<!-- and so on.. -->
</td>
</tr>
</table>
I say use a switch statement inside of your controller.
So depending on the value, the global message would change thus displaying the correct one when triggering the validation msg box to show.

Angular vs-repeat performance issue with tables with 7k rows

I am using angular vs-repeat to render around 7k rows in a table. If I use vs-repeat for table body, the rendering was very slow.
<table class="table">
<tbody vs-repeat style="width: 100%;">
<tr ng-repeat="row in list track by $index">
<td>{{::row[listColumns[0].colName]}}</td>
<td>{{::row[listColumns[1].colName]}}</td>
<td>{{::row[listColumns[2].colName]}}</td>
<td>{{::row[listColumns[3].colName]}}</td>
<td>{{::row[listColumns[4].colName]}}</td>
</tr>
</tbody>
If I use vs-repeat without tables, in my case I used divs. Its rendering very fast
<div vs-repeat class="table-body">
<div class="row" ng-repeat="row in list track by $index">
<div class="col-md-4">{{::row[listColumns[0].colName]}}</div>
<div class="col-md-2">{{::row[listColumns[1].colName]}}</div>
<div class="col-md-2">{{::row[listColumns[2].colName]}}</div>
<div class="col-md-2">{{::row[listColumns[3].colName]}}</div>
<div class="col-md-2">{{::row[listColumns[4].colName]}}</div>
</div>
</div>
Please suggest how to improve performance for table?
With vast collections of items that render many DOM elements, even the most negligible processing of items inside an ng-repeat can choke your app.
DOM-related solutions that check if elements are in view don't tell you if nested components have been loaded and rendered completely, leading to errors.
My solution to this problem is angular's limitTo : limit: begin filter, along with iScroll or native scrollTop and scrollBottom callbacks, which raise or reduce the begin index in the controller according to the browse direction - sort of frontend pagination where only a specific number of items are shown at the DOM.
<tr ng-repeat="item in items | limitTo : 100 : 600 track by $index">
<span>{{ item.property }}</span>
</tr>
Then you can find the optimal limitTo number that work out best for the app - while keeping it light, quick, and agile as Angular should be.
use ng-repeat on small set of an array. Do pagination or lazy loading. store data to temporary array which you want to display rather having n-repeat on 7k records.
Thoughts?
Thanks!

Bootstrap - How to line up two tbody's properly?

I'm having an issue where lining up a table isn't working properly and I was wondering if anyones dealt with something like this before. I looked it up, but couldn't find anything addressing it. I'm using AngularJS and nested ng-repeats which is why I'm having some trouble with this (and need to nest them inside a table). My code is below:
<table class="table table-condensed table-hover table-responsive">
<thead><tr>
<th class="col-sm-4">1</th>
<th class="col-sm-3">2</th>
<th class="col-sm-3">3</th>
</tr></thead>
<tbody ng-repeat="blah in blah">
<tr ng-repeat="blah2 in blah">
<td>......</td>
</tr>
</tbody>
<!--This is the end of "Table 1" in the diagram below-->
<tbody ng-repeat="blah3 in blah4">
<tr ng-repeat="blah5 in blah6">
<td>.........</td>
</tr>
</tbody>
<!--This is the end of "Table 2" in the diagram below-->
</table>
I'm ending up with a result like this (note, I had to draw it due to the fact that the table data I'm using is sensitive information):
How can I pull the second tbody (the smaller one) next to the first?
Thanks
If I understood you correctly, you can simply use Bootstrap's columns as containers for your tables. For instance:
div.col-md-6
Will render two columns together until the screen collapse.
https://jsfiddle.net/DTcHh/11692/
Why not use the grid system of bootstrap ?
<div class="row">
<div class="col-md-4">.col-md-4</div>
<div class="col-md-4">.col-md-4</div>
<div class="col-md-4">.col-md-4</div>
</div>
I don't know what you want to put in the table but you can probably put it into the grid system. link to doc

How to architecture backbonejs application - click event on each table row backbonejs

I am developing a application in which one of my template renders a table with n number of rows. Now in each row, i have a column with buttons like edit and delete.
When clicked on edit, a edit form appears in the same window in some div. That form needs to be populated with values fetched from backend.
Now nothing great in this.
My problem is this:
I have a view which renders the complete table using the following template structure:
<script type="text/template" id="ledgersing">
<div class="span6 widget">
<div class="widget-header">
<span class="title">Ledgers</span>
<button class="btn btn-danger pull-right" id="addLedgerButton">Add Ledger</button>
</div>
<div class="widget-content">
<table width="100%" class="table table-striped dataTable">
<thead>
<tr><th>Name</th><th>Email</th><th>Phone</th><th>Action</th></tr>
</thead>
<tbody>
<% _.each(ledgers,function(data){ %>
<tr>
<td><%= data.name %></td>
<td><%= data.email %></td>
<td><%= data.contact_number %></td>
<td><span onClick="alert(<%= data.id %>)">x</span></td>
</tr>
<% }) %>
</tbody>
</table>
</div>
</div>
</div >
</script>
In this it just alerts a id when clicked on x. Now do i need to necessarily use onClick event like this? I mean that i will need the id in whatever construct i use for processing. What can be a better solution? I know backbonejs can handle this mess with ease if application is structured properly.
So essentially i want to know from experts, what will they do in such a scenario. How will they structure the application? I am novice to this frontend framework.
Instead of using _.each in your templates, I'd go with one view per table row as each one has some bit of complexity (edit, delete)
In these view, you use the events hash to register your DOM events. Never use onclick in your HTML, this is a really bad practice.
Don't hesitate to look at the TodoMVC Backbone example for ideas on how to organize your app.
I'm also developing a backbone application for the first time and went thru exactly the same mistake.
I first I just tried to translate my php / asp / ruby / whatever_server_side_template_technology into underscore templates, and got something pretty much like what you had.
Now I can realize it's a mistake. You should use subviews. The events and the associated model will be connected to that subview. Pretty soon you'll have lots of view listening to events and updating themselves when data changes, but if you're carefull it will be ok.
Here's a demo app I'm working on: https://bb-jugar.rhcloud.com/index.html#Wine
and here's the github repo: https://github.com/opensas/BackboneBootstrap
This is how I solved it: https://github.com/opensas/BackboneBootstrap/blob/master/demoapp/js/src/views/crud/RowsView.js

Resources