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

Mashiane

Expert
Licensed User
Longtime User
Upcoming Updates: Radio Group

An additional function to allow radio groups to be loaded from a database like structure is added, this is how it works.



B4X:
Dim continents As List
    continents.initialize
    continents.add(CreateMap("id":"africa", "text":"Africa"))
    continents.add(CreateMap("id":"america", "text":"America"))
    continents.add(CreateMap("id":"newzeleand", "text":"New Zealand"))
    vm.setstatesingle("continents", continents)

    Dim rg2 As VMRadioGroup = vm.CreateRadioGroup("rg2", "DataSource", Me).SetVModel("ds")
    rg2.SetDataSource("continents", "id", "text")
    rg2.AddToContainer(cont, 2, 1)

We assume that the continents is sourced from a db. We use .SetDataSource for the radio group..

We can also trap the change event of the rado group, for example here, we show the value that is selected.

B4X:
Sub rg2_change(value As Object)
    vm.showsnackbar(value)
End Sub
 

Mashiane

Expert
Licensed User
Longtime User
Working with Watches (not the one you wear -- lol)



Here we want to be able to calculate the total value each time the quantity and the rate changes. VueJS has a nifty tool to do this, a concept called watches. This helps one detect changes on the v-model of an element. So what we want to do is each time a qty and rate changes the total is calculated.

We achieve this via a callback. We add components to our page and assign vmodels to them.
We then add watches for these vmodel states so that whenever the are changes, stuff happens.

B4X:
Dim txtQty As VMInput = vm.CreateInput("txtqty", Me).SetLabel("Quantity").SetVModel("qty").SetTypeNumber(True)
    Dim txtRate As VMInput = vm.CreateInput("txtrate", Me).SetLabel("Rate").SetVModel("rate").SetTypeNumber(True)
    Dim txtTotal As VMInput = vm.CreateInput("txttotal", Me).SetLabel("Total").SetVModel("total").SetTypeNumber(True)


IMPORTANT: Set the vmodels

  1. The vmodel for quantity is "qty"
  2. The vmodel for rate is "rate" and
  3. The vmodel for total is "total"
So we define the callback to call when ever a change happens in those 2 vmodels( qty and rate)

B4X:
'set computed for the total
Sub ComputeTotal
    'get the qty
    Dim iQty As Int = vm.getstate("qty",0)
    'get the rate
    Dim iRate As Int = vm.getstate("rate", 0)
    'calculate total
    Dim iTot As Double = BANano.parseint(iQty) * BANano.parseFloat(iRate)
    'format the amout
    iTot = Round(iTot, 2)
    'save the total
    vm.SetStateSingle("total", iTot)
End Sub

We then when building our app, tell our app that we need to watch these states.

B4X:
vm.SetWatch("qty", True, False, Me, "computetotal")
    'we want t watch for changes in rate
    vm.SetWatch("rate", True, False, Me, "computetotal")

So each time the 2 states changes, our total is calculated.! Walla!
 

Attachments

  • Calculations.zip
    17.8 KB · Views: 258
Last edited:

Mashiane

Expert
Licensed User
Longtime User
Its is with pleasure to release BVM 2.12 (GitHub link on first post)

1. RadioGroup loading from database table structure
2. AutoComplete loading from a database table structure and .GetValue and .SetValue methods for key access in key value fields.
3. EasyHint for tour generation
4. New Drawer section for Concepts added e.g. explaining the watch methodology.
5. Devices
6. Google Map
7. ChartKick
8. File Uploading

Known Issues: A lag when typing fast on input boxes.

Bug fixes

Enjoy!
 

Mashiane

Expert
Licensed User
Longtime User
IMPORTANT: Time to grow: Migrating BVM from VueMaterial to Vuetify aka BANanoVueMaterial 3

BVM2 is still functional and usable



A decision needed to be made, and needed to be made quickly. So far 3 successful projects have been delivered with this library from my side for different clients and one is just being finalized. Based on the comparison table above, the move was inevitable. One of the greatest pros to this move is "Long term support" for Vuetify and the other benefits.

Win 1 - Removing Unnecessary plugins

One of the things I needed to do to make BVM 2 work for the way I needed it to be was to add plugins. The pain with this was using the Gijgo table as the VueMaterial table functionality was incomplete. I love the gijgo table, but then again, the pro with Vuetify is that it already comes with a built in table. So I don't need the extra library. This is also inclusive of the RangeSlider plugin as the upcoming one is just as potent.

Win 2 - Code compatibility

After playing around with Vuetify, I was convinced it was just a very enhanced version of VueMaterial. WRONG! The win here is that with BVM 3, I'm making the code to be almost 100% compatible, so whilst your existing app will not break, it will also have more functionality. There are so many properties per component on the Vuetify framework (to make life easy), I'm mind blown! So far we are at 90% code compatibility between BVM 2+ and BVM 3. Further tests will be done.

Win 3 - 82+ components compared to 56+

The current implementation for BVM 3 is mainly for input components and form controls. We will also delve with the table component to replace the used gijgo table for BVM 2. So the additional components will be added as and when needed. This fortunately is an automated process I have coded but pending tests to check workability.

Win 4 - build in theming

Vuetify is following the same trend that was picked up from MaterializeCSS for example, COLOR_RED, INTENSITY_ACCENT4. Most properties have a "color" property and one can easily pass an intensity. So most controls are just easy to theme as just specifying their color or their background color whilst defining them. This is a very big plus compared to BVM2.

Win 5 - flexibility

Wow, now this is the cake! With Vuetify and BVM3, only your imagination will limit you. The documentation for Vuetify is intact and a marvel and just as easy to follow.

What to expect (still in early stages)

VueMaterial & Vuetify are Material Design Frameworks based on VueJS, so the name of our lib will remain the same whilst the underlying frameworks will be changed drastically.





















Watch this space!

Ta!
 
Last edited:

Mashiane

Expert
Licensed User
Longtime User
ChitChat: Behing the Scenes: Vuetify 2 BANano (Watch it now!)

This clip shows the process of wrapping up Vuetify or any well documented VueJS library to BANano. When well documented, one will get properties, events, slots etc. As we need to wrap this to a BANano class that we will later test to generate HTML code, we fire up something called "VueThing".

This is just a class name I decided to name. In most cases this will receive 3 things, the properties, the slots, and the events. What this does is clean up a few things and generate all the code needed to make the Component VueThing work in BANano. Most of this is .Set? methods that one can use to build their UX through setting up properties and events.


We are almost done with the wrap of all input components so that we can create DB based app. The exception is the table for display purposes, a rather crucial component.

So in simple terms...

B4X:
Dim mthing As VueThing
    mthing.Initialize("VM", "EditDialog", "v-edit-dialog")
    mthing.AddProperties(Array("cancel-text", "dark", "eager", "large", "light", "persistent", _
    "return-value", "save-text", "transition"))
    mthing.AddSlots(Array("input"))
    mthing.AddEvents(Array("cancel", "close", "open", "save"))
    mthing.Create

1. We need to create a component class, it should be prefixed by VM.
2. The name of the componentis "EditDialog"
3. The tag of the component is "v-edit-dialog"
4. We specify the properties for the component. These methods are just shortcuts e.g. AddProperties, AddSlots, AddEvents as there are more detailed methods that also receive default and description of each property, slot, event etc.

We then use some templates to build up the B4X class. a template will look like this..

B4X:
'set for
Sub SetVFor(item As String, dataSource As String) As ClassPrefix<vi>
    dataSource = dataSource.tolowercase
    item = item.tolowercase
    Dim sline As String = $"${item} in ${dataSource}"$
    SetAttrSingle("v-for", sline)
    Return Me
End Sub

This code is based on the root component VMElement where all other elements are based on and it builds the HTML template of the component we need based on .Set calls we make during development. The stuff to change in this template is ClassPrefix<vi>

B4X:
'set for
Sub SetVFor(item As String, dataSource As String) As ClassPrefix<vi>
    dataSource = dataSource.tolowercase
    item = item.tolowercase
    Dim sline As String = $"${item} in ${dataSource}"$
    SetAttrSingle("v-for", sline)
    Return Me
End Sub

Why not use just 1 base element? As the methods in these components are chained, in some cases, the base elements self references, this will lead to over-runs, thus the need to define each components in its own class. At times during exploring the examples and testing that the components works as expected, it has been discovered that some components are made up of a collection of a few components to make them.

Ta!
 

Mashiane

Expert
Licensed User
Longtime User
Latest Developments coming to BVM

Download BETA 2 here

With the new upgrade of BVM from VueMaterial to Vuetify well things are going surely with speed. So far we have ported over 30 components that we are able to use.

Still we are at BETA, but then again, the road has has its hurdles. Below are some stuff we have been able to do. It should be noted that wrapping a huge lib like this has its pros and cons. For now were are mainly focusing our efforts on INPUT controls. So extra components will come with time.

Search input on toolbar



Chips



AutoComplete



Lists



Snackbar Configuration



Steppers



Tabs



TreeView



NB: We are currently working tirelessly to bring the data-table to life, which will close Phase 1 of this important project. The next phase will be to run more tests with the previous version of BVM to ensure compatibility of apps so that current apps dont break much.


Thanks for showing interest in this project.

Ta!
 
Last edited:

Mashiane

Expert
Licensed User
Longtime User
BETA 3 is now available, this is inclusive of the DataTable. Beta 3 is the update of the library to use Vuetify framework. Our previous BVM version used an additional library called Gijgo, this is now not necessary.

Download here



There are some automated processes for form design that are en route.

Ta!
 

Mashiane

Expert
Licensed User
Longtime User
Input Dialog..

This demos how one can add input controls to a dialog:

NB: First ensure you call AddRows(?).AddColumns??? to build the grid where the controls will sit and then use .AddComponent(Row?, Column? ) to add each component.



The code to create this dialog is..

B4X:
Sub InputDialog As VMDialog
    Dim user As Map = CreateMap()
    vm.SetData("user", user)
    '
    Dim diag As VMDialog = vm.CreateDialog("inputdialog", Me)
    diag.SetModal(True)
    diag.SetWidth("800px")
    diag.SetTitle("Input Dialog")
    diag.Container.AddRows(7).AddColumns2x6
    '
    Dim chkAgree As VMCheckBox = vm.CreateCheckBox("chkAgree1", Me).SetVModel("user.agree").SetLabel("I agree")
    Dim dob As VMDatePicker = vm.CreateDatePicker("dob", Me).SetVModel("user.dob").SetLabel("Date of Birth").SetForInput
    Dim fi As VMFileInput = vm.CreateFileInput("myfile", Me).SetAccept("image/*").SetLabel("File input").SetVModel("user.myfile")
    Dim rg1 As VMRadioGroup = vm.CreateRadioGroup("gender", Me).SetVModel("user.gender").SetHorizontal(True).SetLabel("Gender")
    rg1.SetOptions(CreateMap("m":"Male","f":"Female"))
    Dim selx As VMSelect = vm.CreateSelect("code", Me).SetItems("items").SetLabel("Code").SetVModel("user.code")
    Dim age As VMSlider = vm.CreateSlider("age", Me).SetVModel("user.age").SetMin("0").SetMax("100").SetLabel("Age").SetThumbLabel("always").SetValue("46")
    Dim swt As VMSwitch = vm.CreateSwitch("notif", Me).SetLabel("Receive Notifications").SetVModel("user.notif")
    Dim txtm As VMTextArea = vm.CreateTextArea("about", Me).SetLabel("About Yourself").SetVModel("user.about")
    Dim txtfn As VMTextField = vm.CreateTextField("fn", Me).SetLabel("First Name").SetVModel("user.fn").SetHint("Enter a first name").SetPersistentHint(True).SetClearable(True).SetMaxLength(50)
    Dim ac1 As VMAutoComplete = vm.CreateAutoComplete("ln", Me).SetVModel("user.ln").Bind(":items", "items").SetLabel("Last Name")
    Dim a3 As VMAvatar = vm.CreateAvatar("dp", Me).SetImage("./assets/sponge.png", "Sponge")
    Dim tp2 As VMTimePicker = vm.CreateTimePicker("tob", Me).SetVModel("user.tob").SetLabel("Time of Birth").SetForInput
    Dim cbo1 As VMComboBox = vm.CreateComboBox("combox", Me).SetVModel("user.combo").SetItems("items").SetLabel("Select a favourate activity or create a new one")
    Dim pwd As VMTextField = vm.CreateTextField("pwd", Me).SetLabel("Password").SetPassword(True).SetName("password",False).SetVModel("user.pwd").SetHint("At least enter 8 characters.")
    pwd.SetCounter(8)
   
    diag.Container.AddComponent(1, 1, chkAgree.ToString)
    diag.Container.AddComponent(1, 2, dob.tostring)
    diag.Container.AddComponent(2, 1, fi.tostring)
    diag.Container.AddComponent(2, 2, rg1.tostring)
    diag.Container.AddComponent(3, 1, selx.tostring)
    diag.Container.AddComponent(3, 2, age.tostring)
    diag.Container.AddComponent(4, 1, swt.tostring)
    diag.Container.AddComponent(4, 2, txtm.tostring)
    diag.Container.AddComponent(5, 1, txtfn.tostring)
    diag.Container.AddComponent(5, 2, ac1.tostring)
    diag.Container.AddComponent(6, 1, a3.tostring)
    diag.Container.AddComponent(6, 2, tp2.tostring)
    diag.Container.AddComponent(7, 1, cbo1.tostring)
    diag.Container.AddComponent(7, 2, pwd.tostring)
    '
    diag.AddCancel("btnCancelIt", "Cancel")
    diag.AddOK("btnSaveIt", "Save")
    Return diag
End Sub
 

Mashiane

Expert
Licensed User
Longtime User
BETA 4 is out...

Download

This deals with adding controls to the parent container by specifying control position. With this method, one does not need to call .AddRows(?).AddColumns(??) first.

The grid is automatically designed from the positions and spans specified.

Example code: .SetDevicePositions & .AddControl

B4X:
Sub Code
    vm = pgIndex.vm
    'create a container to hold all contents
    Dim cont As VMContainer = vm.CreateContainer(name, Me)
    'hide this container
    cont.Hide
    '
    Dim switch As VMSwitch = vm.NewSwitch("switch1", "Radio", "Yes", "No", True, 0).SetDevicePositions(1, 1, 12, 6, 6, 6)
    cont.AddControl(switch.SwitchBox, switch.ToString)
    '
    Dim radiogroup As VMRadioGroup = vm.NewRadioGroup("radiogroup", "Gender", "f", CreateMap("m":"Male","f":"Female"), 0).SetDevicePositions(1, 2, 12, 6, 6, 6)
    radiogroup.SetHorizontal(True)
    cont.AddControl(radiogroup.RadioGroup, radiogroup.ToString)
    '
    Dim checkbox As VMCheckBox = vm.NewCheckBox("checkbox", "I concur!", "Yes", "No", True, 0).SetDevicePositions(1, 3, 12, 6, 6, 6)
    cont.AddControl(checkbox.CheckBox, checkbox.ToString)
    '
    Dim datepicker As VMDatePicker = vm.NewDatePicker("datepicker", "Date Picker", True, "Select a Date Picker", "This date", 0).SetDevicePositions(1, 4, 12, 6, 6, 6)
    cont.AddControl(datepicker.DatePicker, datepicker.ToString)
    '
    Dim timepicker As VMTimePicker = vm.NewTimePicker("timepicker", "Time Picker", True, "Select a time Picker", "This time", 0).SetDevicePositions(2, 1, 12, 6, 6, 6)
    cont.AddControl(timepicker.TimePicker, timepicker.ToString)
    '
    Dim slider As VMSlider = vm.NewSlider("slider", "Slider", 0, 100, 0).SetDevicePositions(2, 2, 12, 6, 6, 6)
    cont.AddControl(slider.Slider, slider.ToString)
    '
    'add container to page
    vm.AddContainer(cont)
End Sub

This produces...



NB: When using .SetDevicePositions and .AddControl one should not skip a RC when adding components.

The .New??? are just shortcuts for .Create??? and one can use either to create components.

For example, NewSwitch

B4X:
Sub NewSwitch(sname As String, slabel As String, svalue As Object, sunchecked As Object, bPrimary As Boolean, iTabIndex As Int) As VMSwitch
    sname = sname.tolowercase
    Dim actName As String = sname
    Dim actID As String = sname
    If sname.IndexOf(".") >= 0 Then
        actName = MvField(sname,2,".")
    End If
    Dim el As VMSwitch = CreateSwitch(actName, module)
    el.SwitchBox.ActualID = actID
    el.SetVModel(actName)
    el.Setlabel(slabel)
    el.SetTrueValue(svalue)
    el.SetPrimary(bPrimary)
    el.SetFalseValue(sunchecked)
    el.SetTabIndex(iTabIndex)
    el.SwitchBox.Host = $"${actName}field"$
    Return el
End Sub

Ta!
 

Mashiane

Expert
Licensed User
Longtime User
Things the new version comes with: Alerts



B4X:
vm.CreateAlert("a8", Me, "").SetContent("You've got {B}5{/B} new updates on your timeline!.").SetIcon("mdi-twitter") _
    .SetDismissible(True).SetBorder("left").SetColoredBorder(True).SetOutlined(True).SetColor(vm.COLOR_CYAN).SetElevation(2).AddToContainer(cont, 1, 2)
 

Mashiane

Expert
Licensed User
Longtime User
Things the new version comes with: Banners



B4X:
Dim banner1 As VMBanner = vm.CreateBanner("banner1", Me).SetTwoLine(True)
    Dim avat As VMAvatar = vm.CreateAvatar("avat1", Me).SetSlot("icon").SetSize("40").SetColorIntensity(vm.COLOR_DEEPPURPLE, vm.INTENSITY_ACCENT4)
    avat.SetIcon("mdi-lock","", CreateMap("color" : "white"), Null, Null)
    '
    banner1.AddComponent(avat.ToString)
    banner1.SetText(vm.Fake.Rand_LoremIpsum(1))
    banner1.AddAction(vm.CreateButton("btnDismis", Me).SetLabel("Dismiss").SetPrimary(True).SetTransparent(True))
    banner1.AddAction(vm.CreateButton("btnRetry", Me).SetLabel("Retry").SetPrimary(True).SetTransparent(True))
    '
    banner1.SetOnClickIcon("checkConnection")
    
    cont.AddComponent(1, 2, banner1.ToString)

B4X:
Sub checkConnection(e As BANanoEvent)
    vm.showsnackbar("Check connection!")
End Sub
 

Mashiane

Expert
Licensed User
Longtime User
Things the new version comes with: Bottom Navigation



B4X:
Dim bn3 As VMBottomNavigation = vm.CreateBottomNavigation("bn3", Me).SetVModel("bottomNav").SetDark(True).SetShift(True)
    '
    Dim btnRecent2 As VMButton = vm.CreateButton("btnRecent2", Me).SetValue("recent")
    btnRecent2.AddComponent(vm.CreateLabel("").SetSpan.SetText("Recent").tostring)
    btnRecent2.AddComponent(vm.CreateIcon("", Me, "mdi-history").tostring)
    bn3.AddComponent(btnRecent2.ToString)
    '
    Dim btnFav2 As VMButton = vm.CreateButton("btnFav2", Me).SetValue("favorites")
    btnFav2.AddComponent(vm.CreateLabel("").SetSpan.SetText("Favorites").tostring)
    btnFav2.AddComponent(vm.CreateIcon("", Me, "mdi-heart").tostring)
    bn3.AddComponent(btnFav2.ToString)
    '
    Dim btnNear2 As VMButton = vm.CreateButton("btnNear2", Me).SetValue("nearby")
    btnNear2.AddComponent(vm.CreateLabel("").SetSpan.SetText("Nearby").tostring)
    btnNear2.AddComponent(vm.CreateIcon("", Me, "mdi-map-marker").tostring)
    bn3.AddComponent(btnNear2.ToString)
    '
    cont.AddComponent(2, 1, bn3.tostring)
 

Mashiane

Expert
Licensed User
Longtime User
Things the new version comes with: Bottom Sheet



B4X:
Sub BottomSheet2 As VMBottomSheet
    Dim bs As VMBottomSheet = vm.CreateBottomSheet("bs2", Me).SetVModel("bs2").SetInset(True)
    Dim s As VMSheet = vm.CreateSheet("s2", Me).SetTextCenter.SetHeight("200px")
    '
    s.Container.AddRows(1).AddColumns12
    '
    Dim lbl As VMLabel = vm.CreateLabel("lbl2").SetText("This is a botto sheet using inset prop!").SetParagraph
    s.Container.AddComponent(1, 1, lbl.ToString)
    '
    Dim btnClose As VMButton = vm.CreateButton("btnCloseSheet2", Me).SetLabel("Close Sheet")
    s.Container.AddComponent(1, 1, btnClose.ToString)
    '
    bs.AddComponent(s.ToString)
    Return bs
End Sub
 
Cookies are required to use this site. You must accept them to continue using the site. Learn more…