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

Ola

**************************************************
Feb 2024: BVAD3 RoadMap

*************************************************

Download Additional Libraries
Download BANanoVuetifyAD3Core Library OR Download BANanoVuetifyAD3 Library
Download Kitchen Sink WebApp (Optional - useful for Learning how this works)
Download BVAD3Builder (Optional - useful to trim your final package)

Full Install Instructions on Github

What's New

To use this free and open source B4J library, you need BANano.

IMPORTANT: BANano License

Join Us

Telegram: https://t.me/bananovuematerial
Twitter: https://twitter.com/mashymbanga
Discord: https://discord.gg/ys8stGgWCU
YouTube: Mashy Teaches Video Series
B4x Blog: Mashy Teaches BVAD3 - New Series
Full Demo: New Awesome Kitchen Sink

Notable Forum Members Contributions

@Erel : Obviously
@alwaysbusy : valuable advice etc, BANano (incl. adjustments that support BVAD3)
@LJG : BANanoServer jRDC2, best overall bug finder
@aeric: Recommendations & Enhancements etc
@Star-Dust : Small solutions to development hitches etc
More...


What's Next?

You will find the most up to date content from this post onwards

Testing DataBase Connectivity (PHP)

The kitchen sink now has connectity testing for the various backends. To ensure that your app will work, you can check if your back-end is accessible.

MySQL
SQLite
MSSQL

WebServers You Can Use

Laragon - publish to c:\laragon\www



USBWebServer
IIS - Publish to C:\inetpub\wwwroot
XAMPP - change your publish folder to use // instead of \

You can find more information here related to IDE Setup

Enjoy

PS: Log Warnings & Compilation Errors

1. Please check the pre-run logs. In most cases modules with warnings will have an underline. Warning, 9, 10, 11, 12 are normal, don't be scared.

1625825241311.png


2. manifext.txt file not found - Download the library source code and RUN to recompile on your PC. "Do not Compile to Library"
3. Do a HARD REFRESH of your browser.[/B]
 
Last edited:

Mashiane

Expert
Licensed User
Longtime User
Upcoming Changes: Show Date Buttons (True/False)

For the DatePicker used in textboxes, we have added a new property in the property bag. This enables one to hide the buttons on the date picker. By default this is True, when turned off, there is no Cancel, Clear and Ok buttons. This can speed up date entry. This is also available on the VField component.

@ThanksToARecommendationFromAFriend.

1640867154757.png
 

Mashiane

Expert
Licensed User
Longtime User
Upcoming Updates: V-Chip - MinusPlus

MinusPlusChipExp.gif



You activate this by indicating that the vchip is MinusPlus on the property bag.

Reproduction


1. Drop a VChip on the layout
2. Check the MinusPlus property bag option
3. The caption will be the initial value.
4. Indicate the two-way binding VModel to bind the chip value to i.e. age. You can get and set the age with .SetData("age", 10) or .GetData("age")

1640931534905.png


5. Clicking + / - on the chip increments / decrements the age value, this is done by calling IncrementChip

B4X:
Private Sub VChip10_Minus (e As BANanoEvent)
    VChip10.DecrementChip(about)
    'get the value
    Dim vn As String = VChip10.GetValue(about)
    vuetify.ShowSnackBarInfo(vn)
End Sub

Private Sub VChip10_Plus (e As BANanoEvent)
    VChip10.IncrementChip(about)
    'get the value
    Dim vn As String = VChip10.GetValue(about)
    vuetify.ShowSnackBarInfo(vn)
End Sub

Below is an example of setting a random value to the chip

B4X:
Private Sub btnRandom_Click (e As BANanoEvent)
    Dim xi As Int = Rnd(1, 50)
    VChip10.SetValue(about, xi)
End Sub
 
Last edited:

Mashiane

Expert
Licensed User
Longtime User
Upcoming Updates: Updates to scroll bars

Add this to pgIndex / BrowserIndex (Update : this is now built into the library)


B4X:
#if css
::-webkit-scrollbar {
  background: transparent;
  width: 12px !important;
}
::-webkit-scrollbar-thumb {
  background: #606060 !important;
  border-radius: 100px !important;
}
#End If

1640882745168.png


This is more evident here: (see right scrollbar)

1640882788285.png
 
Last edited:

Mashiane

Expert
Licensed User
Longtime User
The VField MinusPlus Chip Counter

1. Place a VField inside a VForm
2. Indicate the field name to bind the value to e.g. age
3. The Title/Caption should be the value of the field i.e. age.
4. The Table Heading indicates the Heading to show for this in the VueTable
5. The Data Type is integer
6. Select the Component Type - MinusPlus.

1640932383784.png


This will generate a MinusPlus Chip component on your form as per example below.

MinusPlusChip.gif
 

Attachments

  • ComboBoxes.zip
    19.1 KB · Views: 161

Mashiane

Expert
Licensed User
Longtime User
Upcoming Updates: VField Component Sizes

In the Add Person Screen above, the Full Name text field takes the whole 12 spaces of the dialog, filling up all the available space in that row.

There are times when you want to specify your own size for a column where your component is placed, for example, span of 6 below for fullname.

1640945271064.png


Option 1

On the FullName row you can add another VField, give it a div component type and indicate that it will be placed at R2C2, whilst the fullname will sit in R2C1.
This option uses 2 vfields to ensure that the components are placed next to each other and thus splitting the dialog.

This is just like the 3rd row, where we have first name and lastname.

We have the first name at R3C1

1640945617439.png


and we have last name at R3C2

1640945651964.png


However for Option 1 here, the component type should be DIV as you would not want any other component next to the first name.

Option 2

As a column size should span 12 spaces, you can with this option just indicate the size of the VField you need between 1 & 12.

1640945732310.png


In this example, the first name will sit in R2C1, however, we have indicated on Sizes SMLX that for Small (12), Medium to XTraLarge (6). Thus when the form is being created during BindState, this "new" size will be picked up and applied without a need for a second div.

With this option, one is able to create components of whatever, size they want at each RC and it just needs 1 VField in this case.
 

Mashiane

Expert
Licensed User
Longtime User
Upcoming Updates: VField Component Offsets

Offsets exists to nudge stuff to the right. In this example, we have nudged the full name 6 spaces to the right.

1640946254553.png


Care however should be practised as the size of the R2C1 should span 12 columns. To achieve the 12 spaces span, we have set an offset of 6 (nudge to the right 6 spaces) and also ensure the size of the fillname is 6, so that it does not extend beyond the dialog.

To offset, just like the example above, you provide the offsets in the VField for that RC. This is done in the Offsets SMLX, where each offset per device is specified.

1640946395765.png
 

Mashiane

Expert
Licensed User
Longtime User
Upcoming Updates: Vfield Computed VModel

The VModel is the two way data-binding of components to the data-model. Whilst one can specify the VField fieldname, which will link to the table to save content to, one can also compute the value of the vmodel.

A simple of this is the date-picker. The date internally on the data-base will be saved as yyyy-mm-dd, however when displayed, it shows as something nice.

The UI Part

Step 1


We need to link each VField to a VForm. On the VForm we specify the RecordSource, this is the single record specification for our form entry. For example.

1640947070018.png


In the above v-form, our table name is people (this should link to a real database table name).
We have given this v-form a record source of person, i.e. each record in the table people is called a "person"
For Singular, as humans, we call a single individual, a Person and many individuals People i.e. plural. These are used by the DataSource for the delete confirmation.

This helps us to ensure that to read the complete form content made up of all VFields inside the form, we can just execute

B4X:
dim pers as map = .GetData("person")
log(pers)

or do whatever manipulation we want.

Step 2

We add all our VFields to the VForm. We added a first name

1640947376404.png


this makes the assignment to the firstname to be person.firstname internally in our app. The Vfield is linked to the VForm with person recordsource.

We also added lastname

1640947431138.png



This makes the assignment person.lastname

Now what we want to do is that on the full name text field, when a person enters the first and last name, the fullname should be "computed", based on the entered first and last name, as depicted below.

ComputeVModel.gif


For this we are not using any change / keypress or any other event but the vmodel.

For the fullname field, we specify the Compute VModel property.

1640949075108.png


In simple terms, we want the computed vmodel for the fullname to be

B4X:
person.firstname + ' ' + person.lastname

being the firstname, a space and the last name.

Thus anytime person.firstname and person.lastname changes, the fullname will be automatically updated.

As noted above, the Compute VModel property has received a JAVASCRIPT code script. This only works for the UI. We need a second leg where for example, the fullname should be "persisted" to the db, as an example.

For the second leg we need to write B4X code for BVAD3 that will actually assign the computed value and save it to the DB. This second leg will not affect the UI but the back-end.

The Back-End Part

The back-end part involves updating the form content just before the content is written to the database.

In this particular case we want to join values of fields and compute a fullname based on firstname and lastname.

The example above only works with the UI, this example is for the back-end.

So in our dialog_ok click method, we need to execute a join of the fields..

B4X:
Private Sub dlgPeople_Ok_Click (e As BANanoEvent)
    frmPeople.JoinFields(home, "fullname", " ", Array("firstname", "lastname"))
    'perform datasource verification
    dsPeople.VERIFY
    'peform the form validation
    home.refs = vuetify.GetRefs
    Dim bValid As Boolean = frmPeople.Validate(home)
    If bValid = False Then
        'the validation has failed
        vuetify.ShowSwalToastError("Please enter all required information!", 2000)
        Return
    End If
    'get the entered content on the form
    Dim person As Map = frmPeople.GetData(home)
    Log(person)
   
    'show a loading indicator on the ok button
    'dlgPeople.OkLoading = True
    'get the record from form (recordsource) and CREATE / UPDATE record depending on mode
    'dsPeople.CREATE_OR_UPDATE
End Sub

As soon as OK is clicked, we execute the JoinFields method of the form, giving it the field to compute and which fields to join.
Then we execute verification and validation.

We also read and logged the form contents.

B4X:
 'get the entered content on the form
    Dim person As Map = frmPeople.GetData(home)
    Log(person)

This produces...

1640952516870.png


From the .GetData call, we can read the form contents as a map, update the map and then execute .SetData to write the contents back to the form, before its saved to teh DB.
 
Last edited:

Mashiane

Expert
Licensed User
Longtime User
Computing / Updating Dialog Form Data just before saving it to the Database

When the OK button of an input dialog is clicked, one can read the form contents, manipulate it and then feed it back to the from before the contents are saved to the db.

Step 1: Read the form contents.

B4X:
Private Sub dlgPeople_Ok_Click (e As BANanoEvent)
Dim person As Map = frmPeople.GetData(home)
 
.
.
.

Step 2: Update the form contents.

B4X:
person.put("age", 48)

Step 3: Feed back the updated content to the form, before CREATE_OR_UPDATE is called.

B4X:
frmPeople.SetData(home, person)

CREATE_OR_UPDATE etc will then save the data to the db.

This should be done inside the _OK_Click method.

You can perform any computation you need and update the map as needed.

NB: No matter how many times we change the age value below, because the computation/update of the age happens after the ok click button, it will always be 48.

ComputeBeforeSave.gif


The complete code

B4X:
Private Sub dlgPeople_Ok_Click (e As BANanoEvent)
    frmPeople.JoinFields(home, "fullname", " ", Array("firstname", "lastname"))
    'perform datasource verification
    dsPeople.VERIFY
    'peform the form validation
    home.refs = vuetify.GetRefs
    Dim bValid As Boolean = frmPeople.Validate(home)
    If bValid = False Then
        'the validation has failed
        vuetify.ShowSwalToastError("Please enter all required information!", 2000)
        Return
    End If
    'get the entered content on the form
    Dim person As Map = frmPeople.GetData(home)
    Log(person)
    person.Put("age", 48)
    frmPeople.SetData(home, person)
    
    'show a loading indicator on the ok button
    'dlgPeople.OkLoading = True
    'get the record from form (recordsource) and CREATE / UPDATE record depending on mode
    'dsPeople.CREATE_OR_UPDATE
End Sub
 
Last edited:

Mashiane

Expert
Licensed User
Longtime User
Adding VField Rules

A rule checks the validity of an entry. A component can have any number of rules, as long as the callbacks are defined.

You can tell the form should lazy-validate (i.e. when contered is entered per input component) with LazyValidation setting. This is on by default.

1640954651640.png


After the layout is loaded, we can add rules per each of the fields.

B4X:
frmPeople.AddRule("firstname", "firstnamecheck")
    frmPeople.AddRule("lastname", "lastnamecheck")
    frmPeople.AddRule("lastname", "lastnamesizecheck")

Above we see the lastname field have 2 rules.

Focusing on the .AddRule, gives intellisense that has code we can copy.

1640953528107.png



The first and last names should be specified, as these are required.

B4X:
Sub firstnamecheck(v As String) As Object    'ignoredeadcode
    v = BANanoShared.ValidString(v)
    If v = "" Then
        Return "This first name is required!"
    Else
        Return True
    End If
End Sub

Sub lastnamecheck(v As String) As Object    'ignoredeadcode
    v = BANanoShared.ValidString(v)
    If v = "" Then
        Return "This last name is required!"
    Else
        Return True
    End If
End Sub

Also, we want the length of the lastname to be more than 3 characters. As noted above, we added another rule, we then specify the callback.

B4X:
Sub lastnamesizecheck(v As String) As Object    'ignoredeadcode
    v = BANanoShared.ValidString(v)
    Dim lnl As Int = v.Length
    If lnl <= 3 Then
        Return "This last name length cannot be less than 3 characters!"
    Else
        Return True
    End If
End Sub

When we run the code, we have a nice experience. NB: Ensure your form's Hide Details is not checked so that the error messages are shown.

VFieldRules.gif


Source Code Attached
 

Attachments

  • ComboBoxes.zip
    19.1 KB · Views: 165
Last edited:

Mashiane

Expert
Licensed User
Longtime User
Upcoming Updates: Enhanced Life Cycle Methods

VueJS has life-cycle methods that you can fire at some events in the life of your app. Going forward, the way these will be defined is via.

Step 1:

Copy the event you want from the definition. This is available when you click VueComponent / VuetifyApp in Class_Globals.

LifeCycleMethods.jpg


Step 2: Take note of your component name

B4X:
Public name As String = "home"

Step 3: Rename the EventName_??? to the name of the VueComponent.

Step 4: Update the source code for the life cycle event.

B4X:
Sub home_mounted
    Dim people As List = home.NewList
    people.Add(CreateMap("id":1, "firstname": "Anele", "lastname":"Mbanga", "age":48))
    people.Add(CreateMap("id":2, "firstname": "Usi", "lastname":"Mbanga", "age":18))
    people.Add(CreateMap("id":3, "firstname": "Olo", "lastname":"Mbanga", "age":12))
    people.Add(CreateMap("id":4, "firstname": "Eso", "lastname":"Mbanga", "age":11))
    people.Add(CreateMap("id":5, "firstname": "Markhams", "lastname":"Mbanga", "age":25))
    people.Add(CreateMap("id":6, "firstname": "Gift", "lastname":"Mbanga", "age":10))
    dtPeople.Reload(people)
End Sub

With this there is no need to add .SetCreated / .SetMounted etc.

Now

.SetCreated = home_created
.SetMounted = home_mounted

YOU DO NOT HAVE TO ADD THESE METHODS with .SetCreated / .SetMounted etc anymore on .Initialize, as long as the ?_created, ?_mounted (etc) are specified as subs in your code module, BVAD3 will know that its a .SetCreated / .SetMounted (etc) call.

Remember
: _oncreated - the UI is not rendered / built. Use it to fetch data from a database / perform API fetch etc.
_mounted - the UI is rendered. use it to update the UI.

NB: If you dont have _created, _mounted (etc), nothing will be linked to .SetCreated / .SetMounted (etc), unless you specify it yourself with either .SetCreated / .SetMounted (etc) or with the _created / _mounted callbacks.
 
Last edited:

Mashiane

Expert
Licensed User
Longtime User
Upcoming Updates : MinusPlus VChip on VueTable.

MinusPlusOnVDataTable.gif


Trapping Events - these work like edit / delete for VueTable

B4X:
Private Sub dtPeople_age_Minus (item As Map)
    BANanoShared.DecrementMap(item, "age")
    Log(item)
End Sub

Private Sub dtPeople_age_Plus (item As Map)
    BANanoShared.IncrementMap(item, "age")
    Log(item)
End Sub

You can then manipulate the row item. The table name is dtPeople, the column name is age, the event is a minus / plus.

How to reproduce?

Option 1

Set the option via the VField inside your VForm. This is done on the Column Type. This is the option used in this example.

1640973927812.png


Option 2

Specify the field name to be a MinusPlus Fields column in the VueTable. Here you can specify, separated by ; all fields in the VueTable to be MinusPlus Fields.

1640974022481.png
 

Mashiane

Expert
Licensed User
Longtime User
Version 7.20.1 BETA Available

Please note BVAD3 7.20.1 BETA is now available. This features Vuetify 7.6.2


Here is the example that speaks to this version.


This also includes some bug fixes and other improvements.

Updated BVAD3.b4xtemplate

Also download and update the BVAD3 project template, add this to your B4J Additional Libraries folder.

 

Mashiane

Expert
Licensed User
Longtime User
Decided to deep dive into some difficult topics...

Known Issues: Inline Editing on the VDataTable DOES NOT WORK as expected for these types of Column Types when Multiple=True, recommendation is rather to set the Column Type as Chips/Normal and edit via your VMsgBox.



These are the variations on the VField

1641487417649.png


1641487441499.png


1641487469073.png
 
Last edited:

Mashiane

Expert
Licensed User
Longtime User
Explaining the VList(View)

The current VList in the Kitchen Sink is made of a tree-like structure like the one below.

1641665771831.png


Looking at the HTML, one notices a node tree. This is depicted like this in Vuetify documentation.

1641665860723.png


For BVAD3, we have created a similar structure to ensure that our VList can work with built in templates. This composition is here.

ListView.jpg


The HTML Tree indicates the level within the tree of each of the nodes we use in BVAD3 to create our template. One can also hide/show each node tree depending on their options via the property bag of the VListOptions used for the VList. For example below, HasDivider, InsetDivider, UseLeftImage have been set so that those components are shown when available.

We chose the tree template for the kitchen sink.

1641666261655.png


In pgIndex, we have a method to add items to our VList.

B4X:
drwlist.AddItem("", "newstuff", "mdi-vuetify", "light-blue", "What's New", "")
    drwlist.AddItem("newstuff", "minusplusx", "", "", "Minus Plus VChip", "/mpvchip")

This created this tree structure..

1641666818108.png


The AddItem method is defined as

B4X:
Sub AddItem(parent As String, key As String, iconName As String, iconColor As String, sTitle As String, url As String) As VList
    parent = parent.ToLowerCase
    key = key.ToLowerCase
    '
    Dim nitem As Map = CreateMap()
    nitem.Put("id", key)
    If iconName <> "" Then nitem.Put("icon", iconName)
    If iconColor <> "" Then nitem.Put("iconcolor", iconColor)
    If sTitle <> "" Then nitem.Put("title", sTitle)
    If url <> "" Then nitem.Put("to", url)
    nitem.Put("parentid", parent)
    nitem.Put("visible", True)
    Records.Add(nitem)
    Return Me
End Sub

This uses as map/object which has icon/iconcolor/title etc. These items you will find further down on the VListOptions.

1641667072328.png


We used mdi-vuetify icon and Whats New title, and the iconcolor is light-blue.

This on the VListOptions we indicate which fields to use to draw the VList via the VListOptions (see DependsOn and Props on the attached Excel Sheet)

By using the Alias, you can get each component after LoadLayout and then add classes or attributes to it.


 
Last edited:
Top