SAPUI5 StandardListItem sort by selected - javascript

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>

Related

AG Grid expand rows on init

i am working on an app that that is using aggrid.
data is received from server, stored into state, and fed to the aggrid [rowData]="rowData"
separate task receives the settings of my data, like: column widths, row expanded, row selected...
i can apply column widths on initial data, and later listen for events when column is resized and save that back,
but for the expanded, no such thing.
i have onFirstDataRendered and there i iterate and set the expanded node, but i want to this before, in init like, because this fires the onRowGroupOpened(event: RowGroupOpenedEvent) every time node is expanded, and i cant distinguish programmatically expand from user click.
can anyone suggest solution for expanding the rows in initial data prep? or distinguish expand event programmatically vs user click?
is there any other way to expand node except node.setExpanded ?
You can use groupDefaultExpanded property to set the default group expansion settings at the start:
0: Don't expand
1: Expand all first level groups
2: Expand up to second level groups
-1: Expand all groups by default (what you need)
Live Demo
Are you using ag-Grid on its own or with AdapTable?
If the latter then that has the ability to set which rows should be expanded when app launches - and will also automatically save any expanded rows for next reload.
I think its AdapTable rather than ag-Grid which is doing this but I'm not 100% sure.
See demo at https://demo.adaptabletools.com/layout/aggridgroupedlayoutdemo

Table in AngularJS app with many "select" elements built with ng-repeat takes very long

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).

Highlight last inserted document in Meteor

I have form and list of objects at the same page. When I insert a new row, it is not very easy to see where the newly inserted row is placed. Therefore, I thought I could color/highlight the newly inserted row (and perhaps remove the highlight after a few seconds).
How can I do this? I think a way to do this could be using a method on the server which returns the inserted id (return Collection.insert(doc);) and on the client use a callback with
Meteor.call('insertDoc', function(err,result) {
// do something with result
});
I think I can use a reactive-var to save the id of the last inserted row and in the loop highlight the row with
{{#each docs}}
<li class="{{isActive}}">{{name}}</li>
{{/each}}
and have a helper to return active if this._id equals the reactive var with the last inserted id.
But is this the best way to do it? How can I remove the color after some seconds? I have seen such behaviour on many pages but I cannot find any tutorials/code snippets to achieve this.
I wrote a package that uses Meteor's UI hooks to fade items in and out of a list as they are added and removed, to help users maintain context as data changes:
https://github.com/mizzao/meteor-animated-each
There is a demo at http://animated-each.meteor.com/. You can see that as items are added and removed, they are faded in and out. If items are inserted off the screen, the visible area does not scroll.
This isn't doing exactly what you want, but you can use the same idea to highlight items as they appear as well, as opposed to the simple fade in.
Note that all of this happens at the UI rendering level - not the template/code level. The UI hooks are also not well documented right now, but they've been around for a while.
I don't know if your method is the best, but that's how I'd go about doing it.
As for the animation, I'd use a CSS3 animation. Plenty to choose from ( https://developer.mozilla.org/en-US/docs/Web/CSS/animation ), and you can easily make them fade to the standard color. The animation would also only be applied to the last inserted item (because of the way you did it, only the last item would have the "active" class)

AngularJS : how to sort in acsending / decending order

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.

Is there any CallBack function which is called before/after data is loaded in Angular Js ng-Grid?

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.

Categories

Resources