I have a ng-repeat that generates around 300 rows. I can't implement infinite scrolling since i need all the rows present on the page. For each row there are 3 elements.
When the page loads, i get all the rows from the database and if the element exists i display it, if not i have the option to add it by clicking on the place where the element would otherwise be. When clicked a form is displayed right under that element.
The form has 4 inputs, which is quite a lot of html. Now since we have two-way data binding, and we are inside the ng-repeat isolated scope, i can't use one form for all 3 elements (since the values in the inputs would be shared), i would need one for each. Considering the amount of rows, rendering so many forms takes more than i'd like.
To get a better idea of what i'm working with (visually, the code is not relevant anymore) http://plnkr.co/edit/xNYUbi?p=preview
I want to stick to the form dropdown under the add element option, so making a modal isn't an option.
How should i approach this problem?
I'm not certain I understand the specific use case here so I will give some generic advice that I hope helps. When working with lots of data angular, there are a number of options:
ng-grid: Has an edit mode and paging so with the correct settings you can pull down all your data, set the data source for the grid and the performance should still be pretty good.
ng-repeat: If you have to have a custom U/I or you need additional functions in your U/I, ng-repeat is about as good as it gets. As long as you don't have nested repeats (can be bad) and you craft your UI carefully you should mostly be all right.
Assuming that ng-repeat is still too slow you could think about implementing some form of paging or ng-infinite-scroll. With either option you can still load the entire data set initially and then display it in chunks rather than all at once.
At the end of the day - if the performance is unacceptable when you try to add all the elements to the DOM the only real solution is to alter the way those elements are added or simply don't add them at all (which is where all the above solutions really lead you). This might require talking to your client or going through a bit of re-design, but in the end it should be worth it. Best of luck!
Related
How could I interpolate a one-time binding manually?
Here is my use case.
I have a list of a lot of elements. The elements just sets of controls. I get the data for the elements from the BE. Then I would like to leverage the AngularJS interpolation and set the controls` values. But I would like to avoid the interpolation of all the elements every time I change only a single control.
So, I use a one-time binding to set the values, but then when I change them they are not updated.
The expected result in the example is that once something is typed in the control, the respective one-time binded value is updated. Also, the one-time binding should remain there, since in my real case there will be a lot of controls and I do not want to strain performance when only one control is interacted with. A simplified example of mine can be found here (in my real case I have not only inputs, but checkboxes as well, but I believe that the approach should be the same for them).
After a research I found out that a directive should be used in this case. But I was not able to find a simple to understand example. So, could someone post it here, please?
Different from a directive solutions are welcome here as well.
First to understand your problem: Why do you want to avoid the angular change detection here? The only reason that comes to my mind would be heavy performance problems.
In one case here, there were one or two thousand of inputs, all with a binding. The application was a little sluggish, but still usable. We accepted this, as we had to re-implement all the binding manually otherwise.
If your binding is rather simple (no validations, conversions, etc.) and the values are not shown on other places while being edited, maybe it would be a way for you to use an AngularJS directive on a native HTML Input element that just listens to its onChange event to save changed data and gets updated programmatically whenever you know it changed from outside (if it does at all).
(Not talking about better using Angular, which has a much tighter grip on change detection ;-) ).
I have a large app with a structure and UI that has been designed to meet the original requirements.
I am now faced with a situation where I have to make an alternative read-only "view" of certain parts of the app for embedding in an iframe (I have no say in this, this is how it has to be).
I'll be referring to these two ways of viewing the app at the "display context".
I am struggling with visualising how to achive this, I can see two solutions both of which have distinct disadvantages:
Have lots of ng-if directives attached to template elements, the ng-if would be bound to the current display context of the app and show/hide elements depending on how it was being used. Even if these were one-time bindings, it would potentially turn the templates into an unreadable mess of nested ng-ifs everywhere
Create entirely separate templates for the two different display contexts. While much cleaner than the first option, it would mean a lot of duplication and maintaining two templates per view whereas previously it would be one.
I should add that the nature of the views is very ng-repeat heavy, a list of data containing categories, each category contains items, each item contains a multitude of data, at each level data may need to be hidden/displayed/manipulated for display depending on the display context. I have made heavy use of directives and components to break things up into logical chunks, however these directives and components are still very much geared towards the original use, rather than the newly required one.
I have also considered creating an entirely new app for this, however I'm not sure this would bring any benefits as I'd be using controllers and injecting services containing tons of stuff that would be never used, I'd also be increasing my duplication problem.
Does anyone have any feeling, suggestions on a good way forward for this as at the moment I'm feeling anything is going to be horrible.
Many thanks
I am about to build a new single page web application where I think the main view will be quite complex and I am tring to decide whether to use Angular.js. My concern is whether there will be too much data-binding causing the performance of the UI to become sluggish.
The app will have a view consisting of 2 panels. One will have 8 tabs each containing a table with 3 cols, 40 rows and one col in each row having a list of numbers (upto 4 numbers) where each number is clickable (clicking a number causes something to happen in the other pane). I was considering using the ng-repeat directive to dynamically create the tabs and tables and list of numbers from data provided from the backend as the content will be different for different users. So I think that would mean 8 * (2 + 4) * 40 (1920) items having watches added to the $watch list. I think this means that a lot of things will be checked each time round the $digest loop even although these items will never change once they have been created the first time.
The 2nd pane will have other tabs and items although not so many as in the first pane so over all there will be over 2000 items involved with data-binding if I use AngularJS and ng-repeat.
Is this too many items for one view when using AngularJS i.e. will the UI performance become sluggish with this number of items?
Are there any alternative ways of dynamically creating tabs and tables using AngularJS that don't use ng-repeat in order to keep the number of data-binding items down?
Some optimizations that i can suggest of would be
Look at bindonce directive. This does not create a watch once data is bounded. This should fix most of your issues.
Use directives like ng-if these destroy\create the DOM based on conditions. If a tab is not in focus what is the point having data bounded to it. Do binding just in time. And maybe destroy the page DOM once the focus on tab is lost (with ng-if) only.
Also test you app with dummy data, to verify how the real performance is and whether it makes sense to try the second option i have mentioned.
Here on StackOverflow is a great answer of Misko, talking about performance.
TL;DR: 2000 elements should be fine!
I got a pretty big form on a wpf page. I'm putting it together on a Grid, but all the element clutter the page. I figured i'd split out the form into smaller usercontrols and then piece it together on the page as one form. That didn't quite work: SharedSizeScope on a Grid makes the form 'dance'
I could break up the form into a 'wizard style' page, with a next button - dealing with each user control on its own, but i'd rather not break it up into several pages because the end user is used to having it all on one page. Also the validation/storing of data is really a big-bang operation, making it harder to provide feedback if something goes wrong in one of the first pages/usercontrols.
So what now? I'm really tempted to just put all the small elements directly on the page in one big grid. I just feel it's wrong - it will be a maintenance nightmare - i even started thinking 'i wish there were some kind of #region tag in xaml' - that means i know i'm wrong ;)
What can i do?
I would strongly recommend to use nested container controls, like Grids (or other Panels) inside other Grids inside more Grids etc.
It is very common to have several nesting levels, and thus hierarchically split a complex layout into multiple less complex sub-layouts. This makes your layout significantly simpler compared to one big container that tries to do it all (see your failed ShardSizeScope approach).
Once you have created a sensible hierarchy of containers, you may easily use the Visual Studio XAML editor's code collapsing feature to keep track of all your XAML.
My aim is to make a editor behave similar to MS-Word.Wpf RichTextBox is a wonderful control for it.By placing it inside a ScrollViewer,we can make it editable.(Like a notepad).But I need MS-Word like pages.One effective way probably is to apply style to scrollViewer such that we create a look and feel of multiple pages on richtextbox but I dont know how to do it.What we are doing in the project is to use a documentViewer. Inside a FixedPage,create a Header(Canvas),Body(WpfRichTextBox),Footer(Canvas). And thus create multiple pages,and by subscribing to RichTextBox sizechanged event, we are manually doing the pagination i.e move the blocks from one page to another when height has changed. Do you see any better approach in doing this? Does using multiple richtextboxes hamper my performance?
#WpfProgrammer This is the good approach I would say. Say if you have 1000s of pages then, there will definitely be a performance problem. For avoiding that problem, you need to do demand paging.
Virtual Paging :
1. You need to construct a page table, which will contains pages. Each page will contains information about the controls, images, their positions, dimension and Styles for the page. [All serializable data]
2. Virtual Pages - You need to
de-serialize all the data for the
page and create a page with
RichTextBox. Virtual Pages are
nothing but, pre-cached pages that
are going to be rendered. Say for
example. If I'm in 1st page. Then,
I'll de-seriealize next 3
consecutive pages and have them in a
collection. Then, repeat this
procedure for consecutive page
movements. Adding some logic using
Most Frequently Used collection. It
will be fast enough. In the case of
1000's of pages. You can collapse
those non-dirty or never visited
pages. That could yield little more
performance. If performance is far
more concern for low hardwares.
Then, you should consider
cleaning.
3. Cleaning -
Cleaning is the process of
identifying LFU pages and remove
them. This would be very helpful if
performance is more pronounced.
Hi Tameem
Set the min height,width of the richTextBox to A4 size(lets say). Subscribe to RichTextBox Size Changed event.As soon as the content exceeds,this event gets fired.Then I take the last block of previous page and push it to the first block of next page.(Remember if page doesnot exist, you need to create new page then add it as first block).And also the focus should be changed to the new page.(because if you press enter at the last RTB, you expect the focus to be there in the new page.).When the user deletes a block in some page(say 2nd),then you need to add all the blocks of bottom pages to this page,so that our pagination logic will push the blocks down again and adjust. I can share some piece of code if you need further help.