smarttable get all rows - sapui5

I have a SmartTable control (with tableType="Table") in a custom app (sapui5 version 1.71).
The xml view (Main) has a filter, which when executed correctly brings the data via custom odata service and shows in the table. This part works as expected. Table threshold is set to 10k.
We are not selecting any rows on the Main view's smarttable (underlying Table has selectionMode="None").
The requirement is to have a 'summarise' button on the Main view that when pressed will show a Summary view (route navigation) with summarised information based on some columns (not keys).
How to get all the data from the Main's view smarttable?
getRows() method of the underlying table returns only visible rows.
I don't want to switch to use ui.table.Table as there are some nice features you get for free for a SmartTable.
Many thanks,
Wojciech

I had exactly same requirement. It's strange that UI5 makes it so hard to achieve something which is very basic. The code below is from my project but it gives the basic gist:
var allItems = oSmartTable.getTable().getItems();
var highestSortOrder = 1;
for (var i=0; i<allItems.length; i++) {
var anItem = allItems[i];
var sPath = anItem.getBindingContext().sPath;
var currentObject = oSmartTable.getModel().getObject(sPath);
var currentSortOrder = currentObject.SORTORDER;
if (null !== currentSortOrder) {
if (currentSortOrder > highestSortOrder) {
highestSortOrder = currentSortOrder;
}
}
}

Related

ag-grid programmatically selecting row does not highlight

Using Angular 4 (typescript), I have some code like below using ag-grid 12.0.2. All I'm trying to do is load my grid and automatically (programmatically) select the first row.
:
this.gridOptions = ....
suppressCellSelection = true;
rowSelection = 'single'
:
loadRowData() {
this.rowData = [];
// build the row data array...
this.gridOptions.api.setRowData(this.rowData);
let node = this.gridOptions.api.getRowNode(...);
// console logging here shows node holds the intended row
node.setSelected(true);
// console logging here shows node.selected == true
// None of these succeeded in highlighting the first row
this.gridOptions.api.redrawRows({ rowNodes: [node] });
this.gridOptions.api.redrawRows();
this.gridOptions.api.refreshCells({ rowNodes: [node], force: true });
First node is selected but the row refuses to highlight in the grid. Otherwise, row selection by mouse works just fine. This code pattern is identical to the sample code here: https://www.ag-grid.com/javascript-grid-refresh/#gsc.tab=0 but it does not work.
Sorry I am not allowed to post the actual code.
The onGridReady means the grid is ready but the data is not.
Use the onFirstDataRendered method:
<ag-grid-angular (firstDataRendered)="onFirstDataRendered($event)">
</ag-grid-angular>
onFirstDataRendered(params) {
this.gridApi.getDisplayedRowAtIndex(0).setSelected(true);
}
This will automatically select the top row in the grid.
I had a similar issue, and came to the conclusion that onGridReady() was called before the rows were loaded. Just because the grid is ready doesn't mean your rows are ready.(I'm using ag-grid community version 19) The solution is to setup your api event handlers after your data has loaded. For demonstration purposes, I'll use a simple setTimeout(), to ensure some duration of time has passed before I interact with the grid. In real life you'll want to use some callback that gets fired when your data is loaded.
My requirement was that the handler resizes the grid on window resize (not relevant to you), and that clicking or navigating to a cell highlights the entire row (relevant to you), and I also noticed that the row associated with the selected cell was not being highlighted.
setUpGridHandlers({api}){
setTimeout(()=>{
api.sizeColumnsToFit();
window.addEventListener("resize", function() {
setTimeout(function() {
api.sizeColumnsToFit();
});
});
api.addEventListener('cellFocused',({rowIndex})=>api.getDisplayedRowAtIndex(rowIndex).setSelected(true));
},5000);
}
Since you want to select the first row on page load, you can do onething in constructor. But your gridApi, should be initialized in OnGridReady($event) method
this.gridApi.forEachNode((node) => {
if (node.rowIndex === 0) {
node.setSelected(true);
}
It's setSelected(true) that does this.
We were using MasterDetail feature, its a nested grid and on expanding a row we needed to change the selection to expanded one.
Expanding a row was handled in
detailCellRendererParams: {
getDetailRowData: loadNestedData,
detailGridOptions: #nestedDetailGridOptionsFor('child'),
}
and withing loadNesteddata, we get params using we can select expanded row as
params.node.parent.setSelected(true)
Hope this helps.

Controller lifecycle: when to call table.autoResizeColumn()

I'm currently using onAfterRendering() hook to auto adjust the layout of a table like this:
onAfterRendering: function() {
var table = this.getView().byId('table');
for (var i = 0; i < table.getColumns().length; i++) {
table.autoResizeColumn(i);
}
}
The result is not usable: all columns are sized 100% of the parent's width.
If I add a simple button to invoke the exact same logic the table gets drawn nicely. It looks like the complete table needs to be present in the DOM before autoResizeColumn() works properly.
My question: is there a suitable hook/event I can use to invoke the resizing once the table is in the document?
You can use the onAfterRendering of the table as suggested and add an if statement with bResized boolean or some kind of counter to prevent the endless loop.
As others have answered you can put add a function to oTable.onAfterRendering but the trick is if you do any rendering in that function it will trigger another rendering event that will again trigger onAfterRendering.
The problem here is where to hang the boolean switch that determine you have done the thing you have done.
One way to get around that is to add some customer data to the table with oTable.addCustomData.
The pattern becomes :
```
oTable.onAfterRendering = function () {
// check the prototype
// read the custom data
var customData = this.getCustomData();
// confirm *your* custom data is in the array (and not some other custom data)
// if not do your rendering operation and then
// set a switch to custom data
this.addCustomData(new sap.ui.core.CustomData({
key: "myRenderingCheck",
value: "true",
"writeToDom": true
}));

telerik kendo treeview - prevent dragging outside of parent

I'm trying to prevent the dragging and dropping of nodes outside of the parent node ("LLCA") with no luck.
Any suggestions?
Image of Treeview
I ended up getting it to work using your code below:
function onDrop(e) {
var dst = e.destinationNode;
var first = $('.k-item:first');
var pos = e.dropPosition;
if (dst && dst.uid === first.uid && pos !== "over") {
e.setValid(false);
}
}
Lets define the treeview:
var tree = $("#tree").kendoTreeView({
dataSource :content,
dragAndDrop:true
}).data("kendoTreeView");
What I'm going to do is add a drop callback where I will control that:
We are not dropping outside the tree
We are not dropping before or after the first node of the tree
The definition of the tree would be:
var tree = $("#tree").kendoTreeView({
dataSource :content,
dragAndDrop:true,
drop :function (ev) {
var dst = tree.dataItem(ev.destinationNode);
var first = tree.dataItem(".k-item:first");
var pos = ev.dropPosition;
if (dst && dst.uid === first.uid && pos !== "over") {
console.log("invalid");
ev.setValid(false);
}
}
}).data("kendoTreeView");
Check http://docs.kendoui.com/api/web/treeview#drop for information on drop event.
Because I cannot comment on an answer, I will write my own.
User Mithrilhall asked about MVC wrappers, also the top answer only prevents movement to the root node.
I will attempt to answer both Mithrilhall and provide an example where you can only move a child within the context of its parent. To put it another way, to only allow children of any parent to change their order within the parent.
Firstly, for MithrilHall, this is how you get to the events in MVC.
#(Html.Kendo().TreeView()
.Name("ourTreeView")
.Events(e => e.Drop("treeViewDrop"))
There are other events in treeview, you can take a gander for yourself. The argument is the name of a javascript function. Here is an example javascript function for this MVC wrapper to prevent children from moving outside of their parent, but allowing them to still move within the parent.
<script type="text/javascript">
function treeViewDrop(dropEvent) {
var treeView = $("#ourTreeView").data("kendoTreeView");
var destination = treeView.dataItem(dropEvent.destinationNode);
var source = treeView.dataItem(dropEvent.sourceNode);
if (!(destination && destination.parentID == source.parentID)) {
dropEvent.setValid(false);
}
}
</script>
I had a parentID field modeled in my datasource. You could accomplish this in many ways. The dataItem method returns a kendo treeview item, so it has all of your modeled fields in it.
Also understand, this solution does not change the widget to show an X when you are moving to a place you cannot drop to. This is another problem with another solution.
I hope this helps, good luck!

Identify which instance of the view is currently active in RCP?

I am creating an RCP application. I need to open multiple instances of the same view but with different data. I did it by setting secondary id for different instances of the same view. Specifically, my problem is as follows: Please take a look
I have a graph view called Views.GraphView. I opened different instances of it from a command called openGraphView to show different graphs. The command is as follows:
page.showView("Views.GraphView", Integer.toString(instanceNum++), IWorkbenchPage.VIEW_ACTIVATE);
Now, I have a command called TreeLayout on this Views.GraphView toolbar, which suppose to change the layout of the graph and it will operate on each instance of the view. But for this, I think, I need to identify which instance of the view is active. The TreeLayout command looks something like this:
IViewPart findView = HandlerUtil.getActiveWorkbenchWindow(event).getActivePage(). findView( "Views.GraphView"); //I think in the findView I need to give the id of the view [but how can I put the secondary id?]
GraphView view = (GraphView) findView;
view.changeLayout(); //I wrote this method in the graph view to change the layout
//I just tried to print the secondary id, but it did not print anyting
System.out.println("From treelayout command:- " + view.getViewSite().getSecondaryId());
So how can I identify which instance of the view is currently active and to operate on it?
You can use IWorkBenchPage.findViewReference(String viewId, String viewId) , if it returns null, the view with viewId and viewId is not present in the current perspective.
If you have a ViewReference you can use ViewReference.getView(boolean restore) to get the view
so in your handler you get something like:
final IWorkbenchPage page = HandlerUtil.getActiveWorkbenchWindow(
event).getActivePage();
final int instanceNum = 8;//the number of instances that are created
for (int index = 0; index < instanceNum; index++) {
final IViewReference viewReference = page.findViewReference(
"Views.GraphView", Integer.toString(index));
if (viewReference != null) {
final IViewPart view = viewReference.getView(true);
if (view instanceof GraphView) {
final GraphView graphView = (GraphView) view;
graphView.changeLayout();
}
}
}
The view.getViewSite().getSecondaryId() method is the good one to identify a secondary view. This method only returns the Null string for the "primary" view: the one opened when user click Window -> Show View - Your View.
I don't understand why your view toolbar button has to operate on all the view instances. TO my eyes, you should have one button in each view instance toolbar operating only in its own view. If you really need to operate from one button to ALL the views I think you will have to keep the open views references yourself, because I think the workbench doesn't provide a findViews method returning a view array.
using the below code you should be able to get the current active view.
PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActivePart()
Active view and Editor name display on MessageDialogbox
public class Active_Workbench extends AbstractHandler{
#Override
public Object execute(ExecutionEvent event) throws ExecutionException {
// A part service tracks the creation and activation of parts within a workbench page.
IPartService service = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getPartService();
MessageDialog.openInformation(HandlerUtil.getActiveWorkbenchWindow(
event).getShell(), "Current Workbench Window", service.getActivePart().getTitle().toString());
return null;
}
}
I hope this answer is useful.

Dojo drag and drop, how do we save the position

After dojo drag and drop, once the page is submitted, I have to save the position of every item that has been placed into "targetZone". How can we save the position?
Eugen answered it here :
Dojo Drag and drop: how to retrieve order of items?
That would be the right way. If you look at the link above, you can save the resulting "orderedDataItems" object as a JSON ...
Look at the following function. It saves our DND "Lightbox" (dojo.dnd.source) to a JSON.
_it is the current raw dnd item
_it.data.item contains all your stuff you need to keep
in our case _it.data.item.label keeps the customized nodes (pictures, video, docs) as a string, we can use later to dojo.place it
it is the dnd item you want to save without dom nodes
E.g. if you drop items from a dijit tree to a arbitrary dojo dnd source / target:
_RAM or _S in our data.item we made before needs to be overwritten.
LBtoJson: function(){
var that = this;
var orderedLBitems = this.dndSource.getAllNodes().map(function(node){
var _it = that.dndSource.getItem(node.id);
var it = { data:{ item:{} }, label:'', type:'' };
if((_it.data.item._RAM)){_it.data.item._RAM={}}
if((_it.data.item._S)){_it.data.item._S={}}
it.data.item = dojo.clone(_it.data.item);
it.label = it.data.item.label[0]||it.data.item.label;
it.type = _it.type;
console.log( it );
return it;
});
var LBjson = dojo.toJson(orderedLBitems);
return LBjson;
}
By calling getAllNodes(), you'll receive a list of nodes in the order they are shown. So if you wanted to save a list in a specific order, you could do something similar to this:
var data;
var nodes = dndSrc.getAllNodes();
for(var i; i < nodes.length; i++)
{
data.push({id: nodes[i].id, order: i});
}
For more information about Dojo DnD regarding data submission, check out this article about DnD and Form Submission: http://www.chrisweldon.net/2009/05/09/dojo-drag-n-drop-and-form-submission