B4J Tutorial [BANanoVuetifyAD3] Create Professional Looking Vuetify WebSites & WebApps with BANano

Mashiane

Expert
Licensed User
Longtime User
Form Validation - Defining Validation Rules

We want the input controls to be validated before being saved. This means for example, they should not be blank.

1. To validate input controls, they should have a parent VForm control. So place them inside a VForm.
2. For each control to be validated, you need to check its "Required" property in the property bag.
3. You also need to add the validation rules. A validation rule requires the callback method that will be executed to check the control validity.

So...

In Process Globals

B4X:
Private txtFirstName As VTextField

Then In Initialize.

You load your layout with the control and then BEFORE BindVueElement / BindState.

B4X:
txtFirstName.AddRule("firstnamecheck")

Then anywhere in your code code..

B4X:
Sub firstnamecheck(v As Object)
    If v = "" Then
        Return "The first name is required!"
    Else
        Return True
    End If
End Sub

A validation rule callsub returns True if the control is valid or the error message. The error message shows just under the control on your form.
 
Reactions: LJG

Mashiane

Expert
Licensed User
Longtime User
Form Validation - Checking Validation

On the button click event that we will use to read the form inputs, we need to add the form input check. Remember our input controls are placed inside the VForm. We have also added validation rules for each input control. So we can easily just call a single method to check the VForm valid state.

We add this to our dialog_ok_click event.

B4X:
Private Sub VMsgBox1_ok_click (e As BANanoEvent)
    'peform the form validation
    two.refs = vuetify.GetRefs
    Dim bValid As Boolean = userform.Validate(two)
    If bValid = False Then
        vuetify.ShowSwalToastError("Please enter all required information!", 2000)
        Return
    End If
    'get the user information, we prefixed the vmodel of each element with user
    'this will return a map object with the entered user details
    Dim user As Map = two.GetData("user")
    Log(user)    
End Sub

The form validation is done by calling the .Validate method of our form. If no content is entered on the form..., errors appear.

 

Mashiane

Expert
Licensed User
Longtime User
Forms - Getting Input Data

Each input control you place on the form needs to have a value. In VueJS, this is called the VModel. The VModel establishes a bi-directional data binding of the value of the input control.

When we were creating our input controls, we also established their data-binding values.



We prefixed each of the values in the data model with user.

This helps in ensuring that we just get/set the values of the input controls by passing them a single value, user.

This value is saved in the state / memory of the VueJS app as

B4X:
user {
firstname="",
lastname = "",
telephone = "",
email = ""}

So to get the data we use

B4X:
Dim user As Map = two.GetData("user")

In the future we will just use the VForm name with .GetData and not the page route component.

And to set the data, one will have to execute

B4X:
two.SetData("user", user)
 

Mashiane

Expert
Licensed User
Longtime User
What is ?.Refs = ?.GetRefs?

In the code above, you might have noticed this code.

B4X:
    two.refs = vuetify.GetRefs

But what does it really mean?

In JavaScript html, when you create an HTML element and give it an id, you are able to access it by .getElementByID("#txtfirstname") and then run code in it.

For example, the element might have been defined by.

B4X:
<input id="txtfirstname" type="text"></input>

With VueJS, the element is different. To be able to execute .getElementByID, each element needs to have a ref attribute. So our code will be..

B4X:
<input ref="txtfistname" id="txtfirstname" type="text"></input>

So basically, we are creating a reference.

Due to us using a route-viewer, i.e. the section of the app where our pages show, each and everytime we navigate between the pages, the references change to reflect the current page references.

So two.refs = vuetify.GetRefs ensures that, when we are in a particular page, the links to the references / controls are the valid ones for that page.

In real-life terms we have

B4X:
<form ref="userform" id="userform"></form>

then we execute...

B4X:
var valid = getElementByID("userform").validate();

And doing this the VueJS / Vuetify way..

B4X:
two.$refs.userform.validate();

Only after we refresh the references with refs = getrefs.
 
Reactions: LJG

Mashiane

Expert
Licensed User
Longtime User
Quick Wins - Toggling the Hamburger Button using Computed properties

When the hamburger button is clicked, it toggles the drawer and opens and closes it.



The sub call is...

B4X:
Private Sub apphamburger_ClickStop (e As BANanoEvent)
    vuetify.Toggle(appdrawer.VModel)
End Sub

What we want to do is that when the drawer is opened / closed, we show an appropriate icon on the nav bar icon. Thus we have added a new property to the VAppNavBarIcon called IconName.




By putting the value of the icon inside {{ }} we are saying it that the value should be obtained from a state/ memory variable. We could do this with

B4X:
Vuetify.SetData("detecthamburger", "mdi-settings")

However in this case, we need to detect whether the drawer is opened / not. So some computation needs to take place. Assigning such values is something called Computed Properties. A computation happens and then it assigns the value of that property from the result of that computation.

So, we need to know which property we are affecting and which sub-routine will run to return the value of that property. For example..

B4X:
detecthamburger = subName(?)

So inside subName(), we need to detect if the drawer is opened / closed and depending on that state, return the icon name to show.

We do this in pgIndex.Ini. detecthamburger will get its value from the checkdrawer subroutine,

B4X:
'detect the hamburger button
    vuetify.SetComputed("detecthamburger", "checkdrawer", Null)

What does the checkdrawer sub-route do?

B4X:
Sub checkdrawer As String            'ignoreDeadCode
    'check if the drawer is opened
    Dim dOpen As Boolean = appdrawer.IsOpenOnApp(vuetify)
    Select Case dOpen
    Case True
        'show the close icon
        Return "mdi-format-indent-decrease"
    Case False  
        Return "mdi-format-indent-increase"  
    End Select
End Sub

So anytime the drawer opens/closes, the checkdrawer sub executes, the icon name changes depending on the drawer state.

There are some instances where however one needs to rather use a Watch statement call with SetWatch. These work the same way though different.

Later!
 
Last edited:

Mashiane

Expert
Licensed User
Longtime User
Quick Wins: Adding a footer with Social Media Links

1. Place a VFooter inside VMain in pgIndex.
2. Create a new layout with a VCard. Inside the VCard put a VCardText.
3. Inside the VCardText, put a VBtn. We will create multiple buttons with icons and urls. We do this using the v-for directive.
A V-FOR directive is a loop that helps one create multiple elements using the same attributes. Think of it as B4J for each x As String in Array

As an example..



Our list name is socialmedialinks. Each object / map in the list should have a url, color, icon. The icon size should be 24px.

The v-for directive means, loop through all the objects in the list, create a v-btn for each item, and now because a v-btn can have a v-icon, we also specify the properties for each icon.

You will note that some properties are prefixed with :, this is called a binding. It helps for data to be computed / read / written to state/memory.

So our list definition on pgIndex.Init

B4X:
socialmedialinks.Initialize
    lsocialmedialinks.Add(CreateMap("url":"mailto:mbanga.anele@gmail.com", "icon":"mdi-google", "color":"white"))
    lsocialmedialinks.Add(CreateMap("url":"https://twitter.com/mashymbanga", "icon":"mdi-twitter", "color":"white"))
    lsocialmedialinks.Add(CreateMap("url":"https://www.linkedin.com/in/anele-mashy-mbanga-4b639376/", "icon":"mdi-linkedin", "color":"white"))
    lsocialmedialinks.Add(CreateMap("url":"https://api.whatsapp.com/send?phone=27817366739&text=Anele%20'Mashy'%20Mbanga", "icon":"mdi-whatsapp", "color":"white"))
    lsocialmedialinks.Add(CreateMap("url":"https://t.me/bananovuematerial", "icon":"mdi-telegram", "color":"white"))
    vuetify.SetData("socialmedialinks", lsocialmedialinks)

This creates, these footer items..



You can use this links to reach us via the various links.

Ta!

PS: The External Libraries and Kitchen Sink have been updated with these examples. Please re-download.
 

Mashiane

Expert
Licensed User
Longtime User
Ola

It is with a great pleasure that we have successfully released the BANanoVuetifyAD3 BANanoServer New Awesome Kitchen Sink - UI Phase project. This would not be possible without Alain and Erel. A many thanks to them. Also a great appreciation to all the partners of this project and also the b4x community. This is for you and your "likes" go a long way as they encourage us to always push to do best!

This has been possible because of your help, time and effort, advice, requests for this. So this is dedicated to y'all.

This project is the implementation of the UI from our New Awesome Kitchen Sink WebApp that we did using BANano + Vuetify + B4X some time ago.

The goal of this project is to help you, the developer, the engineer, the designer to create fresh, awesome, cool, amazing, mind blowing websites/webapps using the power of b4x and its cool abstract designer. You generate events also just like you do when creating B4a, B4i, b4j apps. Easy Peasy.

You can find more information about the BANanoServer here, https://www.b4x.com/android/forum/t...ananoserver-going-full-circle.111406/#content

This project is based on VueJS 2, the Reactive framework created by Evan You. and work done by John Leider on Vuetify.

1. Download BANano, copy the BANano + BANanoServer libraries to your B4J External Libraries Folder.
2. Download BANanoVuetifyAD3 External LIbraries, copy these to your B4J External Libraries Folder
3. Download the BANanoVuetifyAD3 BANanoServer New Awesome Kitchen Sink WebApp - UI Phase to your workspace
4. Run the project and open your browser on http://localhost:55056/

Enjoy and have fun.

PS: At the footer of the WebApp, we have our social media links. You are welcome to join us.

?


 

aeric

Expert
Licensed User
Longtime User
For the Vuetify Core, I see the list is sorted by alphabetical order. Can you (maybe another drop down) make the list group by type?
 

aeric

Expert
Licensed User
Longtime User
No hurry. Just a suggestion if you free to do it in the future else just leave it.
 

Mashiane

Expert
Licensed User
Longtime User
Tip: Code CleanUp [ignore, ignoreDeadCode & RemoveDeadCode]

BANano has a cool feature to detect dead code and remove this on your app. Currently this has been turned off for all BVAD3 apps. This is done on App_Start

To turn this on, there are some conditions, you need to do some tidying up.

Using ignore & ignoreDeadCode

Before you always run your app its always important to check the logs for errors. Most error will not have an effect, but do lookout for warning 8 and fix it. Your app wont work at all.

1. Add ignore to all variable declarations. In most cases these will be custom views from BVAD3. Just add ignore after the variable declaration



2. Add ignoreDeadCode to all subs. These will be reported as not used and as such will be cleaned out by the transpiler.

B4X:
Sub onmounted                'ignoreDeadCode
    'clear the drawer 
    drwlist.ClearOnApp(vuetify)
    drwlist.AddItem("", "welcome", "mdi-vuetify", "light-blue", "Welcome", "/")
    drwlist.AddItem("", "core", "mdi-vuetify", "light-blue", "Vuetify Core", "")

Turn the transpiler options on to remove all unused source code from the final payload (after adding ignore and ignoreDeadCode)

Then you are ready to switch these options on.

B4X:
BANano.TranspilerOptions.RemoveDeadCode = False
    BANano.TranspilerOptions.ShowWarningDeadCode = False

You might have to go back and forth to master this. Do a quality run on your app and check the logs if everything is not working as it should.

Consider using Try-Catch-End Try

Sometimes errors happen, with Try Catch End Try you are able to use BANano.Throw(???) to throw errors to the console.log. This will help to debug your app.

Run your app in Release Mode

At times, the app does not always work as it should in Debug mode, a lot of errors show on the console log (browser) e.g., files with .map extension, not found .js files. In such a case, run the app in release mode to see what happens first.

What to do when your app is not working as expected?

The first point of all is the browser console log, (Shift+Control+I). This provides a lot of information about your app and will show you when errors happen. Before you report an error, check this first, identify what its saying. Usually it gives line numbers of where the error happens. To have a clear understanding of the error, run your app in debug mode and recheck the error logs. Clicking that line will provided an un-encrypted version of your source code.

In summary, most errors on the B4J console are acceptable, warning 8 should be resolved otherwise your app wont run.

 

Mashiane

Expert
Licensed User
Longtime User
Update: Leaflet functionality fix.

One of the partners, @LJG, was testing the LeafLet functionality and indicated its over-lap. Suggested a z-index style file. This has been applied and will be available in the next release.



This is what I'm talking about!!!

Thanks

My browser is always at 90% so I didn't even pick this up!!!

Thanks @LJG!
 

Mashiane

Expert
Licensed User
Longtime User
Important Update for the BVAD3 B4xTemplate

Currently we have been using code modules to develop with BVAD3. Now, because the BANanoServer implementation uses classes, we have changed the B4xtemplate to use class modules. Its not a big change. This helps when one wants to move the project to banano server implementation, you just Import Existing Modules on the BANanoServer project.

If you don't plan to move your project to a BANanoServer in the future, you can continue using code modules, your project will work, however we just recommend you use class modules.

Here is the updated template:

We have included the leaflet page on it as we were testing a few things.

Later!
 
Cookies are required to use this site. You must accept them to continue using the site. Learn more…