Subscribe for automatic updates: RSS icon RSS

Login icon Sign in for full access | Help icon Help
Advanced search

Pages: [1]
  Reply  |  Print  
Author Topic: Using Multidimensional Arrays with Screen Array Displays/Inputs  (Read 8759 times)
Sean H.
Posts: 29


« on: August 10, 2022, 12:06:29 pm »

I was wondering if there is a simpler way to get Multidimensional Arrays to work with Form Screen Arrays for Displays/Inputs

I have a Global Multidimensional Array set up like this

      tier01 dynamic array of record
         t01_id integer,
         t01_code varchar(10),

         tier02 dynamic array of record
            t02_id integer,
            t02_code varchar(10)
         end record
      end record


Which is just holding Dummy Data for Testing like this

      let tier01[1].t01_id = 1
      let tier01[1].t01_code = "T1-1"
      let tier01[1].tier02[1].t02_id = 1
      let tier01[1].tier02[1].t02_code = "T1-1 T2-1"
      let tier01[1].tier02[2].t02_id = 2
      let tier01[1].tier02[2].t02_code = "T1-1 T2-2"

      let tier01[2].t01_id = 2
      let tier01[2].t01_code = "T1-2"
      let tier01[2].tier02[1].t02_id = 3
      let tier01[2].tier02[1].t02_code = "T1-2 T2-3"
      let tier01[2].tier02[2].t02_id = 4
      let tier01[2].tier02[2].t02_code = "T1-2 T2-4"
      let tier01[2].tier02[3].t02_id = 5
      let tier01[2].tier02[3].t02_code = "T1-2 T2-5"

      let tier01[3].t01_id = 3
      let tier01[3].t01_code = "T1-3"
      let tier01[3].tier02[1].t02_id = 6
      let tier01[3].tier02[1].t02_code = "T1-3 T2-6"


And am wanting to display it to a very basic Form

      layout(windowStyle="standard")
         vbox
            group(text="Tier 01")
               table(height=1 lines)
               {
                [t01a ][t01b      ]
               }
               end
            end
            group(text="Tier 02")
               table(height=1 lines)
               {
                [t02a ][t02b      ]
               }
               end
            end
         end
      end
      attributes
         edit t01a = formonly.t01_id, title=%"ID";
         edit t01b = formonly.t01_code, title=%"Code";
         edit t02a = formonly.t02_id, title=%"ID";
         edit t02b = formonly.t02_code, title=%"Code";
         instructions delimiters "  "
         screen record screen_tier01(t01_id, t01_code)
         screen record screen_tier02(t02_id, t02_code)
      end


The Phantom Fields don't seem to work for Array Fields so I had to create duplicate Global Flat Arrays to get the display working

      # work around for displaying only
      tier01_flat dynamic array of record
         t01_id integer,
         t01_code varchar(10)
      end record,

      # work around for displaying only
      tier02_flat dynamic array of record
         t02_id integer,
         t02_code varchar(10)
      end record


Then I can use the Display Array as normal

      dialog d_display_tier01()

         display array tier01_flat
            to screen_tier01.*

         end display

      end dialog

      dialog d_display_tier02()

         display array tier02_flat
            to screen_tier02.*

         end display

      end dialog


Then I am just copying the data from the Multidimensional Array into each respective Flat Array so it can be applied to the displays.

I'm just wondering if there is a better way to do this that doesn't need the creation of the Flat Arrays so I can stick with a single Multidimensional Array.
Reuben B.
Four Js
Posts: 1047


« Reply #1 on: August 12, 2022, 07:57:54 am »

A comment on your code under Display Array as normal.  With two flat arrays, you can use multi-dialog.

So something like this, uses the before row of the tier01 flat array to change what is in the tier02 flat array and the user can click freely between the two arrays.

 
Code
  1.   -- populate tier01_flat
  2.    FOR i = 1 TO tier01.getLength()
  3.        LET tier01_flat[i].t01_code = tier01[i].t01_code
  4.        LET tier01_flat[i].t01_id = tier01[i].t01_id
  5.    END FOR
  6.  
  7.    LET tier01_row = 1
  8.    OPEN WINDOW w WITH FORM "forum1822"
  9.    DIALOG ATTRIBUTE(UNBUFFERED)
  10.        DISPLAY ARRAY tier01_flat TO screen_tier01.*
  11.            BEFORE ROW
  12.                -- populate tier02_flat as row 1 changes
  13.                LET tier01_row = dialog.getCurrentRow("screen_tier01")
  14.                CALL tier02_flat.clear()
  15.                FOR i = 1 TO tier01[tier01_row].tier02.getLength()
  16.                    LET tier02_flat[i].t02_code = tier01[tier01_row].tier02[i].t02_code
  17.                    LET tier02_flat[i].t02_id = tier01[tier01_row].tier02[i].t02_id
  18.                END FOR
  19.        END DISPLAY
  20.        DISPLAY ARRAY tier02_flat TO screen_tier02.*          
  21.        END DISPLAY
  22.  
  23.        ON ACTION close
  24.            EXIT DIALOG
  25.    END DIALOG




Otherwise for complex arrays that are readonly there is always the web component path, see https://github.com/FourjsGenero/wc_2darray


Your idea of using phantom field "The Phantom Fields don't seem to work for Array Fields" is nice but doomed as arrays are done by position.   See this example http://4js.com/online_documentation/fjs-fgl-manual-html/#fgl-topics/c_fgl_DisplayArray_030.html and discussion http://4js.com/online_documentation/fjs-fgl-manual-html/#fgl-topics/c_fgl_Migrate_to_300_struct_arr.html

Reuben

Product Consultant (Asia Pacific)
Developer Relations Manager (Worldwide)
Author of https://4js.com/ask-reuben
Contributor to https://github.com/FourjsGenero
Reuben B.
Four Js
Posts: 1047


« Reply #2 on: August 15, 2022, 02:26:00 am »

I was thinking afterwards I could improve that code ...

The copy in the BEFORE ROW
Code
  1.               CALL tier02_flat.clear()
  2.               FOR i = 1 TO tier01[tier01_row].tier02.getLength()
  3.                   LET tier02_flat[i].t02_code = tier01[tier01_row].tier02[i].t02_code
  4.                   LET tier02_flat[i].t02_id = tier01[tier01_row].tier02[i].t02_id
  5.               END FOR

could have been done in less lines using the .* notation
Code
  1.               CALL tier02_flat.clear()
  2.               FOR i = 1 TO tier01[tier01_row].tier02.getLength()
  3.                   LET tier02_flat[i].* = tier01[tier01_row].tier02[i].*
  4.               END FOR

or even better as one line of code using the copyTo method as the datatypes are the same....

Code
  1. CALL tier01[tier01_row].tier02.copyTo(tier02_flat)

or even better it could take advantage of the fact that assignment of dynamic arrays is done by reference ...

Code
  1. LET tier02_flat =  tier01[tier01_row].tier02
  2.  
thus the second DISPLAY ARRAY in the multi dialog could be an INPUT ARRAY or a DISPLAY ARRAY with CRUD and changes would be made to tier[tier01_row]



Unfortunately I could not think of a way for tier01_flat to be similarly populated by reference from tier01

Reuben






Product Consultant (Asia Pacific)
Developer Relations Manager (Worldwide)
Author of https://4js.com/ask-reuben
Contributor to https://github.com/FourjsGenero
Sean H.
Posts: 29


« Reply #3 on: September 05, 2022, 05:30:35 pm »

The new and improved code looks really nice and will be a viable way to implement what I am trying to do.

I'm also just puzzling on how to copy arrays that don't have the exact same fields. The only way I've been able to do it is with a dedicated get function

function f_get_tier01_flat(tier01)

    define

        tier01_row integer,

        tier01 dynamic array of record
            t01_id integer,
            t01_code varchar(10),

            tier02 dynamic array of record
                t02_id integer,
                t02_code varchar(10)
            end record
        end record

        tier01_flat dynamic array of record
            t01_id integer,
            t02_desc varchar(10)
        end record

    call tier01_flat.clear()
    for tier01_row = 1 to tier01.getLength()
        let tier01_flat[tier01_row].id = tier01[tier01_row].id
        let tier01_flat[tier01_row].code = tier01[tier01_row].code
    end for

   return tier01_flat

end function

Reuben B.
Four Js
Posts: 1047


« Reply #4 on: September 05, 2022, 11:01:52 pm »


Quote
I'm also just puzzling on how to copy arrays that don't have the exact same fields. The only way I've been able to do it is with a dedicated get function

Try something like ...

Code
  1. CALL util.JSON.parse(util.JSON.stringify(tier01),tier01_flat)

... the util.JSON.parse parses by name and will ignore differences

Reuben

Product Consultant (Asia Pacific)
Developer Relations Manager (Worldwide)
Author of https://4js.com/ask-reuben
Contributor to https://github.com/FourjsGenero
Sebastien F.
Four Js
Posts: 509


« Reply #5 on: September 06, 2022, 08:58:50 am »

Hello Sean,

Sorry to jump late on this and if I am missing something...

First, let's call a spade a spade.

You original structure:

Code
  1.      tier01 dynamic array of record
  2.         t01_id integer,
  3.         t01_code varchar(10),
  4.  
  5.         tier02 dynamic array of record
  6.            t02_id integer,
  7.            t02_code varchar(10)
  8.         end record
  9.      end record

Is not exactly what we call a "multi-dimensional" array.

Multi-dimensional dynamic arrays are defined by the "WITH DIMENSION" clause, see Syntax 2 in:
https://4js.com/online_documentation/fjs-fgl-manual-html/#fgl-topics/c_fgl_Arrays_002.html
Example:
Code
  1.  DEFINE myarray DYNAMIC ARRAY WITH DIMENSION 2 OF INTEGER

In your structure, you define a sub-array, as a record element of the main array.

To me this is an indicator that there is a relationship between sub-rows and main rows.

Are you sure you want to control these separate sets of rows in individual DISPLAY ARRAY dialogs?

Would your structure not better be displayed in a TREE view?

https://4js.com/online_documentation/fjs-fgl-manual-html/#fgl-topics/c_fgl_treeviews_001.html

Seb
Sebastien F.
Four Js
Posts: 509


« Reply #6 on: September 06, 2022, 12:49:23 pm »

While working on a sample using a tree view, I saw that the ids of the sub-array (t02_id) can be equal to the ids of root/parent rows (t01_id) ...

      let tier01[1].t01_id = 1
      let tier01[1].t01_code = "T1-1"
      let tier01[1].tier02[1].t02_id = 1

Is this really the case?

This would be a blocker to implement a tree view.

But if you can produce ids that are unique, it's possible (see attachment)

Seb

* tv1.zip (1.37 KB - downloaded 863 times.)
Pages: [1]
  Reply  |  Print  
 
Jump to:  

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines