B4J Question [BANano] [SOLVED] Exploring VJSF JSON Form Builder

Mashiane

Expert
Licensed User
Longtime User
Ola

Warning: This is not BANano but rather VueJS + Vuetify on top of BANano.

Attached is a very minimal project that uses Vuetify + BANano and VJSF.

The only thing one needs to make this project run is BANano and not BVAD3

Problem:

I am able to generate the HTML that is purported to work:

B4X:
<v-app id="app"><v-main id="vmain"><v-container id="container"><v-form id="vform" v-model="valid" ref="vform"><v-jsf id="vjsf" :schema="schema" :model="model" :options="options"></v-jsf></v-form><v-row id="r1" class="mt-2"><v-btn id="btn1" color="primary" v-on:click="btn1_click">Validate</v-btn></v-row></v-container></v-main></v-app>

This is based on the basic example in VJSF, here, https://codepen.io/pen/?&editors=101

The issue is that the compiled HTML returns an attribute of schema=[object Object] after I serve the project.

One can find this when right click on the web page and select Inspect...

1617192507669.png


I guess there is something I am missing somewhere. The expected result from the compilation is of this nature:

1617192654682.png


Thank you so much for trying to check this out!
 

Attachments

  • SchemaStuff.zip
    335.1 KB · Views: 117

alwaysbusy

Expert
Licensed User
Longtime User
I had a look, but as I said before, I just don't think that is possible in JavaScript: using JavaScript, you can only add attributes as Strings, not as objects. If you find some vanilla JavaScript snippet that can do this, I'll gladly look further into this (the pen doesn't show anything).
 
Upvote 0

Mashiane

Expert
Licensed User
Longtime User
you can only add attributes as Strings, not as objects.
Thanks alwaysbusy, this is also confusing me, I am feeding the attribute as a string actually. This is done with this code..

<v-app id="app"><v-main id="vmain"><v-container id="container"><v-form id="vform" v-model="valid" ref="vform"><v-jsf id="vjsf" :schema="schema" :model="model" :eek:ptions="options"></v-jsf></v-form><v-row id="r1" class="mt-2"><v-btn id="btn1" color="primary" v-on:click="btn1_click">Validate</v-btn></v-row></v-container></v-main></v-app>

From above the attribute name and value are :schema="schema"

The : signifies that the attribute needs to be bound to the state variable called schema, it could be any variable name anyway. This name then points to the object. This binding is supposed to happen when Vue is executing. This then becomes the template that I am feeding to VueJS. This is perfectly expected and has been the only way to make Vue work with BANano.

For some reason this time around, its affecting the html above as

<v-jsf id="vjsf" schema="[object Object]" ... >

On the code somewhere I had defined Dim schema As Map = CreateMap()

I am thinking that perhaps let me change this map variable name to something else and see what happens. I will revert back. Thanks again.
 
Upvote 0

DonManfred

Expert
Licensed User
Longtime User
I don´t think that you can serialize a B4X Object.
I also think this also apply to Javascript.


Points out the same. You need to serialize the DATA into an String.
Also you need to qrite a helper method to use the seialized DATA to recreate the Object.
 
Upvote 0

alwaysbusy

Expert
Licensed User
Longtime User
The : signifies that the attribute needs to be bound to the state variable called schema, it could be any variable name anyway. This name then points to the object. This binding is supposed to happen when Vue is executing. This then becomes the template that I am feeding to VueJS. This is perfectly expected and has been the only way to make Vue work with BANano.
You cannot create a :variable attribute via JavaScript, only by manually writing that in your html because HTML is based on XML, where that is allowed. So you can 'write' them manually in a html file with something like NotePad++ as the HTML5 specs do not explicitly prohibit this (and how I think Vue.js actually works) and the browser will not 'complain', but you cannot 'create' such a thing via JavaScript as it can manipulate the DOM as HTML, not as XML. Not a BANano limitation but a JavaScript/HTML limitation.

As I said, if you can show me some Javascript that can do that, I will probably be able to add it to BANano. But I can't find anything on the interweb that can do that in JavaScript. And BANano can not do 'more' than JavaScript.

Alwaysbusy
 

Attachments

  • 1617267430832.png
    1617267430832.png
    12.1 KB · Views: 112
Upvote 0

Mashiane

Expert
Licensed User
Longtime User
I hear you and understand and there is something that I think I'm not able to get about this vjsf library im trying to use. I am not assigning any object to attributes directly.

As an example, these are the steps that I make all the BVAD3 apps.

Step 1: Create the HTML using BANanoElement - this works. For example, if we wanted to create a container with a row and button. We could create the HTML code like this.

<v-app id="app"><v-main id="vmain"><v-container id="container"><v-form id="vform" v-model="valid" ref="vform"></v-form><v-row id="r1" class="mt-2"><v-btn id="btn1" :color="btncolor" v-on:click="btn1_click">Validate</v-btn></v-row></v-container></v-main></v-app>

Step 2: Set states (if available) - this works, for any "bound" component, when VueJS compiles it and during runtime, the states can be changed.

For example, above we have bound the color to a btncolor state variable, with :color="btncolor". To change the color of the button at runtime, we can just execute..

Dim btnColor As String = "red"
VueApp.SetData("btncolor", btnColor)

This produces.

1617269910872.png


If we want to change the color to green, we could execute VueAPp.SetData("btncolor', "green") also. This works and is perfectly acceptable with BANAno and Vuetify. Because I have assigned a click event to the button, I have to define it as

B4X:
Sub btn1_click(e As BANanoEvent)
    'log the refs...")
    Log(VueApp.refs)
End Sub

The click event is bound with v-on:click="btn1_click"

In all these cases, everything works without hurdles.

The issue is for some reason this vjsf library. In this case, an "object" is assigned to the state variable. Looking at the button code above, I am doing a similar thing with vjsf. Let me change this a little bit for more clarity.

Step 1 - Build html

I follow the same approach, I build the html using BANanoElement - this works

<v-jsf id="vjsf" :schema="vjsfschema">

So same rules apply. The bound attribute is :schema="vjsfschema" as an example.

Step 2- Assign States, before we were assigning a "red" string. This time we build a map called "vjsfschema"

This is VueApp.SetData("vjsfschema", schema), where the schema map is defined like below. So we are assigning a binding the variable.

I build the schema

B4X:
{
    "type": "object",
    "properties": {
        "stringProp": {
            "type": "string",
            "title": "I'm a string",
            "description": "This description is used as a help message."
        },
        "stringTextAreaProp": {
            "type": "string",
            "title": "I'm a string in a textarea",
            "description": ""
        },
        "numberProp": {
            "type": "number",
            "title": "I'm a number",
            "description": ""
        },
        "integerProp": {
            "type": "integer",
            "title": "I'm an integer",
            "description": ""
        },
        "integerSliderProp": {
            "type": "integer",
            "title": "I'm an integer in a slider",
            "description": ""
        },
        "booleanProp": {
            "type": "boolean",
            "title": "I'm a boolean",
            "description": "This description is used as a help message."
        },
        "booleanSwitchProp": {
            "type": "boolean",
            "title": "I'm a boolean with switch display",
            "description": "The description is used as a help message"
        },
        "stringArrayProp": {
            "type": "array",
            "title": "I'm an array of strings",
            "description": ""
        },
        "integerArrayProp": {
            "type": "array",
            "title": "I'm an array of integers",
            "description": ""
        }
    }
}

Then I complete the process with..

VueApp.SetData("vjsfschema", schema)

As you can see, I am not doing anything new from what I have not done before where "it worked". For some reason this time around, it does not want to budge.

I'm probably doing something wrong sowhere.

Thanks for your time anyway.[/code]
 
Upvote 0

Mashiane

Expert
Licensed User
Longtime User
Update: I see that I assumed that because the VJSF module is loaded globally inside BANano.Window via BANano.Header.AddJavaScriptFile, it was automatically linked to the "v-jsf", tag name. Big Mistake!!

1617273400942.png


So I have imported it to the VueJS components list by executing this call.

B4X:
Sub UseVJSF
    If components.ContainsKey("v-jsf") = False Then
        Dim boVJsf As BANanoObject
        boVJsf.Initialize("VJsf")
        components.Put("v-jsf", boVJsf)
    End If    
End Sub

Interestingly... its compiling but not giving me any results yet.

1617273654434.png


This is close to working, I can feel it!!!

Thanks again!
 

Attachments

  • SchemaStuff.zip
    335.9 KB · Views: 107
Upvote 0

Mashiane

Expert
Licensed User
Longtime User
Thanks a lot @alwaysbusy. Your help means a lot to me. We have lift off!!!!

1617278313885.png


Sorted it with

1.
B4X:
Sub UseVJSF
    If components.ContainsKey("v-jsf") = False Then
        Dim boVJsf As BANanoObject
        boVJsf.Initialize("VJsf")
        Dim boVJsf As BANanoObject = boVJsf.GetField("default")
        components.Put("v-jsf", boVJsf)
    End If    
End Sub

2.
The binding for v-jsf is v-model="model" and not :model="model"

Perfect!!!


In the process, I also found another lib that does the same stuff, https://github.com/activeliang/vuetify-form-base

But like this one much better due to its flexibility and awesomeness!
 

Attachments

  • SchemaStuff.zip
    236.4 KB · Views: 109
Upvote 0
Top