B4J Library [BANanoVueMaterial]: The first complete opensource VueJS UX based framework for BANano

*START OF NOTICE

As of 02 FEB 2021, this project is is no longer maintained as it has given birth to BVAD3.

This project was a joy to create, however like everything that has a start and an end, its time to move on and evolve. BVAD3 is faster, more simpler to implement and takes advantage of the Abstract Designer use.

Subscribe to Telegram Channel

[BANanoVuetifyAD] Vuetify WebSites & WebApps with BANano for Dummies

Ahoy!!!

*END OF NOTICE


UPDATE 24 October 2020: The recommended methodology to create BANanoVuetify WebApp is being discussed here:
MealPrep. This covers most of what VueJS + Vuetify is all about in terms of the internals.

Whilst you can use the designer to create your UX, you need to separate your concerns when creating the app just like its done on the MealPrep by using components and routers for the pages.

DO NOT FOLLOW THE APPROACH USED IN CREATING THE BANANOVUEMATERIALDEMO WHEN CREATING YOUR APPS. THAT METHOD IS NO LONGER FEASIBLE.


Download

BANanoVuetifyAD - Prelease Playlist on Youtube
BANanoVueMaterial (Vuetify) Playlist on Youtube

2020-05-20 Update: Important Update

BANanoVueMaterial Designer Usage - Mock.Compile.Publish

BANanoVueMaterialCore (pure vuetify without extensions)

Exploring Components & Router Basics

How to ask questions, request help, report bugs and request enhancements + Telegram Channel

Thanks to everyone who has been playing with this and highlighting issues and requesting features. You are stars!

*** IMPORTANT: Migrating to the new version

Word. Moving from VueMaterial to Vuetify was inevitable and whilst both are Vue Material based frameworks, Vuetify has more strengths. If if was going to be possible, we would not be having a migration guide, however things changed and enhancements happened and some code rewrites took place. When doing the transition from the VueMaterial to Vuetify codebases, we tried to make the code transition to be as smooth as possible, thus our migration guide is as small as possible. We did not want to dictate how to use the lib, so we removed some things that were hard coded and fixed. This was specific to the side drawer. To test the migration, the old examples were converted to new examples (see below) and all of them work.

BANanoVueMaterial is complete open source, so this means you can use it to your hearts content and adjust it and make it your own. If you enhance, send us word, we will merge. Make the code simple and comment it as much as you can. I cannot over-emphasize that Vuetify is LARGE, so check their website on how components are created and used to learn stuff. Do enjoy. TheMash. #IAmLovingThis

BANanoVuetify (recommended for new projects & migration notes attached)

You can track our progress from here. All the components that we got from VueMaterial exists in Vuetify and more!!!

  • Copy all the files in the 1. External Libraries folder to your B4J external libraries folder
  • If you want to explore the BANanoVuetify source code, open and run the project in 2. Library
  • If you want to explore all the components in this version, open and run the project in 3. Demo
  • You can also explore other specific examples from the 4. Examples folder
Live Preview



Tutorials (New)

Mock.Compile.Publish


NB: Download and Import the Project Components files for the Expense Tracker here.

1. Expense Tracker with BANanoSQL


Expense Tracker Part 1
Expense Tracker Part 2
Expense Tracker Part 3
Expense Tracker Part 4
Preparations for Part 5
Expense Tracker Part 5.1
Expense Tracker Part 5.2

2. Expense Tracker with SQLite (you need to understand all of 1. Expense Tracker with BANanoSQL first!)

Making your app use SQLite as a backend
Mock.Compile.Publish Expense Tracker with SQLite as BackEnd Full Implementation

3. Expenses Tracker with MSSQL (you need to understand all of 1. & 2. above first!)

Mock.Compile.Publish Expense Tracker with MSSQL as BackEnd

4. Expense Tracker with MySQL (you need to understand all of 1. - 3. above first)

Mock.Compile.Publish Expense Tracker with MySQL as BackEnd

NEW NEW NEW!!!! Handling Events

Developing a grid with the Designer
Developing forms with the Designer
Designing text field controls with the Designer
Designing text area controls with the Designer
Designing password controls with the Designer
Designing images with the Designer
Designing file input with the Designer
Designing buttons with the Designer
Designing checkboxes with the Designer
Designing switches with the Designer
Designing icons with Designer
Designing labels with Designer
Designing sliders with the Designer
Designing select, combo and autocomplete with the Designer
Designing radio boxes with the Designer
Designing date & time pickers with the Designer (NB: functionality works on your app)
Designing a parallax with the Designer
Designing a container with the Designer
Designing the appbar, toolbars and systembar with the Designer - Part 1
Designing the appbar, toolbars and systembar with the Designer - Part 2
Drag n Drop Menu - Part 1
Drag n Drop Menu - Part 2
Drag n Drop Carousel
Drag n Drop Dialog
Drag n Drop Rating
Drag n Drop SpeedDial
DataTable multi selects
SetFocus(?)
Invisible File Selector
DataTable GetItemKeys
Drag n Drop Chips
Drag n Drop Badges
Drag n Drop Avatars
Exporting Component Schemas (Multi Development Mode)
Importing Component Schemas (Multi Development Mode)
Drag n Drop Lists
Drag n Drop Tabs
Drag n Drop Stepper
Drag n Drop ExpansionPanels (Accordion)
Drag n Drop Page
Setting Project Properties
Reading Text files (without upload to server)
Reading Excel files (without upload to server)

Reporting (New)

Excel Client Side Reporting with OXML

Example Projects

Hello World
Navigation (1 or more pages using v-show directive)
Login Screen
User Registration Screen
Expenses.Show - MySQL+PHP+ChartKick CRUD
Form Utilities - BANanoSQL CRUD
Calculations - using watch directives

IMPORTANT: Asking Questions about BANanoVueMaterial

1. Please do not ask questions on this thread as this is about updates and new developments about BANanoVueMaterial.
2. When asking a question, please use the B4J Forum and prefix your question with [BANanoVueMaterial] Your Question
3. As the author of this lib, I would recommend that in the content of your question you also address it to myself with @Mashiane (this will also help me find and attend to your questions faster as it will show in my personal notifications)

Related Content

BANanoVue - a now updated CORE of BANanoVueMaterial
BANanoWired - a mockup framework build on BANanoVue (WIP)
BANanoPDFDesign - a creation based on BANanoVueMaterial for PDF reporting (WIP)
BANanoVMDesign - this intends to support BANanoVueMaterial design philosophy. (WIP)

Have fun and enjoy!

PS: BANanoVueMaterial uses an updated version of the BANanoPostProcessor library done by Kiffi.
 
Last edited:

Mashiane

Expert
Licensed User
Longtime User
Update: 2020-03-15

This code is based on the old BANanoVueMaterial (based on VueMaterial) version. A new version exists based on Vuetify. The new version based examples exist from
this thread.

Download

Live Preview

Blank BANanoVueMaterial Project Template to use for own projects

It is with pleasure to release the first VueJS based framework for BANano to create your apps. A demo is attached in the repo that will take you through the code on how things get done. The Vue in BVM (BANanoVueMaterial) can be explained by this introduction.

View in HD.

During the course of time we will develop some nice database based apps with this.

VueMaterial is available from this link.

Hello BANanoVueMaterial



In our first example we create a page (use a code module), that will show only when we want. This is based on the v-show method of vuejs. For all our pages, we create different modules and then link these to the body of the page in the pgIndex module InitSections method.

InitSections ensures that the complete template of the vuejs app is built. ie. the HTML

We give each code module a name so that its different from another. In this case, hellocode

Steps

1. In Main, let's set up our app. Everything in our App will happen in pgIndex(code module)


B4X:
#Region Project Attributes
    #MergeLibraries: True
    #LibraryAuthor: Anele Mashy Mbanga
    #LibraryVersion: 0.01
#End Region

Sub Process_Globals
    Public BANano As BANano 'ignore
    Public AppName As String = "helloworld"
    Public Dbase As String
    Private Publish As String
    Private BP As BANanoPostProcessor
    Public ServerIP As String
End Sub

Sub AppStart (Form1 As Form, Args() As String)
    'post processor
    BP.Initialize
    BP.RedirectOutput(File.DirApp,"log.txt")
    Publish = "C:\laragon\www"
    'ServerIP = BP.FileReadString(File.DirAssets, "host.txt")
    'Dbase = BP.FileReadString(File.DirAssets, "dbase.txt")
    '
    Dim Version As Long = DateTime.now
    Dim appFile As String = $"app${Version}.js"$
 
    'initialize banano for first use
    BANano.Initialize("BANano", AppName, Version)
    BANano.HTML_NAME = "index.html"
    BANano.Header.Title = AppName
    BANano.JAVASCRIPT_NAME = appFile
    BANano.TranspilerOptions.UseServiceWorker = False
    BANano.transpileroptions.MergeAllCSSFiles = True
    BANano.transpileroptions.MergeAllJavascriptFiles = True
    '
    'php
    'set php settings
    'BANano.PHP_NAME = $"${AppName}.php"$
    'BANano.PHPHost = $"http://${ServerIP}/${AppName}/"$
    'BANano.PHPAddHeader("Access-Control-Allow-Origin: *")
 
    BANano.Build(Publish)
    BP.OpenLog(File.DirApp, "log.txt")
 
    BP.PublishPath = Publish
    BP.ShortName = AppName
    BP.AssetsPath = BANano.ASSETS_FOLDER
    BP.ScriptsPath = BANano.SCRIPTS_FOLDER
    BP.StylesPath = BANano.STYLES_FOLDER
    BP.ScriptFile = BANano.JAVASCRIPT_NAME
    BP.UnzipFonts
    BP.Open(True)
    ExitApplication
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

Sub BANano_Ready
    pgIndex.Init
End Sub

2. In pgIndex (code module), lets create the structure of our app. We want our app to have a navigation bar and no drawer in this instance. You do this with .Show / .Hide method calls. We then add all the different 'pages' of our app in InitSections. Each time we want to show a different page we call .ShowSection

B4X:
'Static code module
Sub Process_Globals
    Private BANano As BANano  'ignore
    Private vm As BANanoVM
    Private sections As List
End Sub

Sub Init
    'initialize the page
    vm.Initialize(Me, Main.appname)
    'update the nav bar title
    vm.NavBar.UpdateTitle("Hello World")
    vm.Drawer.UpdateTitle("Hello")
    vm.Drawer.SetPersistentFull(True)
    'the drawer will be visible (not)
    vm.Drawer.Hide
    'the navbar will be visible
    vm.NavBar.Show
    'set primary color for the navbar
    vm.NavBar.SetPrimary(True)
    'fix the navbar so that it does not move
    vm.NavBar.SetModeFixed(True)
    'hide the back button
    vm.NavBar.SetHasBackButton(False)
    'show the hamburger button
    vm.NavBar.SetHasMenuButton(False)
    '
    'BuildDrawer
 
    'add the code from the modules
    InitSections
    'show the initial page
    ShowSection(modHello.name)
    'build the page
    vm.ux
End Sub

'build list once and for all for all pages
Sub InitSections
    sections.initialize
    '
    sections.add(modHello.name)
    modHello.Code(vm)
 
End Sub

'show 1 section from available sections
Sub ShowSection(sectionName As String)
    For Each section As String In sections
        If section = sectionName Then
            vm.show(section)
        Else
            vm.hide(section)
        End If
    Next
End Sub


Sub BuildDrawer
    'vm.Drawer.AddItem("ui","whatshot","UI Elements")
    'vm.drawer.AddSubItem("ui", "avatar", "person_outline","Avatar")
End Sub

3. modHello page. Here we create our page. For now this defines the grid structure of our page and adds some labels. All this does it to build the HTML content of the page which is passed to the Vue instance to be rendered.

B4X:
'Static code module
Sub Process_Globals
    Private vm As BANanoVM
    Public name As String = "hellocode"
End Sub


Sub Code(vmx As BANanoVM)
    'the instance of view material
    vm = vmx
    'create a container to hold all contents for this page
    Dim cont As VMContainer = vm.CreateContainer(name, Me)
    'hide this container, will be made available when we need
    cont.Hide
 
    '
    cont.addrows(1).AddColumns12
    cont.AddRows(1).AddColumns(1,12,1,1,1).AddColumns(1,12,11,11,11)
    cont.AddRows(1).AddColumns(1,12,2,2,2).AddColumns(1,12,10,10,10)
    cont.AddRows(1).AddColumns(1,12,3,3,3).AddColumns(1,12,9,9,9)
    cont.AddRows(1).AddColumns(1,12,4,4,4).AddColumns(1,12,8,8,8)
    cont.AddRows(1).AddColumns(1,12,5,5,5).AddColumns(1,12,7,7,7)
    cont.AddRows(1).AddColumns(1,12,6,6,6).AddColumns(1,12,6,6,6)
    cont.AddRows(1).AddColumns3_4
    cont.AddRows(1).AddColumns4_3
    '
    Dim rCnt As Int
 
    For rCnt = 1 To 9
        cont.Grid.SetBorder(rCnt,1,"1px", vm.COLOR_BLUEGREY, vm.BORDER_DOTTED)
        cont.Grid.SetBorder(rCnt,2,"1px", vm.COLOR_BLUEGREY, vm.BORDER_DOTTED)
        cont.Grid.SetBorder(rCnt,3,"1px", vm.COLOR_BLUEGREY, vm.BORDER_DOTTED)
        '
        Dim rkey As String = $"lbl${rCnt}1"$
        Dim lblx As VMLabel = vm.CreateLABEL(rkey).SetText($"R${rCnt}.C${1}"$).SetParagraph
        cont.AddComponent(rCnt,1, lblx.ToString)
        '
        Dim rkey1 As String = $"lbl${rCnt}2"$
        Dim lblx1 As VMLabel = vm.CreateLABEL(rkey1).SetText($"R${rCnt}.C2"$).SetParagraph
        cont.AddComponent(rCnt,2, lblx1.ToString)

    Next
 
    '
    'add this container to the contents of the page
    vm.AddHTML(cont.tostring)
End Sub

To link the code to the main page, just update InitSections with the code modules.

B4X:
sections.add(modHello.name)
    modHello.Code(vm)

What is important also here is this piece of code.

B4X:
'hide this container, will be made available when we need
    cont.Hide

This means that the v-show directive for this container is false and will be true when we run .Show.

As we want to show this particular page when we start, with other pages in the app, we run

B4X:
'show the initial page
    ShowSection(modHello.name)

In pgIndex to ensure that we have a start page.

The result of this exercise is..

grid.png


NB: BANanoVueMaterial uses the Bootstrap grid system. Only the grid functionality of Bootstrap was extracted to achieve this and not the complete library. This is the bootstrapgrid.css Style file inside the library. You can read more about the bootstrap grid here.

As you have noted, we added components to the grid by passing their HTML structure by using .ToString as depicted below.

B4X:
cont.AddComponent(rCnt,1, lblx.ToString)

This specifies the Row, then Column then the HTML content of the component to add.

The HTML results of cont.Tostring are:

HTML:
<div id="hellocode" ref="hellocode" :required="hellocoderequired" v-show="hellocodeshow" :disabled="hellocodedisabled">
    <div id="hellocodegrid" ref="hellocodegrid" :required="hellocodegridrequired" v-show="hellocodegridshow"
        :disabled="hellocodegriddisabled">
        <div id="hellocodegridr1" class="row">
            <div id="hellocodegridr1c1" class="col col-sm-12 col-md-12 col-lg-12 col-xl-12"
                style="border-style:dotted; border-width:1px; border-color:blue-grey;">
                <p id="lbl11" ref="lbl11" :required="lbl11required" v-show="lbl11show" :disabled="lbl11disabled">R1.C1
                </p>
            </div>
        </div>
        <div id="hellocodegridr2" class="row">
            <div id="hellocodegridr2c1" class="col col-sm-12 col-md-1 col-lg-1 col-xl-1"
                style="border-style:dotted; border-width:1px; border-color:blue-grey;">
                <p id="lbl21" ref="lbl21" :required="lbl21required" v-show="lbl21show" :disabled="lbl21disabled">R2.C1
                </p>
            </div>
            <div id="hellocodegridr2c2" class="col col-sm-12 col-md-11 col-lg-11 col-xl-11"
                style="border-style:dotted; border-width:1px; border-color:blue-grey;">
                <p id="lbl22" ref="lbl22" :required="lbl22required" v-show="lbl22show" :disabled="lbl22disabled">R2.C2
                </p>
            </div>
        </div>
        <div id="hellocodegridr3" class="row">
            <div id="hellocodegridr3c1" class="col col-sm-12 col-md-2 col-lg-2 col-xl-2"
                style="border-style:dotted; border-width:1px; border-color:blue-grey;">
                <p id="lbl31" ref="lbl31" :required="lbl31required" v-show="lbl31show" :disabled="lbl31disabled">R3.C1
                </p>
            </div>
            <div id="hellocodegridr3c2" class="col col-sm-12 col-md-10 col-lg-10 col-xl-10"
                style="border-style:dotted; border-width:1px; border-color:blue-grey;">
                <p id="lbl32" ref="lbl32" :required="lbl32required" v-show="lbl32show" :disabled="lbl32disabled">R3.C2
                </p>
            </div>
        </div>
        <div id="hellocodegridr4" class="row">
            <div id="hellocodegridr4c1" class="col col-sm-12 col-md-3 col-lg-3 col-xl-3"
                style="border-style:dotted; border-width:1px; border-color:blue-grey;">
                <p id="lbl41" ref="lbl41" :required="lbl41required" v-show="lbl41show" :disabled="lbl41disabled">R4.C1
                </p>
            </div>
            <div id="hellocodegridr4c2" class="col col-sm-12 col-md-9 col-lg-9 col-xl-9"
                style="border-style:dotted; border-width:1px; border-color:blue-grey;">
                <p id="lbl42" ref="lbl42" :required="lbl42required" v-show="lbl42show" :disabled="lbl42disabled">R4.C2
                </p>
            </div>
        </div>
        <div id="hellocodegridr5" class="row">
            <div id="hellocodegridr5c1" class="col col-sm-12 col-md-4 col-lg-4 col-xl-4"
                style="border-style:dotted; border-width:1px; border-color:blue-grey;">
                <p id="lbl51" ref="lbl51" :required="lbl51required" v-show="lbl51show" :disabled="lbl51disabled">R5.C1
                </p>
            </div>
            <div id="hellocodegridr5c2" class="col col-sm-12 col-md-8 col-lg-8 col-xl-8"
                style="border-style:dotted; border-width:1px; border-color:blue-grey;">
                <p id="lbl52" ref="lbl52" :required="lbl52required" v-show="lbl52show" :disabled="lbl52disabled">R5.C2
                </p>
            </div>
        </div>
        <div id="hellocodegridr6" class="row">
            <div id="hellocodegridr6c1" class="col col-sm-12 col-md-5 col-lg-5 col-xl-5"
                style="border-style:dotted; border-width:1px; border-color:blue-grey;">
                <p id="lbl61" ref="lbl61" :required="lbl61required" v-show="lbl61show" :disabled="lbl61disabled">R6.C1
                </p>
            </div>
            <div id="hellocodegridr6c2" class="col col-sm-12 col-md-7 col-lg-7 col-xl-7"
                style="border-style:dotted; border-width:1px; border-color:blue-grey;">
                <p id="lbl62" ref="lbl62" :required="lbl62required" v-show="lbl62show" :disabled="lbl62disabled">R6.C2
                </p>
            </div>
        </div>
        <div id="hellocodegridr7" class="row">
            <div id="hellocodegridr7c1" class="col col-sm-12 col-md-6 col-lg-6 col-xl-6"
                style="border-style:dotted; border-width:1px; border-color:blue-grey;">
                <p id="lbl71" ref="lbl71" :required="lbl71required" v-show="lbl71show" :disabled="lbl71disabled">R7.C1
                </p>
            </div>
            <div id="hellocodegridr7c2" class="col col-sm-12 col-md-6 col-lg-6 col-xl-6"
                style="border-style:dotted; border-width:1px; border-color:blue-grey;">
                <p id="lbl72" ref="lbl72" :required="lbl72required" v-show="lbl72show" :disabled="lbl72disabled">R7.C2
                </p>
            </div>
        </div>
        <div id="hellocodegridr8" class="row">
            <div id="hellocodegridr8c1" class="col col-sm-12 col-md-4 col-lg-4 col-xl-4"
                style="border-style:dotted; border-width:1px; border-color:blue-grey;">
                <p id="lbl81" ref="lbl81" :required="lbl81required" v-show="lbl81show" :disabled="lbl81disabled">R8.C1
                </p>
            </div>
            <div id="hellocodegridr8c2" class="col col-sm-12 col-md-4 col-lg-4 col-xl-4"
                style="border-style:dotted; border-width:1px; border-color:blue-grey;">
                <p id="lbl82" ref="lbl82" :required="lbl82required" v-show="lbl82show" :disabled="lbl82disabled">R8.C2
                </p>
            </div>
            <div id="hellocodegridr8c3" class="col col-sm-12 col-md-4 col-lg-4 col-xl-4"
                style="border-style:dotted; border-width:1px; border-color:blue-grey;"></div>
        </div>
        <div id="hellocodegridr9" class="row">
            <div id="hellocodegridr9c1" class="col col-sm-12 col-md-3 col-lg-3 col-xl-3"
                style="border-style:dotted; border-width:1px; border-color:blue-grey;">
                <p id="lbl91" ref="lbl91" :required="lbl91required" v-show="lbl91show" :disabled="lbl91disabled">R9.C1
                </p>
            </div>
            <div id="hellocodegridr9c2" class="col col-sm-12 col-md-3 col-lg-3 col-xl-3"
                style="border-style:dotted; border-width:1px; border-color:blue-grey;">
                <p id="lbl92" ref="lbl92" :required="lbl92required" v-show="lbl92show" :disabled="lbl92disabled">R9.C2
                </p>
            </div>
            <div id="hellocodegridr9c3" class="col col-sm-12 col-md-3 col-lg-3 col-xl-3"
                style="border-style:dotted; border-width:1px; border-color:blue-grey;"></div>
            <div id="hellocodegridr9c4" class="col col-sm-12 col-md-3 col-lg-3 col-xl-3"></div>
        </div>
    </div>
</div>

That concludes our exercise 1.
 
Last edited:

Mashiane

Expert
Licensed User
Longtime User
Navigation between different pages

BVMDrawer.gif


In this exercise we are going to create two pages and navigate between them. We will use.

1. The drawer
2. The navigation bar
3. Clicking a button on a page to go to another.

Let's create the drawer.

We just need to ensure that this is visible and then add links to it. These links do not have children like our demo.

B4X:
vm.Drawer.Show
    vm.Drawer.AddItem("page1","done", "Page 1")
    vm.Drawer.AddItem("page2","done_all", "Page 2")

For each item, we have a key, this will be linked to a key_click event, an icon (material design icons) and the label of the link. To ensure that there are events linked to the items, we create the events and then write code for the events.

Here we have also created some navbar buttons that we will show or hide on demand.

B4X:
Sub page1_click(e As BANanoEvent)
    'update the title of the navigation bar
    vm.navbar.UpdateTitle("Navigation - Page 1")
    'show page 1
    vm.showpage(modPage1.name)
    'hide the navbar button
    vm.Hide("npage1")
    'show the navbar button
    vm.Show("npage2")
End Sub

Sub page2_click(e As BANanoEvent)
    'update the title of the navigation bar
    vm.navbar.UpdateTitle("Navigation - Page 2")
    'show page 2
    vm.showpage(modPage2.name)
    vm.Show("npage1")
    vm.Hide("npage2")
End Sub

So when we click page1 on the drawer items, it will fire page1_click. This updates the navbar title, show the page1, hide the navbar button for page 1 and shows the navbar button for page 2.

When executed, we have a seamless execution as depicted in the gif above. Let's now look at the code for the navbar.
 

Mashiane

Expert
Licensed User
Longtime User
Navigation between different pages : continued

Let's explore the navigation bar buttons.

BVMNavBar.gif


The navbar sits on the top section of the page (blue here)

Also just like the drawer, we need to set its .Show method to show it. To make it invisible one can .Hide it.

B4X:
'the navbar will be visible
    vm.NavBar.Show
    'set primary color for the navbar
    vm.NavBar.SetPrimary(True)
    'fix the navbar so that it does not move
    vm.NavBar.SetModeFixed(True)
    'hide the back button
    vm.NavBar.SetHasBackButton(False)
    'show the hamburger button
    vm.NavBar.SetHasMenuButton(True)
    'add buttons
    vm.NavBar.AddIcon("npage1","done","Go to page 1", "")
    vm.NavBar.AddIcon("npage2","done_all","Go to page 2", "")

So in the code above, we show it. We then set its color to primary with .SetPrimary. We want it to be fixed on the top (this means it wont scroll when the page is scrolled).
We dont want to show a back button on it but want to show the hamburger menu, thus .SetHasMenuButton(true).

We then add buttons to the right section of the navbar. We give these npage1 and npage2, with icons and tooltips. These are icon buttons.

NB: For more details about navbar items see the demo on the "Toolbar".

So again, the events that are linked here are npage1_click and npage2_click. We create the subs for them and write code to be executed,

B4X:
Sub npage1_click(e As BANanoEvent)
    vm.navbar.UpdateTitle("Navigation - Page 1")
    vm.ShowPage(modPage1.name)
    vm.Show("npage2")
    vm.Hide("npage1")
End Sub

Sub npage2_click(e As BANanoEvent)
    vm.navbar.UpdateTitle("Navigation - Page 2")
    vm.ShowPage(modPage2.name)
    vm.Show("npage1")
    vm.Hide("npage2")
End Sub

When npage1 is clicked, the other navbar button should be shown and the current one clicked hidden. Again we see here, we update the navbar title, show the page we want etc,
 

Mashiane

Expert
Licensed User
Longtime User
Navigation between different pages : continued

Let's explore the code in the 2 pages

Here we create 2 (code modules) and add code to them including the events that need to be run on button clicks. Simply put, We create a page with a 6x2 grid.
In one side of the grid we add a label and then on the other side we add a button. When the button is clicked, an event is fired so that code that is respective to that button is executed.

BVMPages.gif


NB: You might have noted that now instead of the sections code in the previous example we have .AddPage and .ShowPage code methods of the vm instance. We just decided to simplify the code.

After we have finished our code, we need to add it to the master template for each page in pgIndex.

NB: Its compulsory that if you use .AddPage and .ShowPage, there is a sub called Code in your module. This is compulsory.

In pgIndex.Init, lets add the pages we will use in the app. Each page will be hidden until shown. We also do every init we need to do.

B4X:
'add the code from the modules
    vm.AddPage(modPage1.name, modPage1)
    vm.addpage(modPage2.name, modPage2)
    'show this page
    vm.navbar.UpdateTitle("Navigation - Page 1")
    vm.ShowPage(modPage1.name)
    vm.Hide("npage1")
    vm.Show("npage2")

We add the page code, we update the navbar title, we then show page1, hide one of the navbar buttons and show another.

Page1 and Pag2 code similarity.

As this is just a simple example, we just create a label and a button. We are trying to generate HTML here and nothing else and also add the events for any component that needs an event.

B4X:
'create the grid for the container in the page
    cont.AddRows(1).AddColumns2_6
    ' create a H1 label
    Dim lbl As VMLabel = vm.CreateLABEL("lbl1").SetText("This is page 1!").SetH1
    'create button
    Dim btn As VMButton = vm.CreateButton("btn0", Me).SetText("Page 2").SetPrimary(True).SetRaised(True).SetToolTip("Go to page 2")
    'add label to R1C1
    cont.AddComponent(1,1, lbl.ToString)
    'add button to r1c2
    cont.AddComponent(1,2, btn.ToString)

1. We create a container with 1 row and 2 equal sized columns.
2. We create a label and then create a button

NB: Because all these components will be in one page, ensure that your component ids are not the same. This is a SPA, ids should be different.

3. We add both the label at the positions we need them to be, label at 1,1 and button at 1,2.

4. We then add code for the button so that when clicked it executes something.

B4X:
Sub btn0_click(e As BANanoEvent)
    vm.navbar.UpdateTitle("Navigation - Page 2")
    vm.ShowPage(modPage2.name)
    vm.Show("npage1")
    vm.Hide("npage2")
End Sub

Out button id is btn0, then our event will be btn0_click. We write the code to execute when that is done. If you look at the code for page 2 its similar but a slight different.

Summary

  • With this example, we have explored how to add buttons to the drawer and then link events to them including the code to be fired when such links are clicked. See how the drawer in the BVMDemo example was created for more details.
  • We also looked at adding navigation bar buttons and how to hide and how these on demand.
  • We created 2 pages using code modules, added a label and button in each, created events for each button in the modules and linked the code.
This covers how navigation works for the Drawer, Navigation Bar, internal pages. For more details explore the BVMDemo source code.

Ta.

NB: Updated code in the github repo.
 

Mashiane

Expert
Licensed User
Longtime User
Creating a Modal Login / Sign In Screen

BVMSignIn.gif


In the example 3, we look at how one can create a login screen. For this exercise we will look at some form controls. These are:

1. Input (email input type)
2. Input (password input type)
3. We will add action buttons to our modal and link events to them

We will validate these controls to ensure that there is content entered. The password control has a 'show password' icon when clicked one is able to view the password.
We have added icons to prefix the input controls. For more details about the input controls, see the BVMDemo source code.

When our app starts we want to show a login modal. As noted for his we do not have a navbar or drawer. This means we have to hide them using .Hide. We create the modal form in its own module and then show it using .ShowDialog(?)

When we define the controls, we give them unique ids e.g. email and password. These ids are used to also set the v-model directives for the controls. This means we can then read the contents back by reading the state of those input controls.

1. Create the master page and then hide the navbar and drawer and then add the modal code relevant.

B4X:
Sub Init
    'initialize the page
    vm.Initialize(Me, Main.appname)
    'update the nav bar title
    vm.NavBar.UpdateTitle("Login Dialog")
    vm.Drawer.UpdateTitle("Login")
    vm.Drawer.SetPersistentFull(True)
    'the navbar will be hidden
    vm.NavBar.Hide
    'set primary color for the navbar
    vm.NavBar.SetPrimary(True)
    'fix the navbar so that it does not move
    vm.NavBar.SetModeFixed(True)
    'hide the back button
    vm.NavBar.SetHasBackButton(False)
    'show the hamburger button
    vm.NavBar.SetHasMenuButton(False)
    
    'add the drawer items
    'the drawer will be visible (not)
    vm.Drawer.Hide
    'add the code from the modules
    vm.AddPage(pgLogin.name, pgLogin)
    'show the dialog when page opens
    vm.ShowDialog("mdlsignin")
    'build the page
    vm.ux
End Sub

Let's look at the modal code in the module.

1. We define the dialog in process globals as we will access it later on.

B4X:
Private mdlSignIn As VMDialog

2. Then we define the structure of our modal dialog and the input controls we will use etc.

B4X:
Sub Code(vmx As BANanoVM)
    'the instance of view material
    vm = vmx
    'create the modal dialog
    mdlSignIn = vm.CreateDialog("mdlsignin", Me)
    'dont show the backdrop
    mdlSignIn.SetBackdrop(False)
    'disable clicking outside of modal
    mdlSignIn.SetClickOutsideToClose(False)
    'dont close when a user presses escape
    mdlSignIn.SetCloseOnEsc(False)
    'on cellphones show full screen
    mdlSignIn.SetFullScreen(True)
    'set width of the modal
    mdlSignIn.SetWidth("600px")
    '
    'set the title of the modal
    mdlSignIn.SetTitle("Sign In")
    'add a cancel button
    mdlSignIn.AddCancel("btnCancelLogin", "Cancel")
    'add a login button
    mdlSignIn.AddOk("btnOkSignIn", "Sign In")
    'create the controls
    Dim txtEmail As VMInputControl = vm.Container.NewEmail("email","Email Address","",True,"email","Enter email address here", "The email address is required!")
    Dim txtPassword As VMInputControl = vm.container.NewPassword("password","Password","",True,"lock",10,"Enter password here","The password is required!")
    'add the controls, the grid will be automatically created
    mdlSignIn.Container.AddControl(txtEmail,1,1,0,0,0,0,12,12,12,12)
    mdlSignIn.Container.AddControl(txtPassword,1,1,0,0,0,0,12,12,12,12)
    
    'add this modal to the page
    vm.adddialog(mdlSignIn)
End Sub

The way we have defined our components here by default leaves out the possibility of us defining the grid 'first'. As soon we we run the .AddControl method, this expects the row, column, offsets and sizes of the RC co-ordinates and BANanoVueMaterial will generate a grid automatically based on the options you provide.

B4X:
 mdlSignIn.Container.AddControl(txtEmail,1,1,0,0,0,0,12,12,12,12)

    mdlSignIn.Container.AddControl(txtPassword,1,1,0,0,0,0,12,12,12,12)

3. When done, designing the modal dialog, we want to add it to the master page. We call .AddDialog

4.
We added btnCancelLogin and btnOkSignIn, these are then linked to their respective click events. When clicked, we want the login contents to be read, validated (if not blank) and then further processing will be done.

B4X:
Sub btnOkSignIn_click(e As BANanoEvent)
    'get the contents of the form
    Dim rec As Map = mdlSignIn.Container.GetData
    'validate the details
    Dim bValid As Boolean = mdlSignIn.Container.Validate(rec)
    If bValid = False Then Return
    Log(rec)
    'process further
End Sub

The returned map object of this exercise is the 'email' and 'password' field data entered by the end user. The dialog container has a .GetData method that based on the design we added controls with using the .AddControl method, that helps to get the contents of the page. Because there is some data that is required on the controls, we need to run the .Validate method of the container. If data is valid we continue processing else we exit.

Ta!

NB: BANanoVueMaterial was updated to version 2.01, example 3 attached on the github repo.
 

Mashiane

Expert
Licensed User
Longtime User
Creating a user Registration Dialog (showcasing most form controls)

In this example we continue from the previous login dialog. We add a Register button on the login screen and then. When that is selected we open the register dialog and hide the sign in dialog.

This SignUp dialog is to showcase most form controls that one can use. We follow the same shortcuts here to add the controls to the page. We however split the page into 2x6 grid as there are a lot of controls on the page. This gid has been shortened due to the file size.

BVMSignUp.gif


We create a pgSignUp (code module), add it to the master page and keep it hidden. Only when Register is clicked that its shown.

We have also extended the login form with a Remember Me, checkbox.

We create all the necessary controls we need and place them at right locations needed.

B4X:
Dim txtfirstname As VMInputControl = vm.Container.NewText("firstname", "First Name", "First Name", True, "", 0, "", "The first name is required!", 0)
    Dim txtlastname As VMInputControl = vm.Container.NewText("lastname", "Last Name", "Last Name", True, "", 0, "", "The last name is required!", 0)
    '
    Dim dpDOB As VMInputControl = vm.Container.NewDatePicker("dateofbirth", "Date of Birth", True, True, True, "Date of Birth",0)
    Dim tpTOB As VMInputControl = vm.Container.NewTimePicker("timeofbirth", "Time of Birth", True, True, "", "",0)
    '
    Dim txtTel As VMInputControl = vm.Container.NewTel("telephone", "Telephone", "Telephone Number", True, "", "", "",0)
    Dim txtEmail As VMInputControl = vm.Container.NewEmail("email","Email Address","Email Address",True,"","", "The email address is required!",0)
    '
    Dim radGender As VMInputControl = vm.Container.NewRadioGroup("gender", "Gender", "M", CreateMap("M":"Male","F":"Female"),0)
    Dim chipSkills As VMInputControl = vm.Container.NewChips("skills", "Skills", "", False, False, "","", 0)
    '
    Dim children As VMInputControl = vm.Container.NewNumber("children", "Total Children", "", False, "", "","", 0)
    Dim notifications As VMInputControl = vm.Container.NewSwitch("notifications", "Receive Notifications", "true", True, 0)
    '
    Dim profilepic As VMInputControl = vm.Container.NewImage("displaypic", "./assets/sponge.png", "SpongeBob","80px", "80px")
    Dim uploadprofile As VMInputControl = vm.Container.NewFile("uploadpic", "Upload Profile Image", "", False, "", "", 0)
    
    Dim notes As VMInputControl = vm.Container.NewTextArea("notes", "Notes", "", True, True, "", 0,"", "Notes are required!", 0)
    Dim agree As VMInputControl = vm.Container.NewCheckBox("agree", "I agree with terms of use", "true", True, 0)
    
    Dim txtPassword As VMInputControl = vm.container.NewPassword("password","Password","",True,False,"",15,"", "The password is required!",0)
    Dim txtconfirmPassword As VMInputControl = vm.container.NewPassword("confirmpassword","Confirm Password","",True,True,"",15,"", "The password is required!",0)
    
    'add the controls, the grid will be automatically created
    mdlRegister.Container.AddControl(profilepic,1,1,0,0,0,0,12,6,6,6)
    mdlRegister.Container.AddControl(uploadprofile,1,2,0,0,0,0,12,6,6,6)
    
    mdlRegister.Container.AddControl(txtfirstname,2,1,0,0,0,0,12,6,6,6)
    mdlRegister.Container.AddControl(txtlastname,2,2,0,0,0,0,12,6,6,6)
    '
    mdlRegister.Container.AddControl(dpDOB,3,1,0,0,0,0,12,6,6,6)
    mdlRegister.Container.AddControl(tpTOB,3,2,0,0,0,0,12,6,6,6)
    '
    mdlRegister.Container.AddControl(txtTel,4,1,0,0,0,0,12,6,6,6)
    mdlRegister.Container.AddControl(txtEmail,4,2,0,0,0,0,12,6,6,6)
    '
    mdlRegister.Container.AddControl(radGender,5,1,0,0,0,0,12,6,6,6)
    mdlRegister.Container.AddControl(chipSkills,5,2,0,0,0,0,12,6,6,6)
    '
    mdlRegister.Container.AddControl(children,6,1,0,0,0,0,12,6,6,6)
    mdlRegister.Container.AddControl(notifications,6,2,0,0,0,0,12,6,6,6)
    '
    mdlRegister.Container.AddControl(txtPassword,7,1,0,0,0,0,12,6,6,6)
    mdlRegister.Container.AddControl(txtconfirmPassword,7,2,0,0,0,0,12,6,6,6)
    '
    mdlRegister.Container.AddControl(notes,8,1,0,0,0,0,12,12,12,12)
    mdlRegister.Container.AddControl(agree,9,1,0,0,0,0,12,12,12,12)

As noted, the controls on the modal will appear side by side in the 2x6 grid.

When Cancel is clicked, we want to hide this modal and show the login modal, this is achieved by:

B4X:
Sub btnCancelSignUp_click(e As BANanoEvent)
    'hide the registration modal
    vm.HideDialog("mdlregister")
    'show the login modal
    vm.ShowDialog("mdlsignin")
End Sub

And when we continue with the registration, we need to validate some data before we save.

B4X:
Sub btnOkSignUp_click(e As BANanoEvent)
    'get the contents of the form
    Dim rec As Map = mdlRegister.Container.GetData
    'validate the details
    Dim bValid As Boolean = mdlRegister.Container.Validate(rec)
    If bValid = False Then Return
    Log(rec)
    'process further
End Sub

Ta!
 

Mashiane

Expert
Licensed User
Longtime User
Pushed Version 2.05 which ensures some consistencies across the board.

latest.png


1. One can set up the logo on the navbar.
2. Built in file upload based on PHP, see modFile example
3. A blank project template for your own projects has been added.
4. All example projects updated to refresh version 2.05. No further breaks are anticipated.
 

Mashiane

Expert
Licensed User
Longtime User
Upcoming Plugins: Google Map

First Get API Key: https://developers.google.com/maps/documentation/javascript/get-api-key

The VueMaterial framework does not have a mapping component. So research about a compatible vue based google map component went underway yesterday. So far the experience has been a marvel. It does what is needed.

Well, one needs a gmap javascript api key.

BVMGMap.gif


In this instance once needs to show a GPS location on the map. We are able to add / remove markers on demand based on some the marker "state". Only the basic stuff has been added here for now.
 
Last edited:

Mashiane

Expert
Licensed User
Longtime User
Important Update: File Uploading

BVMaterial uses PHP for file uploads, to be able to do this, one needs the attached upload.php file. This saves uploaded files to the assets folder.

The way the framework uploads files has been updated to use the BANanoXMLHttpRequest object.

The new code is..

B4X:
Sub UploadFiles(fList As List)
    For Each fileObj As Object In fList
        vm.HTTPUpload(fileObj, Me, "filedone")
    Next
End Sub

Sub FileDone(fileObj As Map, json As String)
    Dim resp As Map = BANano.FromJson(json)
    Dim status As String = resp.Get("status")
    Select Case status
    Case "success"
        Dim fd As FileObject = vm.GetFileDetails(fileObj)
        Log(fd)
    Case Else
        vm.ShowSnackBar("File could not be uploaded!")
    End Select
End Sub

The fList variable is the fileList obtained from an file input control.

The underlying source code works like this.

1. We create a FileObject type for internal use.

B4X:
Type FileObject(FileName As String, FileDate As String, FileSize As Long, FileType As String)

2. This we later use with... (this reads FileReader details and saves it as a type)

B4X:
Sub GetFileDetails(fileObj As Map) As FileObject
    Dim sname As String = fileObj.Get("name")
    Dim slastModifiedDate As String = fileObj.Get("lastModifiedDate")
    slastModifiedDate = Date2YYYYMMDDHHMM(slastModifiedDate)
    Dim ssize As String = fileObj.Get("size")
    Dim stype As String = fileObj.Get("type")
    '
    Dim ff As FileObject
    ff.Initialize
    ff.FileName = sname
    ff.FileDate = slastModifiedDate
    ff.FileSize = ssize
    ff.FileType = stype
    Return ff
End Sub

3. We upload each file in the file list by calling...

B4X:
Sub HTTPUpload(fileObj As Object, module As Object, methodname As String)
    Dim promise As BANanoPromise 'ignore
    ' some vars to hold our results
    Dim Error As String
    Dim json As String
    
    ' call the http request
    promise.CallSub(Me, "DoUpload", Array(fileObj))
    promise.ThenWait(json)
    BANAno.CallSub(module, methodname, Array(fileObj, json))
    promise.ElseWait(Error)  'ignore
    BANAno.CallSub(module, methodname, Array(fileObj, Error))
    promise.End
End Sub

4. This called DoUpload..

B4X:
private Sub DoUpload(fileObj As Object) As String   'ignore
    Dim aEvt As Object
    Dim xhr As BANanoXMLHttpRequest
    'define form data
    Dim fd As BANanoObject
    fd.Initialize2("FormData",Null)
    fd.RunMethod("append", Array("upload", fileObj))
    '
    xhr.Initialize
    xhr.Open("POST", "./assets/upload.php")
    xhr.AddEventListenerOpenAsync("onreadystatechange", aEvt)
    If xhr.ReadyState = 4 Then
        If xhr.Status = 200 Then
            BANAno.ReturnThen(xhr.ResponseText)
        Else
            Dim err As Map = CreateMap()
            err.Put("status", "error")
            Dim serr As String = BANAno.ToJson(err)
            BANAno.ReturnElse(serr)
        End If
    End If
    xhr.CloseEventListener
    xhr.Send2(fd)
End Sub
 

Mashiane

Expert
Licensed User
Longtime User
Upcoming Plugins: Gijgo Table

Sadly, the table implementation for VueMaterial is incomplete, so I ported the table that I discussed here, to work in a vue environment. Yes there are tables available for vue as components, this one due to an already implemented methodology, it proved easy to use.

VMGijgoTable.png


One can add columns as they need, whether for images, icons etc.

You can learn more on how to use this plugin from this thread.
 
Last edited:

Mashiane

Expert
Licensed User
Longtime User
MySQL CRUD Tutorial

You can quickly learn how to create a CRUD app by following this tutorial here. It discussed some important things that are related to creating, reading, updating and deleting records from a MySQL database. Also shows you how to load select boxes from database records using vue state methodology.

[BANanoVueMaterial] Creating Expenses.Show - a CRUD expense tracker with MySQL backend: Part 1

[BANanoVueMaterial] Creating Expenses.Show - a CRUD expense tracker with MySQL backend: Part 2
 

Mashiane

Expert
Licensed User
Longtime User
Upcoming Plugins - EasyHint


This is simple as...

B4X:
Sub StartTour
    Dim eh As VMEasyHint
    eh.initialize
    eh.AddStep("btnAddEmployees", "Click here to add an employee")
    eh.AddStep("btnRefreshEmployees", "To refresh the list of employees, click here")
    eh.AddGijgoTable("tblEmployees", "Your list of captured employees will be shown in this table. Here you can also click Edit or Delete to update and delete employees")
    eh.AddStep("fltEmployees", "You can filter the columns to display on your table by using filters here")
    eh.AddSelect("filterEmployees", "You can select multiple columns to display on the table here")
    eh.AddStep("btnRstFltEmployees", "Clicking here will reset the column filters")
    eh.AddStep("btnAplyFltEmployees", "Once columns are selected in the filter, you can click here to apply the filters")
    eh.EndsOn("btnAplyFltEmployees")
    eh.run
End Sub
 

Mashiane

Expert
Licensed User
Longtime User
Upcoming Updates: Autocomplete

The upcoming update is based on how the autocomplete can be used as a replacement to the select control. This is a hack that I came up with to this control using 2 underlying maps.

1. You add items that are key value pairs to the autocomplete. 1 version of this map is saved as is and the other first swapped and then saved. For example here, we add some fonts as a map and use .SetOptionsMap. The existing .SetOptions uses a list of strings

B4X:
Dim fonts As Map = CreateMap()
    fonts.put("arial","Arial")
    fonts.put("calibri","Calibri")
    fonts.put("cambria","Cambria")
    fonts.put("comicsans","Comic Sans")
    fonts.put("consolas","Consolas")
    fonts.put("courier","Courier")
    fonts.put("droidsans","Droid Sans")
    fonts.put("georgia","Georgia")
    fonts.put("helvetica","Helvetica")
    fonts.put("impact","Impact")
    fonts.put("roboto","Roboto")
    fonts.put("segoeui","Segoe UI")
    fonts.put("timesnewroman","Times New Roman")
    fonts.put("ubuntu","Ubuntu")
    fonts.put("verdana","Verdana")
    '
    Dim ac4 As VMAutoComplete = vm.createautocomplete("ac4", Me).SetLabel("Fonts")
    ac4.SetVModel("fonts").SetOptionsMap(fonts).SetHelperText("Uses options as source")
    cont.AddComponent(4,1, ac4.ToString)

So to get a selected key, one will run this kind of call passing the identifier of the control.

B4X:
'get the
    Dim selValue As String = vm.GetAutoCompleteKey("ac4")
    vm.ShowSnackBar(selValue)

And to set the content via the key one can use.

B4X:
vm.SetAutoCompleteKey("ac4", "roboto")

by passing the identifier and the key to select.

This is useful when we want to store the underlying keys from a db but use an autoselect instead of a select control.

When one is also sourcing records from a database, one can also set the DataSource like this.

B4X:
'use datasource for content source
    Dim countries As List
    countries.initialize
    countries.add(CreateMap("id":"australia", "text":"Australia"))
    countries.add(CreateMap("id":"brazil", "text":"Brazil"))
    countries.add(CreateMap("id":"japan", "text":"Japan"))
    countries.add(CreateMap("id":"united-states", "text":"United States"))
    vm.setstatesingle("countries", countries)

    Dim ac5 As VMAutoComplete = vm.createautocomplete("ac5", Me).SetLabel("DataSource")
    ac5.SetVModel("ds").SetDataSource("countries", "id", "text").SetHelperText("Uses datasource for content")
    cont.AddComponent(4,1, ac5.ToString)

This works the same as the SetOptionsMap example but now a list of maps is being used.

Ta!
 
Last edited:
Top