B4J Question [BANano] multiple 'pages' without using router

Dave G

Active Member
Licensed User
I'm trying to figure out how to have multiple 'pages' like B4xPages or B4A activities without using BANano Router. The "B4X Getting Started Guide has instructions for Router with a comment "I personally do not use this in my PWA's. B4J has already so much organization of your code build-in with its classes and modules that I do not really need it. I simply put the code in a normal B4J class per page and load them when needed. By emptying the <body> tag and loading the new layout, I have the same effect.". I'd like to have static modules or classes for each 'page' that has its own layout and logic. Can't see a way to associate a Class/Module to a Layout and 'run' it.

Any help would be appreciated.
 

Dave G

Active Member
Licensed User
Will give a try. That didn't show up in any of my many searches.
Thanks for the info. That involves a lot of HTML and knowledge of HTML/CSS.

After looking at your example I was inspired to create a Single Page BANano app. I've created three layouts (main, page2, page3). Views in each have their page name embedded in the view name e.g. btnPage2DoSomething. Same with other views. I then use AD to create the variable reference for each view and any events in Main. So, when they switch to a new page is save off the information of the current page, restore any information for the new page and let events do their thing. Embedding the page name is for documentation. This isn't a solution for a large app, but for my Proof of Concept it's great as all of the code is in Main.
 
Upvote 0

alwaysbusy

Expert
Licensed User
Longtime User
This is a very simple example on how to organize your code as a multipagewith multiple classes, while transpiled it is a SPA.

main:
B4X:
Sub Process_Globals
    Private BANano As BANano 'ignore
    ' your logical pages
    Dim myPage1 As Page1
    Dim myPage2 As Page2
End Sub

Sub AppStart (Form1 As Form, Args() As String)
    ' With this little snippet, the new B4J 9.30 logs with jump are activated
    #if Debug
        ' MUST be literally this line if you want to use the B4J Logs jump to code feature!
        Log("BANanoLOGS")
    #End if
        
    ' some general settings like the name of your PWA
    BANano.Initialize("BANano", "BANanoMinimal",DateTime.Now)
    BANano.Header.Title="BANano Minimal"
    ' DateTime.Now is to make sure our app is reloaded on ReBuild
    BANano.JAVASCRIPT_NAME = "app" & DateTime.Now & ".js"
        
    ' some directives for the Tranpiler
    BANano.TranspilerOptions.MergeAllCSSFiles = True
    BANano.TranspilerOptions.MergeAllJavascriptFiles = True
    BANano.TranspilerOptions.RemoveDeadCode = True
    BANano.TranspilerOptions.ShowWarningDeadCode = True
    BANano.TranspilerOptions.EnableLiveCodeSwapping = True
    
    ' start the actual build
    BANano.Build(File.DirApp)
    
    ' stop running. We do not need the .jar file running anymore
    ' in release mode
    #if Release
        ExitApplication        
    #End if
End Sub

'Return true to allow the default exceptions handler to handle the uncaught exception.
Sub Application_Error (Error As Exception, StackTrace As String) As Boolean
    Return True
End Sub

' HERE STARTS YOUR APP
Sub BANano_Ready()
    ' initialize your pages
    myPage1.Initialize
    myPage2.Initialize
    
    ' load the first one
    myPage1.Load
End Sub

SharedData module:
B4X:
'Static code module
Sub Process_Globals
    Dim CurrentPage As String
        
    Dim Page1TextBox As String
    Dim Page2TextBox As String
End Sub
' saving the data on the page you are leaving
Public Sub SavePreviousPage()
    Select Case CurrentPage
        Case "Page1"
            Page1TextBox = Main.MyPage1.SKTextBox1.Text
        Case "Page2"
            Page2TextBox = Main.MyPage2.SKTextBox1.Text
    End Select    
End Sub
' loading the data previously saved
public Sub LoadThisPage()    
    Select Case CurrentPage
        Case "Page1"
            Main.MyPage1.SKTextBox1.Text = Page1TextBox
        Case "Page2"
            Main.MyPage2.SKTextBox1.Text = Page2TextBox
    End Select
End Sub

Page1 class with its Layout Page1. Note that its SKButton_Click event is raised right here in the class.
B4X:
Sub Class_Globals
    Dim BANano As BANano 'ignore
    Public SKButton1 As SKButton
    Public SKTextBox1 As SKTextBox
End Sub

'Initializes the object. You can add parameters to this method if needed.
Public Sub Initialize
    
End Sub

public Sub Load()
    SharedData.SavePreviousPage
    
    Dim body As BANanoElement
    body.Initialize("body")
    body.Empty
    
    body.LoadLayout("Page1")
    
    SharedData.CurrentPage = "Page1"
    SharedData.LoadThisPage
End Sub

Private Sub SKButton1_Click (event As BANanoEvent)
    Main.myPage2.Load
End Sub

Page2 class (same system)
B4X:
Sub Class_Globals
    Dim BANano As BANano 'ignore
    Public SKButton1 As SKButton
    Public SKTextBox1 As SKTextBox
End Sub

'Initializes the object. You can add parameters to this method if needed.
Public Sub Initialize
    
End Sub

public Sub Load()
    SharedData.SavePreviousPage
    
    Dim body As BANanoElement
    body.Initialize("body")
    body.Empty
    
    body.LoadLayout("Page2")
    
    SharedData.CurrentPage = "Page2"
    SharedData.LoadThisPage
End Sub

Private Sub SKButton1_Click (event As BANanoEvent)
    Main.myPage1.Load    
End Sub

I like doing it like this as all is well organized: every page it's own events, layout and logic, all data available in a shared module and main is still uncluthered.

Alwaysbusy
 
Upvote 0

Dave G

Active Member
Licensed User
This is a very simple example on how to organize your code as a multipagewith multiple classes, while transpiled it is a SPA.

main:
B4X:
Sub Process_Globals
    Private BANano As BANano 'ignore
    ' your logical pages
    Dim myPage1 As Page1
    Dim myPage2 As Page2
End Sub

Sub AppStart (Form1 As Form, Args() As String)
    ' With this little snippet, the new B4J 9.30 logs with jump are activated
    #if Debug
        ' MUST be literally this line if you want to use the B4J Logs jump to code feature!
        Log("BANanoLOGS")
    #End if
       
    ' some general settings like the name of your PWA
    BANano.Initialize("BANano", "BANanoMinimal",DateTime.Now)
    BANano.Header.Title="BANano Minimal"
    ' DateTime.Now is to make sure our app is reloaded on ReBuild
    BANano.JAVASCRIPT_NAME = "app" & DateTime.Now & ".js"
       
    ' some directives for the Tranpiler
    BANano.TranspilerOptions.MergeAllCSSFiles = True
    BANano.TranspilerOptions.MergeAllJavascriptFiles = True
    BANano.TranspilerOptions.RemoveDeadCode = True
    BANano.TranspilerOptions.ShowWarningDeadCode = True
    BANano.TranspilerOptions.EnableLiveCodeSwapping = True
   
    ' start the actual build
    BANano.Build(File.DirApp)
   
    ' stop running. We do not need the .jar file running anymore
    ' in release mode
    #if Release
        ExitApplication       
    #End if
End Sub

'Return true to allow the default exceptions handler to handle the uncaught exception.
Sub Application_Error (Error As Exception, StackTrace As String) As Boolean
    Return True
End Sub

' HERE STARTS YOUR APP
Sub BANano_Ready()
    ' initialize your pages
    myPage1.Initialize
    myPage2.Initialize
   
    ' load the first one
    myPage1.Load
End Sub

SharedData module:
B4X:
'Static code module
Sub Process_Globals
    Dim CurrentPage As String
       
    Dim Page1TextBox As String
    Dim Page2TextBox As String
End Sub
' saving the data on the page you are leaving
Public Sub SavePreviousPage()
    Select Case CurrentPage
        Case "Page1"
            Page1TextBox = Main.MyPage1.SKTextBox1.Text
        Case "Page2"
            Page2TextBox = Main.MyPage2.SKTextBox1.Text
    End Select   
End Sub
' loading the data previously saved
public Sub LoadThisPage()   
    Select Case CurrentPage
        Case "Page1"
            Main.MyPage1.SKTextBox1.Text = Page1TextBox
        Case "Page2"
            Main.MyPage2.SKTextBox1.Text = Page2TextBox
    End Select
End Sub

Page1 class with its Layout Page1. Note that its SKButton_Click event is raised right here in the class.
B4X:
Sub Class_Globals
    Dim BANano As BANano 'ignore
    Public SKButton1 As SKButton
    Public SKTextBox1 As SKTextBox
End Sub

'Initializes the object. You can add parameters to this method if needed.
Public Sub Initialize
   
End Sub

public Sub Load()
    SharedData.SavePreviousPage
   
    Dim body As BANanoElement
    body.Initialize("body")
    body.Empty
   
    body.LoadLayout("Page1")
   
    SharedData.CurrentPage = "Page1"
    SharedData.LoadThisPage
End Sub

Private Sub SKButton1_Click (event As BANanoEvent)
    Main.myPage2.Load
End Sub

Page2 class (same system)
B4X:
Sub Class_Globals
    Dim BANano As BANano 'ignore
    Public SKButton1 As SKButton
    Public SKTextBox1 As SKTextBox
End Sub

'Initializes the object. You can add parameters to this method if needed.
Public Sub Initialize
   
End Sub

public Sub Load()
    SharedData.SavePreviousPage
   
    Dim body As BANanoElement
    body.Initialize("body")
    body.Empty
   
    body.LoadLayout("Page2")
   
    SharedData.CurrentPage = "Page2"
    SharedData.LoadThisPage
End Sub

Private Sub SKButton1_Click (event As BANanoEvent)
    Main.myPage1.Load   
End Sub

I like doing it like this as all is well organized: every page it's own events, layout and logic, all data available in a shared module and main is still uncluthered.

Alwaysbusy
That's exactly what I was hoping for. Will give a try. Thanks a bunch.
 
Upvote 0

Dave G

Active Member
Licensed User
Was able to adapt it to my Proof of Concept (Main, Page 2, Page 3). So easy when you have a lot of help from your friends.

I really like BANano now that I've changed my way of thinking in order to operate in the world of DOM. It's really nice not to have to contend with the browser Back issues since BANano is in total control of navigation. I may save some values in LocalStorage, but like saving and restoring from the Shared module.

I'll mimic this in BVAD3 if possible. I've implemented a single page app in Xamarin, NSbasic, B4X xui (android and iOS), VueJS, BANano, and BVAD3 called Winch Calc (free on Google Play and Apple Store) as a Proof of Concept. I've also created a Client that get information from Server (SQL Server, SQLite) with the ability to return multiple tables to the client.

Will start posting my experience with all of the pieces and parts I've explored in the past 6-7 months here on the forum.

Thanks so much,

Dave G
 
Upvote 0

Mashiane

Expert
Licensed User
Longtime User
Wow, You know before I found b4x, by accident, I also used Nsbasic and enjoyed it too. Thanks to many google searches. I see they have changed their model to SAAS.
They also added more controls to work with Bootstrap and other stuff.

Will start posting my experience with all of the pieces and parts I've explored in the past 6-7 months here on the forum.
This should be interesting.

Have fun.
 
Upvote 0

Dave G

Active Member
Licensed User
Wow, You know before I found b4x, by accident, I also used Nsbasic and enjoyed it too. Thanks to many google searches. I see they have changed their model to SAAS.
They also added more controls to work with Bootstrap and other stuff.


This should be interesting.

Have fun.
Ya, I discovered NSbasic many years ago and implemented my Winch Calc app using it for Android. When PhoneGap went away NSbasic had to scurry to regroup because it relied on that for deployment. Around then I discovered B4X and never looked back.

BTW, thanks for all that you've contributed with BVAD3 etc. I'm working on a BVAD3 version of Winch Calc. Will try to take advantage of the Vue-based UI widgets.
 
Upvote 0

Dave G

Active Member
Licensed User
Update: reworked my router-less routing Proof of Concept. Patterned after B4X Pages with a Main that acts as the router and several class instances that manage their respective 'Page'. Instead of having Shared module maintain Page context if changed it to have each Page instance manage its own context. Works great.

I also solved the orientation change issue by creating a Landscape and Portrait layout and choosing the correct one when an orientation change occurs and it's advantageous to switch orientation e.g. on a phone. Turned out to be pretty easy. What's really interesting is that my PWA code that references layout Views such as TextBox or Label doesn't care which layout is being used as long as the layout variable match up e.g. txtWeight or lblStatus. The B4X code is matched up with the Layouts that exist in the DOM without any HTML, JavaScript or CSS! I will document all that I've learned in the past couple of months with B4X (BANano/BVAD) and Vue.JS shortly.
 
Upvote 0

toby

Well-Known Member
Licensed User
Longtime User
Patterned after B4X Pages with a Main that acts as the router and several class instances that manage their respective 'Page'. Instead of having Shared module maintain Page context if changed it to have each Page instance manage its own context. Works great.
That's neat, could you be kind enough to share those pieces of code?
 
Upvote 0
Top