Announcement

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

    DynamicForm items _rowTable

    In DynamicForm you create the property _rowTable in items.
    Could you make this property readable in development mode?

    #2
    What is the use case where you think you want access to this property?

    During what part of the component lifecycle (clear/draw/init/redraw/clear/etc) would you need access.

    Note: neither question can be answered meaningfully on it's own.

    Comment


      #3
      I’m trying to implement a workaround for setting the width of form items that have their width set to "*", especially when the title field’s width changes dynamically.
      To achieve this, I handle the form’s drawn and resized functions and recalculate the item widths.
      Having access to the _rowTable would be very helpful for performing these calculations correctly.

      Comment


        #4
        Any approach based on accessing _rowTable - a temporary, internal calculation structure - would be a 100% unsupportable hack, which could easily break spontaneously due to us fixing an unrelated bug.

        If a field title's width changes dynamically, and you want the form to take this into account, you can do your own offscreen measurements of the title's width and then adjust the form's layout accordingly (e.g. colWidths).

        Comment


          #5
          Any approach based on accessing _rowTable - a temporary, internal calculation structure - would be a 100% unsupportable hack, which could easily break spontaneously due to us fixing an unrelated bug.
          To avoid potential errors, you could add a getRowTable function that returns a copy of the original _rowTable, rather than the _rowTable itself.
          Code:
          getRowTable = function () {
               return this.items?._rowTable ? this.items._rowTable.map(row => row.slice()) : null;
          }
          Last edited by Hirn; 1 Oct 2025, 00:26.

          Comment


            #6
            Definitely not, because it in order to provide such an API and have it be supportable, we have to document exactly where in the lifecycle it is available vs invalid, how exactly it is calculated, etc.

            This is a very large project in the first place, but then there is the further problem that returning this intermediate calculation requires us to maintain exactly the same algorithm forever, or break backcompat.

            So again - you have an approach with precalculation you can use, which fits neatly into the existing support.

            If that doesn't address your use case, explain your use case at a high level - but no more requests to reference random internals. We cannot expose those for you as supported APIs.

            Comment


              #7
              Instead of creating a separate function, you could assign a rowTable property to items inside applyTableResizePolicy and make it visible within the block:
              Code:
              if (!this._tableResizePolicyIsValid(items)) {
                  ...
                  items.rowTable = items._rowTable.map(row => row.slice());
              }

              Comment


                #8
                This does nothing to resolve all the issues noted above as far as creating supportable APIs.

                Basically:

                1) tell us your use case and we will try to describe a supportable way to do it (indeed we probably have already - please review the above)

                .. or ..

                2) hack whatever you like, but, expect your approach to break randomly and require a complete rework in the future. This may happen on even minor patches, because you are outside the supported API.

                Note that, because this is not a bug and not even a cognizable feature request, and multiple attempts have been made to help you without Support, you probably will not receive further responses here for several days. Just to set expectations.

                Comment


                  #9
                  This is a very large project in the first place, but then there is the further problem that returning this intermediate calculation requires us to maintain exactly the same algorithm forever, or break backcompat.

                  So again - you have an approach with precalculation you can use, which fits neatly into the existing support.

                  If that doesn't address your use case, explain your use case at a high level - but no more requests to reference random internals. We cannot expose those for you as supported APIs.
                  I have adopted the algorithm for creating _rowTable, but for correct calculations I will need to account for cases when form items are shown or hidden, and then rebuild my array. Most likely, you are already handling these cases and rebuilding _rowTable.
                  However, if it is not possible to make this property visible, then I apologize for the inconvenience.

                  Comment


                    #10
                    For the reasons explained above, it is not at all simple for us to make these intermediate calculations available. It's man-weeks of senior-effort to turn that into a supportable API, and we wouldn't want to support it long term, either!

                    So, we're not sure how your calculation works, but, from the vague idea you've given as to what your use case might be, you probably don't need that API anyway: just measure your titles offscreen and plug that into the existing layout algorithm, via colWidths.

                    Comment


                      #11
                      1) tell us your use case and we will try to describe a supportable way to do it (indeed we probably have already - please review the above)
                      Here is my class extending the standard DynamicForm. It is working correctly now, but I would like to avoid calling the buildRowItems function, which duplicates the algorithm for creating _rowTable. That’s why I wanted to access the existing _rowTable array.
                      This entire class was created for the setItemsWidths() function, which solves the problem with items having a width of "*" and a dynamically changing title width.

                      Code:
                      import ISC_CLASS from "../ISC_CLASS";
                      import { DynamicForm } from 'smartclient-pro/react';
                      let isc = window.isc;
                      class CustomForm extends DynamicForm {
                        static ISC_CLASS_NAME = "CustomForm";
                        static IS_CLASS = true;
                        static PROPERTY_TYPES = {};
                        static init = function () {
                          this.Super("init", arguments);
                          for (const field of this.getFields()) {
                            if (field.width === "*") {
                              field.calcWidth = true;
                            }
                          }
                        };
                        static buildRowItems = function (create) {
                          if (!this.isVisible()) return;
                          if (!create && this.rowsTable) return this.rowsTable;
                          var items = this.getItems();
                          var numCols = this.numCols || 2;
                          var rowTable = [];
                          var currentRow = 0;
                          var currentCol = 0;
                          for (var itemNum = 0; itemNum < items.length; itemNum++) {
                            var item = items[itemNum];
                            if (!item.isVisible()) continue;
                            var itemCols = item.getColSpan ? item.getColSpan() : (item.colSpan || 1);
                            var itemRows = item.getRowSpan ? item.getRowSpan() : (item.rowSpan || 1);
                            if (!itemCols || !itemRows) continue;
                            if (!isNaN(itemCols)) itemCols = parseInt(itemCols);
                            if (itemCols == null) itemCols = 1;
                            if (!isNaN(itemRows)) itemRows = parseInt(itemRows);
                            if (itemRows == null) itemRows = 1;
                            var requiredCols = (itemCols === "*") ? 1 : itemCols;
                            if (item.showTitle) {
                              requiredCols += (item.getTitleColSpan ? item.getTitleColSpan() : 1);
                              if (itemCols !== "*") itemCols += (item.getTitleColSpan ? item.getTitleColSpan() : 1);
                            }
                            var startRow = (item.isStartRow ? item.isStartRow() : item.startRow);
                            var endRow = (item.isEndRow ? item.isEndRow() : item.endRow);
                            var placeRow = null, placeCol = null;
                            if (item._startRow = (currentCol >= numCols || (startRow && currentCol != 0))) {
                              currentRow++;
                              currentCol = 0;
                            }
                            if (currentRow < rowTable.length) {
                              for (; currentRow < rowTable.length; currentRow++) {
                                var rowSlots = rowTable[currentRow];
                                if (!rowSlots) break;
                                for (; currentCol < numCols; currentCol++) {
                                  if (rowSlots[currentCol] != null) continue;
                                  for (var j = currentCol; j < numCols; j++) {
                                    if (rowSlots[j] != null) break;
                                    if ((j - currentCol) + 1 >= requiredCols) {
                                      placeRow = currentRow;
                                      placeCol = currentCol;
                                      break;
                                    }
                                  }
                                  if (placeCol != null) break;
                                }
                                if (placeCol != null) break;
                                currentCol = 0;
                                item._startRow = true;
                              }
                            }
                            if (placeCol == null) {
                              placeRow = currentRow;
                              placeCol = 0;
                              item._startRow = true;
                            }
                            currentCol = placeCol;
                            if (itemCols === "*") itemCols = numCols - currentCol;
                            if (!isc.isA.Number(itemRows)) itemRows = 1;
                            for (var r = currentRow; r < currentRow + itemRows; r++) {
                              if (!rowTable[r]) rowTable[r] = [];
                              for (var c = currentCol; c < currentCol + itemCols; c++) {
                                rowTable[r][c] = item;
                              }
                            }
                            currentCol += itemCols;
                            if (endRow) currentCol = numCols;
                          }
                          var rows = rowTable.map(function (cells) {
                            var unique = [];
                            for (var i = 0; i < cells.length; i++) {
                              var it = cells[i];
                              if (it && !unique.contains(it)) unique.push(it);
                            }
                            return unique;
                          });
                          return this.rowsTable = rows;
                        }
                        static drawn = function () {
                            this.setItemsWidths();
                        };
                        static resized = function () {
                            this.setItemsWidths();
                        };
                        static setItemWidth(item, width) {
                          if (item.getWidth() !== width) {
                            item.setWidth(width);
                            const canvas = item.canvas;
                            if (canvas) {
                              canvas.setWidth(width);
                            }
                          }
                        }
                        static setItemsWidths() {
                          setTimeout(() => {
                            const rowsTable = this.buildRowItems();
                            if (!rowsTable) return;
                            const patternWidth = this.getInnerContentWidth();
                            if (this.prevWidth !== patternWidth) {
                              this.prevWidth = patternWidth;
                              for (const rowItems of rowsTable) {
                                const starItems = [];
                                let fixedWidth = this.cellPadding * (rowItems.length + 1);
                                for (const item of rowItems) {
                                  if (item.calcWidth) {
                                    starItems.push(item);
                                  }
                                }
                                const starWidth = starItems.length > 0 ? Math.floor((patternWidth - fixedWidth) / starItems.length) : 0;
                                for (const item of rowItems) {
                                  if (starItems.includes(item)) {
                                    this.setItemWidth(item, starWidth);
                                  }
                                }
                              }
                            }
                          }, 0);
                        }
                      }
                      ISC_CLASS.registerClass(CustomForm, DynamicForm);
                      export default CustomForm;
                      Last edited by Hirn; 1 Oct 2025, 01:40.

                      Comment


                        #12
                        Again, if the problem you are trying to solve is that you want "*" sized columns to size perfectly in the presence of dynamic titles (without horizontal overflow), then the solution is just to measure the title widths offscreen and set colWidths from that.

                        That approach is massively simpler than whatever you're attempting here.

                        Comment

                        Working...
                        X