How to manage responsive design

I can’t understand how to manage responsive design for a xojo web app. For example, I want to create a web app that has 2 photo aligned horizontally as picture #1. Then, once the webpage is resized, web app should adjust vertically as picture #2 shows. How

pix #1
from here.

pix #2
to here >>

You can do it the hard way, by adding code to WebPage.Resized, like this:

WebPage1.Resized
   Relayout()

Sub Relayout()
    dim w as integer = self.width
    dim h as integer = self.height

    dim x,y as integer 

    if w < 500 then
      ' --------------------------------------------------------------------------------
      ' one picture per row
      ' --------------------------------------------------------------------------------
      picture1.top = 32
      picture2.top = picture1.top + picture1.height + 32
      ... [etc.]
    else if w < 1000 then
      ' --------------------------------------------------------------------------------
      ' two pictures per row
      ' --------------------------------------------------------------------------------
      picture1.top = 32
      picture2.top = picture1.top
      picture2.left =  picture1.left + picture1.width + 32
      picture3.top = picture1.top + picture1.height + 32
      // etc.
    end if
end if

There are some issues with moving controls, however, bugs which we hope to see fixed soon?

  • 61536 - WebUIControl: Changing location is undone by visibility or contents change feedback://showreport?report_id=61536
  • 61544 - WebUIControl.WebStyle.value(“width”) changes wrong div feedback://showreport?report_id=61536

In a web app this should be done via CSS (bootstrap has already the styles)
Is abnormal to use the server (one core…) to do this.

3 Likes

Use the Flex layout for the WebContainer:
In the open event you can do something like this:

LayoutType = LayoutTypes.Flex
for i as integer = 0 to 5
  dim cc as new CCTextfield
  cc.EmbedWithin(self, self.Width, cc.Height)
  cc.AddResponsiveLayout(12,6,4,3,2) //Optional if you want to specify columns
next

AddResponsiveLayout is a custom method I built so you can specify the columns for XS,Small,Medium,Large, and XL screens based on a 12 column system. Use this if you want your controls to stretch to fill up the space evenly.

Here’s the helper method you can add on a Module:

Public Sub AddResponsiveLayout(extends control as WebUIControl, ColXS as integer = -1, ColSm as integer = -1, ColMd as integer = -1, ColLg as integer = -1, ColXl as integer = -1)
  dim classesToAdd() as string
  //-1 = inherit
  if ColSm = -1 then ColSm = ColXS
  if ColMd = -1 then ColMd = ColSm
  if ColLg = -1 then ColLg = ColMd
  if ColXl = -1 then ColXl = ColLg
  //0 = hidden https://getbootstrap.com/docs/4.0/utilities/display/
  if colxs = 0 or colsm = 0 or colmd = 0 or collg = 0 or colxl = 0 then //If Any Hidden
    if ColXs = 0 then classesToAdd.Append("d-none") else classesToAdd.Append("d-block")
    if ColSm = 0 then classesToAdd.Append("d-sm-none") else classesToAdd.Append("d-sm-block")
    if ColMd = 0 then classesToAdd.Append("d-md-none") else classesToAdd.Append("d-md-block")
    if ColLg = 0 then classesToAdd.Append("d-lg-none") else classesToAdd.Append("d-lg-block")
    if ColXl = 0 then classesToAdd.Append("d-xl-none") else classesToAdd.Append("d-xl-block")
  end
  //1-12 https://getbootstrap.com/docs/4.0/layout/grid/
  if ColXs > 0 then classesToAdd.Append("col-"+ColXs.ToString)
  if ColSm > 0 then classesToAdd.Append("col-sm-"+ColSm.ToString)
  if ColMd > 0 then classesToAdd.Append("col-md-"+ColMd.ToString)
  if ColLg > 0 then classesToAdd.Append("col-lg-"+ColLg.ToString)
  if ColXl > 0 then classesToAdd.Append("col-xl-"+ColXl.ToString)
  
  //ADD CLASSES
  for each classToAdd as string in classesToAdd
    dim js as string = "document.getElementById('"+control.ControlId+"').classList.add('"+classToAdd+"');"
    control.ExecuteJavaScript(js)
  next
End Sub
1 Like

Thank Guys!

Hi Nash,

Does this mean, I must call “AddResponsiveLayout” for each webUI control that I will be using in webcontainer?

Each container can take up a different number of columns, you’ll want to specify this for each container you add. The controls within the container won’t need this. They will be laid out with the standard layout. I suggest locking the controls left and right so they stretch the with responsive layout when embedded

whew!

I think, this is no longer embraceable for newbies.

and It’s seems, it’s more easier to use “ready to use” bootstrap template and edit its html to design the web screen, rather than managing webUI control in xojo.

is it possible with Xojo web?

Yes, if you look at my example it uses the built-in bootstrap classes.

Here’s a simple example project:

I would like to compose a “real” page.
How can I insert other controls in ContainerControl1?

thank you

Just drag the control to container control. Then drag the container control to the webpage.

Just to add a bit of clarity if it is needed, I will expand on @ronaldo_florendo answer :

  • you need to create your webcontainer separately, just like you would a page.
  • then, drag the completely designed container to the destination page (or other container).

In web 1.0, I also like to use (abuse?) webdialogs to reduce the density of controls on the page or container. It is somewhat different in 2.0 with dialogs behaving differently (apparently, you can fix that at the level of the bootstrap style, but that is yet another issue that I have with 2.0. Hopefully, a future release will improve on that.)

does this mean responsive design is not (yet) working for web dialogs? I’m indeed currently struggling with this.

I simply added 4 buttons in ContainerControl1 of the Web2SimpleResponsiveLayout demo project.
then I dragged ContainerControl1 into WebPage1.
but the 4 buttons are displayed with fixed layout.
I think the AddResponsiveLayout method should be applied to every ContainerControl1’s control.
or not?
how to do it?

I’m sure there is more functionality to be exposed that will help us deal with this a little easier.

For now @Brock_Nash is really blazing a path for us.

That being said, I would kill to have a Xojo template engine, where we can mix html and Xojo code, save it to a file and then return that as a response from HandleURL.

I’m still new here - is this possible already? I have not looked at WebSDK at all.

I prefer making the other controls and then embedding them in the parent container’s Open event like the example i showed:

LayoutType = LayoutTypes.Flex
for i as integer = 0 to 5
  dim cc as new CCTextfield
  cc.EmbedWithin(self, self.Width, cc.Height)
  cc.AddResponsiveLayout(12,6,4,3,2) //Optional if you want to specify columns
next

This loads in 6 containers in the open event. You can of course load in any number of Containers of different types in the open event. Just follow the same pattern: New up the container, call EmbedWithin(), and then call AddResponsiveLayout() - This is also where you would hook up any AddHandler events

@Brock_Nash so this means that you always need a container for responsive designs? Even for a very small login webDialog?

I typically don’t use more than one or two WebPages in any app. Everything is then containers within containers within containers. I found it’s the most efficient and gives the most control. But yeah, it isn’t super great from the WYSIWYG perspective.

But yeah you end up with essentially a container for every control. Usually with a label and the control and then use a bunch of AddHandler methods. Not elegant but achieves the responsive goal. Until Xojo comes up with something better I see this as the only real solution.

In another project I created a helper method that loops through the containers on a page and then uses a naming convention on the containers name to specify the columns. Example: MyContainer1R_12_6_4_3
And that way you can see the containers in the layout rather than having to Embed them constantly

1 Like

It does not seem to work when custom bootstrap theme (bootstrap.min.css) is added to the app. Does the custom theme needs any particular characteristic enabled?