I am implementing the table view .In table view I am implementing infinite scroll .In other word I have 2000 objects .I am showing 25 element at one time .When user scroll to bottom it load more 25 elements so on .. I have "V" or "^" button on header .On click of this image I want to display in descending order only last 25 elements .when scroll more it load more data so on ..So I added filter in that but it is not working ..could you please tell me how we can implement this ..
I will give you example :Like A, B,D,C,K,N....T,Z objects when application load object is load like that .when user click it show Z,y,X ,W,V,U...A or again ascending way "A,B,C...Z"
here is plunker
$scope.setSort = function(idx, reverse){
$scope.sortval = 'columns['+idx+'].value';
$scope.reverse = reverse;
};
Html
<div class="col col-center brd gray-20" ng-repeat="d in invoice_column_name | filter:{checked: true}">
<sort-header label="{{d.label}}" index="{{d.index}}" sort-exp="setSort(idx, reverse)"></sort-header>
EDIT
Update
I will explain again I have 2000 objects ..It is display randomly .I am display only 25 object at one time .When user scroll more data it show again 25 data..But I want to sort that data in ascending as well as descending way .First I need to sort the 2000 objects then display 25 elements from that and than if user want to load more it scroll data and load that.In your example it is sorting first 25 object only .then load another 25 elements then sort 5o elements ..so on ..so it is not correct solution –
Update plunker
If you are dealing with a large collection of data, then it might be better to load the whole collection first. I have a couple of reasons for this:
Sorting the results on each load operation can be taxing for older browsers, especially as more data is brought in. This will slow down your UI.
If the data is not provided in order by the source, then the process of sorting might scatter the last-loaded set of items over several "pages" of the view before the one that your user is looking at. They will then have to search backwards through the results for the new information.
Try with with this library https://github.com/sroze/ngInfiniteScroll
First you need to load data from server or whatever you like, than in your controller you have to implement one function that gets called when user scrolls down. Also you can order your data in your controller
$filter('orderBy')(data, orderProp, desc/asc)
see angularjs filter order by. When user clicks on letter you have to order your data and search for first element in the array that starts with that letter. All you have to do next is to implement this in the ngInfinitScroll directive callback function.
Related
I have SelectDialog for one of the popovers. Inside that, I am displaying data using StandardListItem.
The list shows more than 2000 records. However, it takes lots of time to load data, so I set the threshold of 50. When user opens popover, it will show the first 50 records, once he scrolls down, next set of 50 records and so on.
Now, the issue is when user search for a record (e.g. "ABC"), this ABC can be at position 500 in the list. He selects ABC, closes popover, and then reopens it, he cannot see ABC (because ABC is not in first 50 records). He needs to scroll down 6 times to see the data.
What I want to achieve, is once the user selects records, it automatically goes to the top position. UI5 SelectDialog (UI5 Demo Kit) does not provide this functionality since it only supports one-way binding. Any help on this?
My fragement.XML code:
<SelectDialog
id="idSel"
growingThreshold="50"
growing="true"
showClearButton="true"
items="{data>AllItems}"
multiSelect="true"
noDataText="Not Found"
liveChange="handleSearch"
title="Choose"
autoAdjustWidth="true"
growingScrollToLoad="true">
<StandardListItem id="idItem" description="{data>AllDataId})"
title="{data>Title}" type="Active"/>
</SelectDialog>
rememberSelections would keep the options ticked/unticked but "ABC" would still be in position 500. I don't think the standard sap.m.SelectDialog control has a way of doing this.
I see a few options though:
If the selection is queried from somewhere (OData?) you could enrich the options read with whether they are selected or not for this purpose. Then add a sorter to the list that sorts by selected first (https://sapui5.hana.ondemand.com/#/api/sap.ui.model.Sorter). You might also be able to do that in the UI when reading the list data at once, but you've already said you're doing that in batches for performance reasons.
If manipulating the backend won't work, you could build a custom control that is basically a sap.m.Dialog with 2 sap.m.Lists on top of each other to replicate what you are describing. The top displaying selected items then the bottom, the standard list.
If we look at how other UIs manage multi-select, it is actually 2 lists side-by-side. Selecting/deselecting is simply moving the item from one side to the other (buttons in between or drag and drop). That way you always keep the context of the selected while looking for another to select. I've implemented this recently myself for choosing multiple options from a long list.
Alternatively, don't bother with multi-select on the dialog but simply keep the selected state in a sap.m.MultiInput as sap.m.Tokens. This is probably least work of all.
You can try to set rememberSelections = true, to store the current selection and load this state when the dialog is opened again.
<SelectDialog
id="idSel"
rememberSelections="true"
growingThreshold="50"
growing="true"
showClearButton="true"
items="{data>AllItems}"
multiSelect="true"
noDataText="Not Found"
liveChange="handleSearch"
title="Choose"
autoAdjustWidth="true"
growingScrollToLoad="true">
<StandardListItem id="idItem" description="{data>AllDataId})"
title="{data>Title}" type="Active"/>
</SelectDialog>
I have a table with variable number of records (could be up to hundreds) where its body is build with one ng-repeat.
Within each record, there are two input fields of type select where their contents is also built using ng-repear and the number of options for each is about 100.
This is working right now, except that it takes a lot of time for the page to be built (several seconds; I guess due to the large number of html records that AngularJS is adding to the DOM).
Here is an example of one of the selects:
<select class="form-control" ng-model="One_Source.Measuring_Method_Code">
<option ng-selected="{{One_Method.Value == One_Source.Measuring_Method_Code}}"
ng-repeat="One_Method in All_Collections.Parameters_Test_Methods"
value="{{One_Method.Value}}"
title="{{One_Method.Test_Method_Name}} | {{One_Method.Method_Internal_Name}}">
{{One_Method.Value}}
</option>
</select>
Two questions:
Is there a simple way to speed up the page building process?
As shown in the example, each option in the list has a title clause displaying a detailed description of the option's meaning. How can I add a title to the select showing the description of the current value?
For the first question I was thinking about building the list of options for each select element only upon clicking on it, but I'm not sure if that would be the best way to do it.
Try using one time bindings so that Angular doesn't watch the value by prefixing it with ::. It can also be more efficient to use track by in your ng-repeat if each row has a unique value, like an ID.
<option
ng-selected="{{One_Method.Value == One_Source.Measuring_Method_Code}}"
ng-repeat="One_Method in All_Collections.Parameters_Test_Methods track by One_Method.id"
value="{{::One_Method.Value}}"
title="{{::One_Method.Test_Method_Name}} | {{::One_Method.Method_Internal_Name}}"
>
{{::One_Method.Value}}
</option>
If you still can't gain the performance you're expecting from #doublesharps's answer, you will have to implement one of the following:
You could build a custom list that has a 'load more' button which would destroy say the first '50' options and load the next 50.
A better option would be to turn this into an autocomplete, where the user searches for values.
Virtual repeat - Something angular material does really well, it constantly draw's and re-draws new elements based on the scroll position inside the element.
Other resources:
http://blog.scalyr.com/2013/10/angularjs-1200ms-to-35ms/
https://github.com/stackfull/angular-virtual-scroll
http://klajd.github.io/angular-virtual-repeat/#/Home
I found a PARTIAL SOLUTION that still needs to be polished but is quite promising.
During creation of the page, I do not make use of ng-repeat for the options but instead deploy a single option with the value received for the field from the database (if any, otherwise the select element is left blank).
When the user clicks on the select element a $scope function is invoked that checks the number of options within the select element and, if less or equal to 1, the inner HTML of this select element is re-generated and deployed.
Though clicking on all these select in the page will take (accumulative) a comparable time as when built upon load, this time is distributed over several events (the user clicking on all the select elements) and hence it is not perceived by the user.
Now, by polishing I mean that there is a strange behavior. In order to see the generated list of options, I need to click on the select twice. Will keep investigating this and post the solution (hoping I find one).
I have a page with a long list of search result set.
When clicking a result you are directed to a different page that show this specific item details.
What I want is when the user goes back on his browser, the window is located at the link he clicked. (Which might be lower because its a long page that loads more feed when you scroll down, like the Facebook news feed).
Any suggestions with PHP/JavaScript or other language?
Thanks.
This would be quite hard to achieve, since it goes against the whole idea of infinite-scrolling.
You could refer to that item's ID and then preload the set it's in, while ignoring the previous result sets. Like so:
Let's imagine your list of results consists of a total of 100 items. And you want only 10 new items to load each time the bottom of the page is reached. That would leave you with 10 sets (with 10 items each). Quite similar to normal pagination, actually.
Now, if your itemID is 32 and you want to navigate right back to it, you can actually preload the list to show the 3rd result set by default (and you could even add option to scroll up or down to show the first two or the next result sets).
# result set 1: hidden
# result set 2: hidden
# result set 3:
item 30
item 31
item 32
item 33
...
item 39
#result set 4: hidden
If you want both resultSet1 and resultSet2 to be visible as well, you'll have to apply some sort of a JavaScript window height calculation in order to place the 3rd set in the center of the screen.
But, like I said - this is probably too much work and it takes away from the UX. Either use normal pagination or leave the infinite-scrolling as is.
I'm building a directive (Angular 1.2) that will toggle between displaying two different lists - think of them as a list of "trending" items on the site and a list of items the user is "following". So we have a toggle that allows the user to choose which list is being displayed, with an ng-repeat below it showing the items.
There will be a good deal of overlap between these lists, and when the user toggles from one list to the other, I'd like items that are contained in both to transition from their places on the "outgoing" list to their places on the new one, rather than disappearing and reappearing.
My question isn't about how to achieve the actual animations (we're using ngAnimate), but about how I should structure the controller/data to. I'm thinking about my directive controller having a trendingList and a followingList (that contain the actual data items), and an activeList that points to whichever of the two are currently being displayed. So the ng-repeat is actually on activeList, and toggling is essentially:
$scope.toggleMode = function(){
if ($scope.mode == 'trending')
$scope.mode = following;
$scope.activeList = followingList;
else {/*the inverse...*/}
}
Is that the most reasonable approach? If so, how do I ensure that angular recognizes the equality of objects present in both lists?
Or is there an easier/cleaner way to do this?
From what I understand, angular isn't tracking the equality of objects in the list it is repeating. The animations are triggered when the DOM is manipulated, not when the data changes (though data changes will change the DOM). As to what you should do, I don't have experience with this problem so hopefully somebody can point you in the right direction!
Presently i have a Angular Js Grid which is pagination Enabled say 5 records per page for example and total number of records is 2000, so there are going to be 400 pages in All.
when pagination in ng-grid is handled the gridOption data is specified per page which means for 1st page the gridOption will be 1-5 rows for 2nd 6-10 rows and so on........
Here i have implemented a selection functionality through checkboxes thus whenever a row is selected[checkBox becomes selected] and it's stored in selectedItems array and i show selected items in another grid like this.....
Now when i move on to second page[pagination] and select further rows like this ...
The real trouble lies here when i again go back to the previous page i.e page 1 the checkboxes will not be checked because in pagination we load data runtime thus the pages shows following result...
Hope you must have understood my problem....
what i need here is a callback before/after data is loaded so that i can select the checkboxes as i have the number of selection preserved
OR any other workaround for my problem will be much helpful too.
Thanks!.
Can you store the checked value on the data model where you are storing the row values? Then you come back and its just checked by Angular bindings?
I am not sure of your setup, but I do this in a similar situation.
I have been working on this for a couple days now.
While I am still unable to preserve selection across pagination, I am able to clear selections while simultaneously "deselecting" the select all checkbox.
The allSelected variable is not exposed in the gridScope but you are able to grab it and address it using the following code.
// Use this to deselect all options.
$scope.gridOptions.$gridScope.toggleSelectAll(null, false);
// use this to find the allSelected variable which is tied to the
// (the ng-model related to the select all checkbox in the header row)
var header = angular.element(".ngSelectionHeader").scope();
// use this to turn off the checkbox.
header.allSelected = false;
I'll follow up again if I manage to get the "reselecting" to work as documented, but for now I might remain content with this.