27
Views
10
Comments
Solved
Dynamically create a table layout

Hi,

I have a screen TemplateDetail where the user can add new lines. The user should be able to dynamically create a layout in a tabular format like this:


For that I have this data model above. But Im with doubt about how to handle the case where there is in the column some lines. Maybe with the border type is possible to achievae that but Im not understanding why. 

Do you know how to properly achieve this? I have a oml with a example already working to create lines but without this case with more lines in the column working because Im not understanding how to achieve that. Thanks.

layout.oml

Rank: #237
Solution

Hi,

This was actually a nice challenge to try. It's possible, but you need to handle some of the cases previously handled by OutSystems by yourself. I think this could also be achieved using CSS grid layout, but then it would not be a table.

Here's how it looks:

I took the liberty of creating following data structure(s). This can be improved in many ways, but the principle remains - Data is a list of records containing a possible list of sub-records:

"Data" variable is used as Table Records widget's Source record list. 

Next, I'm filling in the data. This can be achieved dynamically quite easily, query from your data source or append from modal / popup, depending on your use case. Whenever item is added or removed, table just needs to be refreshed using Ajax refresh widget. Again, for the sake of demonstration, I'm skipping adding rows and using screen preparation to do this:

  • ListAppend_row<n> and ListAppend_Title<n> items are appended to Data list
  • ListAppend<n> items are appening new SectionDataitems to the most recently appended ListAppend_row item like this:
    • Data[Data.Length-1].SectionDataitems

Table / UI is the most tricky thing to achieve, but because OutSystems allows us to override HTML table properties using "colspan" and "rowspan" attributes in OutSystems element extended properties, table cells are completely customizable, albeit some of this is visible only during runtime. 

To get rid of extra cells, we can hide table cells using "class" or "style" extended properties and use CSS "display: none" where we don't want a cell to be visible. If we are using "class" property, this causes all out-of-the-box classes to be overridden (TableRecords_OddLine / EvenLine), so these need to be added back manually using same class/style extended properties. This applies to your requirement for differently styled title rows as well, just add your own styling:

class
  "TableRecords_"+If (Mod(TableRecords1.List.CurrentRowNumber+1,2)=0, "OddLine","EvenLine")

3rd column in the end of the table needs some extra trickery because it needs to span several rows. This is a simple example, where first item spans down and some use cases are probably not handled correctly. Rowspan can be set like this to drop the first row:

rowspan
  If(TableRecords1.List.Current.IsCol3RowSpan, 99, 1)

Then I remove the subsequent columns from the screen with inline style:

style
  If (TableRecords1.List.Current.IsTitleRow or TableRecords1.List[DecimalToInteger(Max(0,TableRecords1.List.CurrentRowNumber-1))].IsCol3RowSpan,"display:none;","")

Displaying a list of items inside table needs to be done with a web block, so I created one which takes a list of SectionDataitems as its input parameter. Nothing fancy here, just listing items with ListRecords widget:

I hope this helps, drop me a PM if you need to see the live version.

br,

-Mikko(N)

Hi Jake,

Good evening!

You need to use a Table records widget for that one.

Then next, you need to create a Webblock, which holds the format/template you desire.

Then going back to the Table records widget, inside its Row widget, you have to place the web block.

Hope this helps,

Thank you and good night,

Chris

Rank: #7780

Thanks, but the user should be able to create a table dynamically, is not a static table, the table can have a different format but the possible formats are this, but the table can have more or less rows more or less sections.

mvp_badge
MVP
Rank: #2

Hi Jake,

Fully dynamic tables are not possible with OutSystems. You can however fake it by having a Table Records with different styling per row depending on some value in your list.

Rank: #541

That's right. 

I tried a lot here and couldn't do it. We just have access to the Row Span property in a Cell from Table Widget,  but, from Table Record and List Records, it is not available. 

Best regards.

Rank: #7780

Thanks, yes I was trying to achieve this without using a table, but using containers and borders. But Im not understanding how to achieve this layout properly even without table, only using containers with borders.

Rank: #541

But you can do it with a Table Widget (TW), not a Table Records Widget.

In the cell of a TW, you can set the Row Span attribute, it will make the cell to expand to another row (look at this link to see how it works with pure HTML: Row Span).

You will have to create the logic that will calculate how many rows a cell will have to span and set that attribute.

Rank: #7780

But like that is necessary to change the data model in the oml right? Also it seems that the table widget dont allow the use of list records.

Rank: #541

I thought It could be done with Table Widget, but I was wrong. It is not possible to add rows and cell at runtime. At least, I didn't find how to do it.

Champion
Rank: #270

You could, but by doing this, it doesn't count as Low Code anymore.

Basically you use javascript for generating table.


See my example .oml (after this run, click on flag icon to view the table)


Explanation :

Get data in preparation, assign to a structure before serialize to JSON (this is to prevent JSON has entity on the JSON structure)

If you use serialize JSON directly from aggregate :

[

  {

    "User": {

      "Id": 6,

      "Name": "Adam Jones",

      "Username": "adam.jones",

      "Password": "CEB83AADAD8ACD27B8B9D8896ED3AF90",

      "Email": "adam.jones@customer360.com",

      "Creation_Date": "1900-01-01T00:00:00",

      "Last_Login": "2020-04-08T09:43:23.203Z",

      "Is_Active": true

    }

  }

]


If you convert this to structure first :

[

  {

      "Id": 6,

      "Name": "Adam Jones",

      "Username": "adam.jones",

      "Password": "CEB83AADAD8ACD27B8B9D8896ED3AF90",

      "Email": "adam.jones@customer360.com",

      "Creation_Date": "1900-01-01T00:00:00",

      "Last_Login": "2020-04-08T09:43:23.203Z",

      "Is_Active": true

    }

  ]


Then after that, will run javascript (i use from this link)

The javascript will read JSON data and generate HTML table.

GenerateTable.oml

Rank: #237
Solution

Hi,

This was actually a nice challenge to try. It's possible, but you need to handle some of the cases previously handled by OutSystems by yourself. I think this could also be achieved using CSS grid layout, but then it would not be a table.

Here's how it looks:

I took the liberty of creating following data structure(s). This can be improved in many ways, but the principle remains - Data is a list of records containing a possible list of sub-records:

"Data" variable is used as Table Records widget's Source record list. 

Next, I'm filling in the data. This can be achieved dynamically quite easily, query from your data source or append from modal / popup, depending on your use case. Whenever item is added or removed, table just needs to be refreshed using Ajax refresh widget. Again, for the sake of demonstration, I'm skipping adding rows and using screen preparation to do this:

  • ListAppend_row<n> and ListAppend_Title<n> items are appended to Data list
  • ListAppend<n> items are appening new SectionDataitems to the most recently appended ListAppend_row item like this:
    • Data[Data.Length-1].SectionDataitems

Table / UI is the most tricky thing to achieve, but because OutSystems allows us to override HTML table properties using "colspan" and "rowspan" attributes in OutSystems element extended properties, table cells are completely customizable, albeit some of this is visible only during runtime. 

To get rid of extra cells, we can hide table cells using "class" or "style" extended properties and use CSS "display: none" where we don't want a cell to be visible. If we are using "class" property, this causes all out-of-the-box classes to be overridden (TableRecords_OddLine / EvenLine), so these need to be added back manually using same class/style extended properties. This applies to your requirement for differently styled title rows as well, just add your own styling:

class
  "TableRecords_"+If (Mod(TableRecords1.List.CurrentRowNumber+1,2)=0, "OddLine","EvenLine")

3rd column in the end of the table needs some extra trickery because it needs to span several rows. This is a simple example, where first item spans down and some use cases are probably not handled correctly. Rowspan can be set like this to drop the first row:

rowspan
  If(TableRecords1.List.Current.IsCol3RowSpan, 99, 1)

Then I remove the subsequent columns from the screen with inline style:

style
  If (TableRecords1.List.Current.IsTitleRow or TableRecords1.List[DecimalToInteger(Max(0,TableRecords1.List.CurrentRowNumber-1))].IsCol3RowSpan,"display:none;","")

Displaying a list of items inside table needs to be done with a web block, so I created one which takes a list of SectionDataitems as its input parameter. Nothing fancy here, just listing items with ListRecords widget:

I hope this helps, drop me a PM if you need to see the live version.

br,

-Mikko(N)