Search code examples
csssapui5

sap.ui.table.Table: visibleRowCountMode="Auto" not working with VBox (FlexBox)


I would like the number rows of my sap.ui.table.Table to fit the screen height. I tried using visibleRowCountMode="Auto" for that but in the beginning, it did not work because certain parent elements did not have a height="100%".

My table is nested quite deeply into several Pages and FlexBoxes but this is kind of how my views look.

<VBox height="100%" class="sapUiTinyMarginBegin">
  <layout:Splitter id="CSL_idSplitter" height="100%" resize=".onSplitterResize">
    <VBox height="100%">
      <HBox justifyContent="SpaceBetween" height="100%">
        <VBox height="100%">
          <table:Table id="idTable" visibleRowCountMode="Auto" />
          <Button />
        </VBox>
      </HBox>
    </VBox>
  </layout:Splitter>
</VBox>

I also added this to my CSS file:

html, body {
  height: 100%;
}

According to other questions, this seemed to be the solution but it did not work for me. I found out that, in the DOM, the direct parent <div> of the table-control (which is automatically created by UI5 and does not seem to belong to any element declared in the view) was the problem because it did not have a style height: 100%.

Here is the DOM from the Chrome Dev-Tools (Yellow is my table and in red is the div without any height):

enter image description here

If I add the height to the element manually, the visibleRowCountMode="Auto" works fine.

So I found a quite ugly workaround and I was hoping that anyone would know a nicer way to overcome this issue. When the View is loaded, I select the parent <div> element of the table and set its height programmatically in onAfterRendering of the controller.

onAfterRendering: function() {
  const oTable = this.byId("idTable");
  const oHTMLElement = document.getElementById(oTable.getIdForLabel());
  oHTMLElement.parentNode.style.height = "100%";  
}

Since this is just a workaround, I was wondering where the real problem was lying and if anyone could help me solve it.


Solution

  • If the table has sibling controls, a prerequisite for the visibleRowCountMode="Auto" or sap.ui.table.rowmodes.Auto to work is that the table is allowed to grow within a flexbox element (e.g. sap.m.VBox). This can be achieved by adding <FlexItemData growFactor="1" /> to the layoutData aggregation of the table.

    <VBox xmlns="sap.m" renderType="Bare" fitContainer="true"><!-- or height="100%" -->
      <table:Table xmlns:table="sap.ui.table" visibleRowCountMode="Auto">
      <!-- visibleRowCountMode deprecated since 1.119 -->
      <!-- Add sap.ui.table.rowmodes.Auto to the aggregation rowMode instead. -->
        <table:rowMode><!-- since UI5 1.119 -->
          <rowmodes:Auto xmlns:rowmodes="sap.ui.table.rowmodes" />
        </table:rowMode>
        <table:layoutData><!-- Every control has the aggregation layoutData -->
          <FlexItemData growFactor="1" /><!-- Allow the Table to grow -->
        </table:layoutData>
        <table:columns>
          <!-- ... -->
        </table:columns>
      </table:Table>
      <Button /><!-- Other flex box sibling items ... -->
    </VBox>
    

    From the API reference of sap.ui.table.rowmodes.Auto:
    Similar description in the old visibleRowCountMode="Auto"

    The table must be rendered without siblings in the DOM. The only exception is if the table's parent element is a flexbox, and the table is a flex item allowed to grow and shrink.

    Here is a little demo:

    globalThis.onUI5Init = () => sap.ui.require([
      "sap/ui/core/mvc/XMLView",
      "sap/ui/model/odata/v4/ODataModel",
      "sap/ui/model/json/JSONModel",
    ], async (XMLView, ODataModel, JSONModel) => {
      "use strict";
      
      const control = await XMLView.create({
        definition: `<mvc:View xmlns:mvc="sap.ui.core.mvc"
          xmlns="sap.m"
          xmlns:table="sap.ui.table"
          displayBlock="true"
          height="100%"
        >
          <App autoFocus="false">
            <Page showHeader="false">
              <VBox
                fitContainer="true" 
                renderType="Bare"
              >
                <ToggleButton
                  pressed="{viewModel>/grow}"
                  text="{= %{viewModel>/grow} ? '' : 'Enable '}Growing Automatically"
                  type="Neutral"
                />
                <table:Table xmlns:table="sap.ui.table"
                  class="sapUiSizeCondensed"
                  columnHeaderVisible="false"
                  selectionMode="None"
                  visibleRowCountMode="Auto"
                  enableBusyIndicator="true"
                  rows="{/People}"
                >
                  <table:layoutData>
                    <FlexItemData id="myFlexItemData"
                      growFactor="{= %{viewModel>/grow} ? 1 : 0}"
                      backgroundDesign="Solid"
                    />
                  </table:layoutData>
                  <table:rowMode><!-- since UI5 1.119 -->
                    <rowmodes:Auto
                      xmlns:rowmodes="sap.ui.table.rowmodes"
                      minRowCount="3"
                    />
                  </table:rowMode>
                  <table:columns>
                    <table:Column>
                      <Text text="First Name" />
                      <table:template>
                        <Text text="{FirstName}" />
                      </table:template>
                    </table:Column>
                    <table:Column>
                      <Text text="Last Name" />
                      <table:template>
                        <Text text="{LastName}" />
                      </table:template>
                    </table:Column>
                  </table:columns>
                </table:Table>
              </VBox>
            </Page>
          </App>
        </mvc:View>`,
        models: {
          undefined: new ODataModel({
            serviceUrl: "https://services.odata.org/TripPinRESTierService/(S(w2saquxz0v41rmteqmgyytks))/",
            autoExpandSelect: true,
            sharedRequests: true,
          }),
          "viewModel": new JSONModel({ grow: true }),
        },
      });
    
      control.placeAt("content");
    });
    <script id="sap-ui-bootstrap"
      src="https://sdk.openui5.org/nightly/resources/sap-ui-core.js"
      data-sap-ui-libs="sap.ui.core,sap.m,sap.ui.table,sap.ui.layout,sap.ui.unified"
      data-sap-ui-async="true"
      data-sap-ui-on-init="onUI5Init"
      data-sap-ui-compat-version="edge"
      data-sap-ui-exclude-jquery-compat="true"
      data-sap-ui-resource-roots='{ "my.demo": "./" }'
      data-sap-ui-xx-wait-for-theme="init"
    ></script>
    <body id="content" class="sapUiBody sapUiSizeCompact"></body>

    Press Run Code Snippet and then "Full Page" to see the table adjusting its height automatically depending on the viewport height.


    API reference: sap.ui.table.rowmodes.Auto
    Understanding flex-grow, flex-shrink, and flex-basis