SAP / openui5

OpenUI5 lets you build enterprise-ready web applications, responsive to all devices, running on almost any browser of your choice.
http://openui5.org
Apache License 2.0
2.94k stars 1.23k forks source link

Table method getRows() returns only visible Rows #393

Closed JenniferKiesel closed 9 years ago

JenniferKiesel commented 9 years ago

In my use case I wanted to get the selected indices and the related rows. So I used the methods getSelectedIndices() and getRows(). But to my utter surprise I only get the actual visible rows, but the indices are the "real" indices (so when scrolled down they start fortunately NOT with 0).

In my opinion this is a bug, because working with indices and the rows becomes useless. Also the method should be called "getVisibleRows()" or something similar to make it clear.

Actual I use "the workaround" that I use the indices with my related model.

OpenUI5 version: 1.24.2

Browser/version (+device/version): Google Chrome 41.0.2272.118 (64-bit)

Any other tested browsers/devices(OK/FAIL): Firefox 37.0.1

Steps to reproduce the problem:

  1. Open the JSBin example
  2. Click the button and look into the console
  3. Scroll the table down, click the button and look into the console again http://jsbin.com/pujokiyusa/1/edit?html,console,output

What is the expected result? getRows() should return ALL rows

What happens instead? It returns only the displayed rows

sirion commented 9 years ago

Hi Jennifer,

you can currently use the getContextByIndex-method to get the row-context for all rows regardless of whether they are visible or not. https://sapui5.netweaver.ondemand.com/sdk/#docs/api/symbols/sap.ui.table.Table.html#getContextByIndex

I will contact the control owner to get more information on this and get back to you.

Internal reference: 1570147881

SebastianRied commented 9 years ago

Hi Jennifer, we are currently updating the documentation. I'll include your feedback and will try to make it clear, that getRows() only returns the visible rows.

When you only use client-models, you can go with getContextByIndex().

When you use OData models there are a few things to consider: Due to paging and lazy loading of the table content it's quite difficult to return "all" rows with an API call since it might be the case that not all records are loaded yet. This might even be the case when using getContextByIndex. While this works nicely when all records are at the client, the method might return undefined and trigger a request for this single entity in order to load the missing entity. This can happen in select-all scenarios. I'd propose to process select-all scenarios in the backend, rather than loading all contexts to the client and then sending them back to the backend in order to perform an action.

If you require all data at the client, you might want to use the getContext method of the underlying (OData)ListBinding. It accepts start index, length and a threshold as parameters and will load the requested section from the backend or just return it if all is loaded. You need to register to the change event of the binding. This event will get fired when the model has finished loading.

joeybronner commented 7 years ago

Hi,

Can you please update the openui5 documentation https://openui5.hana.ondemand.com/#docs/api/symbols/sap.ui.table.Table.html#getRows ? I lost time to understand why I only get visible rows with the getRows() method... until I found this post.

Thank you guys.

sonjadeissenboeck commented 5 years ago

These methods are not working for me. I'm looking for a way to loop through the cell content for all of the cells. @SebastianRied @sirion With getContextByIndex() or _getContext() I can't access the getText() method of the rows, I only get the constructors for each of them. Is there another way for accessing the content?

kak00n commented 5 years ago

Hello,

If I need to know the selected indices (in collapse or expanded elements, both), it's not possible. getContextByIndex() need a parameter to return data. This solution not resolved the problem of the thread.

Regards.

sfdfklskldf commented 5 years ago

So the table is for "big amount of data" but mass change does not work well?

What would be the correct solution to mass change for example 2000 entries? A function import? How should it work with the information of ".getSelectedIndices()"? Frontend could be sorted somehow and also user could uncheck some entries.

davidconvista commented 5 years ago

I found myself in the same situation. If I want to delete all entries in the table I need to set the table threshold to a number higher than the number of entries, in order to preload them beforehand and being able to get the context afterwards and calling remove for each entry path.

This seems innapropiate to me, because I now have 2000 entries, but i could be having several thousands more...

I thought about the idea of creating a function import for mass deletion, checking whether the select all is active or not, but what if the user selects all and afterwards deselects one?

Is there gonna be any solution to this?

Thank you

TeeOlee commented 4 years ago

I thin it is still open in SAP Ui5 16013... It says ...

"Gets content of aggregation rows. Rows of the Table"

Yeah well but only gets the visible rows.

getSelectedIndices() returns all Indices but nothing else like the data/key of the row... Now im more or less blind on what rows the user has marked(selected) ,... My idea was to match the index with the rows to get the selected row

var oTab = this.getView().byId("tblAdminMaint"); var oRows = oTab.getRows();

        if (oTab) {
            var oSelRows = oTab.getSelectedIndices();
            if (oSelRows) {
                for (var i = 0; i < oSelRows.length; i++) {

                    for (var ii = 0; ii < oRows.length; ii++) {
                        if (oRows[ii].getIndex() === oSelRows[i]) {
                            var oSource = this.getView().getModel().getProperty(oRows[ii].getBindingContext().sPath);
                            if (oSource) {
                                // do something
                            }
                        }
                    }

                }
            }
        }

    }

Do we have any other solution to read all currently selected rows(with data also not visible) ?

Thanks in advance

TeeOlee commented 4 years ago

I now found a solution for me...

  1. Load all data at once by setting threshold="20000000" of the table to a high number
  2. Access aKeys to retrieve the object that was selected i.e. path

testItemsSelected: function (oEvent) {

        var oTab = this.getView().byId("tblAdminMaint");
        // var oRows = oTab.getRows(); //Does not work, only returns visible rows
        var oRows = oTab.getBinding().aKeys; //this is returning the array with keys excalctly haveing same sorting/filtering and can be accessed via index
        var sSelected = "";

        if (oTab) {
            var oSelRows = oTab.getSelectedIndices();
            if (oSelRows) {
                for (var i = 0; i < oSelRows.length; i++) {

                    var oRow = this.getView().getModel().getObject("/" + oRows[oSelRows[i]]);
                    if (oRow) {
                        sSelected = sSelected + oRow.Prototypematnr + ";"; //Prototypematnr = any attribute of your row/model
                    }

                }

                sap.m.MessageToast.show(sSelected);
            }
        }

    }
AnuradhaSharma000111 commented 4 years ago

Hi TeeOlee, As per your solution, it is showing a simple Table not a smart table. so, when we need to show number of columns that time it is not possible to show.

AnuradhaSharma000111 commented 4 years ago

Still, I am finding some solutions for this.

AnuradhaSharma000111 commented 4 years ago

Hi, I think I got the solutions.

//START //END ##Just add code written between START and END to your table and use the same table Id= “TableId” to get your selected Column. If you are working on multiple selection you can use the below code: var oList = this.getView().byId("TableId"); var aSelectedIndex = oList.getSelectedIndices(); var TableDataArray = []; for (var i in aSelectedIndex) { var Selectedrow = oList.getModel().getProperty(oList.getContextByIndex(oList.getSelectedIndices()[i]).sPath); TableDataArray.push(Selectedrow); }
EricVanEldik commented 1 year ago

For anyone comming across this problem I used this the get the actual number of rows visible, but this can also be used to read the rows.

const table = this.getView().byId("MaterialTable");
table.setVisibleRowCount(table.getBinding("rows").getLength());
const oBinding = table.getBinding("rows"); 
oBinding.attachChange(function() {
            table.setVisibleRowCount(oBinding.getLength());
});
ThomasChadzelek commented 1 year ago

This looks a bit weird to me. The 2nd line is essentially the same as the event handler. What are you trying to achieve thereby?

Maybe https://openui5.hana.ondemand.com/api/sap.ui.model.ListBinding#methods/getAllCurrentContexts is what you are looking for?

EricVanEldik commented 1 year ago

This looks a bit weird to me. The 2nd line is essentially the same as the event handler. What are you trying to achieve thereby?

Maybe https://openui5.hana.ondemand.com/api/sap.ui.model.ListBinding#methods/getAllCurrentContexts is what you are looking for?

The second line is to initialize, because attachChange is only called on a change.

leonikussmaul commented 1 year ago

Hi,

Another quick workaround that might fit some use cases is to simply bind the visibleRowCount property of the table to the model that has the table data stored and calculate the length using expression binding. This way avoids any complicated JS code and handles the calculation directly in the XML view.

visibleRowCount="{= ${tablemodel>/rows}.length }"

In this example i have stored the data for the rows inside the rows property of my JSON Model "tablemodel". Now getRows() returns all the rows which can be useful at times. In my use case, i needed to apply custom css to specific table cells and this was the only way that worked. However, it might not be the best approach for a large dataset.

Vidal-Exxon-JM commented 1 year ago

I have a question leonikussmaul, how can I set the visible row count from the controller? Because initially I am displaying the TreeTable empty, and when the filters are populated, then with bindRows I am populating the table

This is my code and is not working the parameter visibleRowCount new Promise(function (resolve, reject) { oTableTree.bindRows({ path: "/FieldsSet", filters: that.makeFilters(), parameters: { expand: "JoinClauseSet", countMode: "Inline", numberOfExpandedLevels: 1, operationMode: "Client", editable: true, json: true, visibleRowCountMode: "interactive", visibleRowCount: "FieldsSet>rows.length", useServersideApplicationFilters: true } }); }).then(that.changeVisibility(true));

Thanks a lot for the help, really appreciate it

leonikussmaul commented 1 year ago

Hi @Vidal-Exxon-JM,

Have you tried calling the method setVisibleRowCount()?

Something like this in your controller..

var aRows = oTableTree.getRows().length; oTableTree.setVisibleRowCount(aRows);