Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
Clear All
new posts

    ListGrid frozen column and canExpandRecords=true,

    I have a ListGrid component with columns configured using frozen=true and the grid also has canExpandRecords=true.
    The problem is that the expand component is displayed to the right of the frozen columns, and when the grid is scrolled horizontally it can move out of the visible area.
    Is it possible to make the expand component appear inside the frozen columns area so that it stays visible and does not move during horizontal scrolling?

    For demonstration purposes I slightly modified your example from this link:
    https://smartclient.com/smartclient-...tedWithDetails

    and defined the fields like this:
    fields: [
    {name: "itemName", width: 250, frozen:true},
    {name: "SKU", width: 250},
    {name: "category", width: 250}
    ],
    Last edited by Hirn; 10 Mar 2026, 23:07.

    #2
    We don't currently support that combination of features (frozen fields + expansion) per docs, because it would generally be really odd: if you think through the typical expansion modes, like sub-grids or detail views, there is no way to map the sub-grid columns to the main grid columns (usually different DataSources) to create corresponding separate scrolling regions.

    We could place the expansion component in only one of the two body areas (frozen or unfrozen) but this just results in a big blank in the other region. The blank is needed because otherwise the data in the second body area would not line up. We could also duplicate it for all grid bodies.

    If we tried to support this combo in a usable manner, probably the best approach would be to float an element over the frozen and unfrozen area that would scroll within itself if needed. However, that's a pretty unusual UI (we've never seen it elsewhere) and we're not sure end users would understand what was going on.

    It would be possible to implement this yourself, at the app level, because the grid exposes all the geometry necessary to place the component and you could change the row height so that it did not occlude later rows.

    So:
    1. what is the expansion component you have in mind? Can you maybe sketch out the ideal UI here, keeping in mind that the expansion is going to create gaps in the data for the second body?

    2. have you consider a hoverComponent, or just an area external to the grid that displays the data you want to show on expansion?

    Comment


      #3
      Thank you for your reply. I found a very simple workaround.

      I just overrode two functions in my ListGrid component, and after that everything worked exactly as I wanted.

      Code:
        addEmbeddedComponent(component, record, rowNum, colNum, position) {
          if (this.frozenBody) {
            colNum = 0;
            component.width = component.members[0].width = this.frozenBody.width - component.layoutLeftMargin;
          }
          this.Super("addEmbeddedComponent", [component, record, rowNum, colNum, position]);
        }
        fieldStateChanged() {
          if (this.frozenBody) {
            const expandedRecords = this.getExpandedRecords() || [];
            for (let record of expandedRecords) {
              const currentComponent = this.getCurrentExpansionComponent(record);
              const width = this.frozenBody.width - currentComponent.left - CONSTANT.PADDING;
              if (currentComponent.width != width) currentComponent.setWidth(width);
            }
          }
        }
      Last edited by Hirn; Today, 08:15.

      Comment


        #4
        My previous example does not work correctly if table columns are hidden until only the columns with frozen=true remain visible. In that case all expanded records disappear.

        To fix this issue I modified the functions I posted earlier and added one more function.

        For convenience I also added a variable to my grid:
        expandBody = "frozenBody" / "body".

        Code:
          addEmbeddedComponent(component, record, rowNum, colNum, position) {
            if (this.expandBody == "frozenBody" && this.frozenBody) {
              colNum = 0;
              component.width = component.members[0].width = this.frozenBody.width - component.layoutLeftMargin;
            }
            const owner = this;
            setTimeout(function () {
              owner.expandedRecords = owner.getExpandedRecords() || [];
            }, 0);
            this.Super("addEmbeddedComponent", [component, record, rowNum, colNum, position]);
          }
          removeEmbeddedComponent(record, component) {
            this.Super("removeEmbeddedComponent", arguments);
            const owner = this;
            setTimeout(function () {
              owner.expandedRecords = owner.getExpandedRecords() || [];
            }, 0);
          }
          fieldStateChanged() {
            if (this.expandBody == "frozenBody") {
              const oldExpandedRecords = this.expandedRecords || [];
              const oldLength = oldExpandedRecords.length;
              const currentExpandedRecords = this.getExpandedRecords() || [];
              const currentLength = currentExpandedRecords.length;
              if (oldLength !== currentLength) {
                if (!currentLength && oldLength) this.expandRecords(oldExpandedRecords);
              } else {
                if (this.frozenBody) {
                  for (let record of currentExpandedRecords) {
                    const currentComponent = this.getCurrentExpansionComponent(record);
                    const width = this.frozenBody.width - currentComponent.left - CONSTANT.PADDING;
                    if (currentComponent.width != width) currentComponent.setWidth(width);
                  }
                }
              }
            }
          }
        It is also necessary to take into account when creating the ExpansionComponent that the component width must be different for expandBody = "frozenBody" and expandBody = "body". I solved this problem in the following way...

        Code:
          getExpansionComponent(record) {
            const ExpansionComponent = record.inheritsGrid = isc.MyComponent.create({
              width: ((this.expandBody == "frozenBody" && this.frozenBody) ? 100 : "100%"),
              .....
            });
            return ExpansionComponent;

        Comment

        Working...
        X