B4J Tutorial [BANano] [VuetifyAD3] Small solutions to development hitches (Tricks and tracks)

At the request of several friends, I opened this Thread which explains some problems encountered when developing with Banano and VuetiiFy.

Obviously I will propose the solutions that I have experimented, perhaps they will not be the best, but they are those obtainable with the documentation available at the moment.

INDEX
  1. MAKE A VTextField visible or invisible
  2. CHANGE NUMBER OF COLUMNS AND NAMES IN A TABLE BY CODE
  3. SIDE MENU
  4. CARD, ITERATIVE CYCLES AND .... ELECTRONIC SHOWCASE ( Part-1 , Part-2 , Part-3 , Part-4 , SOURCE CODE )
  5. IN-LINE PHP
  6. LOCAL storage of data or variables
  7. Change properties of vLabel and VTextField from code
  8. VUETABLE- How to insert MinusPlus columns and editable fields
  9. Button inside a VTABLE and event raised
  10. MESSAGE box, INPUTDIALOG and ToastMessage
  11. REGEX SPLIT
  12. From http to https (insecure to secure)
  13. How can I cast form String to number?
  14. Upload file to DB
  15. Viewer image from DB
  16. Upload a file and save it in a folder
  17. List of file
  18. USE the php code from an external application
  19. Using MQTT from Banano VAD3 with a ListView
  20. Cast string into integer
  21. Set and remove focus
  22. Call a JavaScript function from your injected JS source
  23. Calls a sub from JavaScript source
  24. Example of mobile panel and GoogleMaps without Vuetify


PLEASE DO NOT WRITE IN THIS THREAD. If you have any questions or comments, open a dedicated threads, but don't post your posts here.
If you want to propose some other solution, open your specific tutorial
 
Last edited:

Star-Dust

Expert
Licensed User
Longtime User
Upload a file and save it in a folder

You can use BANanoShared.UploadFileWait like this:
B4X:
Private Sub VFileInput1_Change (fileObj As Map)
    If banano.IsNull(fileObj) Or banano.IsUndefined(fileObj) Then Return
    VFileInput1.UpdateLoading(page, True)
 
    Dim fileDet As FileObject
    fileDet = BANanoShared.GetFileDetails(fileObj)
    Dim fnm As String = fileDet.FileName
    fileDet=BANanoShared.UploadFileWait(fileObj)
    Dim sstatus As String = fileDet.Status
 
    Select Case sstatus
        Case "error"
            vuetify.ShowSwalNotificationError($"file ${fnm} error"$,10000)
        Case "success"
            vuetify.ShowSwal("Success" )
    End Select
    VFileInput1.UpdateLoading(page, False)
End Sub

With this code, however, it transfers the file to the assets folder. But it could be a problem if the file you upload has the same name as one already present, even worse if it is a logo or a file needed for your pages.

This is why I suggest to modify the upload.php file (or create a second one with a different name) which loads the page in a different folder (for example the upload folder)

new upload.php:
<?php
header("Access-Control-Allow-Origin: *");
set_time_limit(0);
// create folder if don't exist
if (!file_exists('../upload/')) {
    mkdir('../upload/', 0777, true);
}
if (isset($_FILES['upload'])) {
    // Example:
    // if(move_uploaded_file($_FILES['upload']['tmp_name'], "../assets/" . $_FILES['upload']['name'])){
    if(move_uploaded_file($_FILES['upload']['tmp_name'], "../upload/" . $_FILES['upload']['name'])){
        echo '{ "status": "success" }';
    } else {
        echo '{ "status": "error" }';
    }
    exit;
} else {
    echo '{ "status": "error" }';
}
?>


In case you decide to use a second php for upload,
If you call the file upload2.php, you can invoke the code with UploadFileWait sub
B4X:
Sub UploadFileWait(fileO As Map) As FileObject
    'get the file details
    Dim fileDet As FileObject = BANanoShared.GetFileDetails(fileO)
    'get the file name
    Dim fn As String = fileDet.FileName
    'start uploading the file
    Dim fd As BANanoObject
    fd.Initialize2("FormData", Null)
    fd.RunMethod("append", Array("upload", fileO))
    '
    Dim Res As String = BANano.CallAjaxWait("./assets/upload2.php", "POST", "", fd, True, Null) ' php filename - upload2.php
    Dim result As Map = BANano.FromJson(Res)
    Dim sstatus As String = result.Get("status")
    fileDet.Status = sstatus
    If sstatus = "success" Then
        fileDet.FileOK = True
    Else
        fileDet.FileOK = False
    End If
    fileDet.FullPath = $"./upload/${fn}"$ ' folder selected
    Return fileDet
End Sub

And the event raised by VFileInput1 must be like this
B4X:
Private Sub VFileInput1_Change (fileObj As Map)
    If banano.IsNull(fileObj) Or banano.IsUndefined(fileObj) Then Return
    VFileInput1.UpdateLoading(page, True)
 
    Dim fileDet As FileObject
    fileDet = BANanoShared.GetFileDetails(fileObj)
    Dim fnm As String = fileDet.FileName
    fileDet=UploadFileWait(fileObj)
    Dim sstatus As String = fileDet.Status
 
    Select Case sstatus
        Case "error"
            vuetify.ShowSwalNotificationError($"file ${fnm} error"$,10000)
        Case "success"
            vuetify.ShowSwal("Success" )
    End Select
    VFileInput1.UpdateLoading(page, False)
End Sub

_________________________________________________________________________________________________________________________________________
PLEASE DO NOT WRITE IN THIS THREAD
. If you have any questions or comments, open a dedicated threads, but don't post your posts here.
If you want to propose some other solution, open your specific tutorial
 
Last edited:

Star-Dust

Expert
Licensed User
Longtime User
List of file
Today I have the need to have the list of files inside an upload folder.
As I load the images from the pc, I would like to get the content. How to do?

Here is a small example:
ezgif.com-gif-maker.gif



B4J code (For split function see here)
B4X:
Private Sub refresh
    VList1.Clear(page)
    VList1.AddHeader("File founded")
    Dim res As String = banano.CallInlinePHPWait("listdir", CreateMap("path":"upload"))
    For Each nomefile As String In Split("&",res)
        VList1.AddItem("",nomefile,"mdi-file","blue",nomefile.Replace("upload/",""),"")
    Next
    VList1.Refresh(page)
End Sub

'This is a variant of the attached source
Private Sub VList1_Click (item As Map)
    'vuetify.ShowSwal(banano.ToJson(item))
    'vuetify.NavigatetoURL(Main.ServerIP & item.Get("id"))
    VImg1.SetImage(page,Main.ServerIP & item.Get("id"))
End Sub

PHP Code
PHP:
  function listdir($path) {
    $ret = "";
      //$fileList = glob( __DIR__. $path. "/*.*");
    $fileList = glob($path. "/*.*");
    foreach($fileList as $filename){
        if(is_file($filename)){
            $ret.= $filename. "&";
        }
    }
    echo $ret;
  }

NB. To upload the image see the previous post

_________________________________________________________________________________________________________________________________________
PLEASE DO NOT WRITE IN THIS THREAD
. If you have any questions or comments, open a dedicated threads, but don't post your posts here.
If you want to propose some other solution, open your specific tutorial
 

Attachments

  • ListOfFile.zip
    24.2 KB · Views: 113
Last edited:

Star-Dust

Expert
Licensed User
Longtime User
USE the php code from an external application
In the pages of BANANO it is possible to insert PHP functions as explained in lesson 5 (see here)
If you also develop a STAND-Alone Mobile (android or iOs) or Desktop version of the same WebApp you may want to use the same PHP functions without having to recreate them all over again. How to do?

Suppose we have added this function
B4X:
#IF PHP
 function funcmd5($codevalue) {
    echo md5($codevalue);
   }
#END IF

From BANANO we would call the function like this
B4X:
Dim res As String = banano.CallInlinePHPWait("funcmd5", CreateMap("value": "mytext"))

From the App (Android / iOS / Desktop) we will send a POST request to the url nameApp.php with these JSON parameters
{"request":"funcmd5","params":{"codevalue":"mytext"}}

in B4X it would be
B4X:
Dim j As HttpJob
j.Initialize("", Me)
j.PostString("https://www.yourdomain.org/bananonameapp.php",$"{"request":"funcmd5","params":{"codevalue":"mytext"}}"$)
Wait For (j) JobDone(j As HttpJob)
If j.Success Then
    Log(j.GetString)
End If
j.Release
______________________________________________________________________________________________________________________________________

What if you would like to use the BANANO functions to access the DB?
Here is an example of parameters that must be sent in the POST
{"request":"BANanoMySQLDynamic","params":{"command":"select","query":"SELECT * FROM `my_table` WHERE `KeyName` = ? ORDER BY `Nome`","args":["Star-Dust"],"types":["s"],"host":"localhost","username":"userDB","password":"passwordDB","dbname":"my_databasename"}}

NB. Replace yourdomain with the name of the webApp address included in the sub-folder if it exists.
The PHP file always has the name you gave the WebApp. If you have any doubts, look in the folder where the files were generated and find the php file in the main folder where you also find the index.

PS. If you send POST requests from an App, don't forget to set USER-Agent, because you may have access authorization problems on some servers

_________________________________________________________________________________________________________________________________________
PLEASE DO NOT WRITE IN THIS THREAD
. If you have any questions or comments, open a dedicated threads, but don't post your posts here.
If you want to propose some other solution, open your specific tutorial
 
Last edited:

Star-Dust

Expert
Licensed User
Longtime User
Using MQTT from Banano VueAD3 with a ListView

I noticed that there are no examples of how to use Banano/VueAD3 to broadcast messages on an MQTT server.
It is very simple, the same as it is normally done on B4J. Please find attached a sample code


NB. You need to use mqtt with websocket connection.
Works fine with chrome and edge, in my case with opera the connection was not successful. I have not tested on other browsers

1679475277238.png


_________________________________________________________________________________________________________________________________________
PLEASE DO NOT WRITE IN THIS THREAD
. If you have any questions or comments, open a dedicated threads, but don't post your posts here.
If you want to propose some other solution, open your specific tutorial
 

Attachments

  • mqtt.zip
    17.4 KB · Views: 70
Last edited:

alwaysbusy

Expert
Licensed User
Longtime User
Thanks for publishing the example. Usage is indeed just like normal B4J.
doesn't connect using opera
Maybe there is some conflict within BDAV3? In pure BANano MQTT does work in Opera. We have several WebApps in production which use MQTT. We do have our own MQTT servers, setup with secure websockets, which may be something Opera does require? What errors do you see in the console in Opera?

Probably better to open a new thread for this issue.
 
Last edited:

Star-Dust

Expert
Licensed User
Longtime User
CAST STRING INTO INTEGER
I wrote this short code which Cast two strings into two integers.
B4X:
Dim TA As Int = 1 * "900"
Dim TTo As Int = 1 * "2100"
Dim B As Boolean = (TA<TTo)
vuetify.Showswal(TA & " < " & TTo & " " & b)

It is possible to use BANano.ParseInt() but it is slower

_________________________________________________________________________________________________________________________________________
PLEASE DO NOT WRITE IN THIS THREAD
. If you have any questions or comments, open a dedicated threads, but don't post your posts here.
If you want to propose some other solution, open your specific tutorial
 

Star-Dust

Expert
Licensed User
Longtime User
SET AND REMOVE FOCUS

Set focus
B4X:
SKTextBox.Element.RunMethod("focus", Null)

Remove focus
B4X:
SKTextBox.Element.RunMethod("blur", Null)

_________________________________________________________________________________________________________________________________________
PLEASE DO NOT WRITE IN THIS THREAD
. If you have any questions or comments, open a dedicated threads, but don't post your posts here.
If you want to propose some other solution, open your specific tutorial
 
Last edited:

Star-Dust

Expert
Licensed User
Longtime User
Call a JavaScript function from your injected JS source

mycode.js
mycode.js:
function myfunc (message) {
    // your code
    alert('Info: ' + message);
}

In the main of the B4J code insert the instruction that loads your JS source
main B4j:
BANano.Header.AddJavascriptFile("mycode.js")

To call your function from anywhere in your code
B4X:
BANano.RunJavascriptMethod("myfunc ", Array("Hallo"))

_________________________________________________________________________________________________________________________________________
PLEASE DO NOT WRITE IN THIS THREAD
. If you have any questions or comments, open a dedicated threads, but don't post your posts here.
If you want to propose some other solution, open your specific tutorial
 
Last edited:

Star-Dust

Expert
Licensed User
Longtime User
Calls a sub from JavaScript

Create a sub in B4J
B4X:
Sub mysub_event(message as string)
    BANano.Alert(message)
End Sub

Create your JS source by calling the SUB by entering the name (to lower case) of the b4j file (in the example myapp.b4j)
mycode.JS:
// Insert the name (to lower case) of the b4j file after _banano_
window._banano_myapp.mysub_event("Hallo");

_________________________________________________________________________________________________________________________________________
PLEASE DO NOT WRITE IN THIS THREAD
. If you have any questions or comments, open a dedicated threads, but don't post your posts here.
If you want to propose some other solution, open your specific tutorial
 
Last edited:

Star-Dust

Expert
Licensed User
Longtime User
Example of mobile panel and GoogleMaps without Vuetify
In this example I collect some of the latest suggestions. I inserted the map with a javascript code and I manage the events by calling the JS source. This will be useful in case you want to understand how to add objects that don't exist and how to connect them to the b4j subs.

You will see how moving the mouse constantly updates the position in a label and the click event on the map and finally how to insert a polygon on the map. The same method can be used to insert markers but you must add the markers element or any other element you deem useful to the JS code

You will also see a pop-up menu list activated by a hamburger-type button.

PS. In the JS code you will find a small code commented to import kml into the map... it could be useful


Please note: To work you must enter the Google key to see the map in the source code file. You will find a note on the source that tells you where to insert the key

1700725988242.png


HOW TO GET A KEY
Register your app in Google developer console: https://console.developers.google.com
You need to enable Google Maps Android API.
Then click on Credentials -> Create Credentials -> API Key -> Android Key.
You should get a key that looks like: AIzaSyCmFHamGE0O0BvxxxxxxxxXbTCSrjFVg-Q


_________________________________________________________________________________________________________________________________________
PLEASE DO NOT WRITE IN THIS THREAD
. If you have any questions or comments, open a dedicated threads, but don't post your posts here.
If you want to propose some other solution, open your specific tutorial
 

Attachments

  • example.zip
    394.8 KB · Views: 24
Last edited:
Top