B4J Question [ABMaterial] Question about ABMCustomComponent

CGP

Member
Licensed User
Longtime User
Hi,

I'm trying to add some custom gauges with ABMCustomComponent and this code:

B4X:
page.AddExtraJavaScriptFile("custom/justgage.js") 
page.AddExtraJavaScriptFile("custom/raphael-2.1.4.min.js")

B4X:
Dim custGauge As GaugeClass
custGauge.Initialize(page, "custGauge", 25, "Test")
page.Cell(2,1).AddComponent(custGauge.ABMComp)

GaugeClass
B4X:
Sub Class_Globals
    Dim ABMComp As ABMCustomComponent
    Private myValue As Int
    Private myLabel As String
End Sub

'Initializes the object. You can add parameters to this method if needed.
Public Sub Initialize(InternalPage As ABMPage, ID As String, value As Int, name As String)
    ABMComp.Initialize("ABMComp", Me, InternalPage, ID)
    myValue = value
    myLabel = name
End Sub

Sub ABMComp_Build(internalID As String) As String
    Return $"<div id="${internalID}"></div>"$
End Sub

' Is useful to run some initalisation script.
Sub ABMComp_FirstRun(InternalPage As ABMPage, internalID As String)
    Dim script As String = $"
                            var g1 = new JustGage({
                             id: "${internalID}",
                             value: ${myValue},
                             Min: 0,
                             Max: 100,
                             relativeGaugeSize: true,
                             title: "${myLabel}"
                           });"$

     InternalPage.ws.Eval(script, Array As Object(ABMComp.ID))
    ' flush not needed, it's done in the refresh method in the lib
End Sub

' runs when a refresh is called
Sub ABMComp_Refresh(InternalPage As ABMPage, internalID As String)
   
End Sub

' do the stuff needed when the object is removed
Sub ABMComp_CleanUp(InternalPage As ABMPage, internalID As String)
End Sub

My question is: How can update gauge value once page is already loaded? It's possible to make something like this?

B4X:
Dim mygauge As GaugeClass = page.Component("custGauge")
mygauge.update(50)

Thanks in advance.
 

alwaysbusy

Expert
Licensed User
Longtime User
You can do this in the Sub ABMComp_Refresh() method. I don't know this javascribt library but it may be as simple as like this (I'm guessing here):

B4X:
Dim script as String = $"var gl = document.getElementById('${internalID}')
                                gl.JustGage.value=${myValue}"$
InternalPage.ws.Eval(script, Null)

Make your myValue public instead of private in your class.

And then in you B4J code:

B4X:
custGauge.myValue = 150
custGauge.Refresh

Or the javascript library may have a seperate method for it, something like gl.JustGage.setValue(). You have to check their documentation.
 
Upvote 0

CGP

Member
Licensed User
Longtime User
Thanks for the answer @alwaysbusy, I've tried without luck :(. I got:
B4X:
VM29356:3 Uncaught TypeError: g1.refresh is not a function

With this html code and executing g1.refresh(50) on chrome console, gauge was updated successfully.
HTML:
<!doctype html>
<html>

  <head>
    <meta charset="utf-8" />
    <title>Test</title>
  </head>

  <body>
    <div class="wrapper">
      <div class="box">
        <div id="g1" class="gauge"></div>
      </div>
    </div>
    <script src="../raphael-2.1.4.min.js"></script>
    <script src="../justgage.js"></script>
    <script>
    var g1 = new JustGage({id:"g1",value:getRandomInt(0,100),min:0,max:100,title:"Test"});
    </script>
  </body>

</html>
 
Upvote 0

alwaysbusy

Expert
Licensed User
Longtime User
It looks like we have to be a bit creative because this javascript library does not connect its parent tag with the created JustGage.

We will have to keep track of the JustGage variable ourselves by adding a script tag in the build:

B4X:
Sub ABMComp_Build(internalID As String) As String
  Return $"<div id="${internalID}"></div><script>var _${internalID};</script>"$
End Sub

The complete CustomGauge class (notice we use _${internalID} instead of your g1 variable):

B4X:
Sub Class_Globals
   Public ABMComp As ABMCustomComponent
  Public myValue As Int
  Public myLabel As String
End Sub

'Initializes the object. You can add parameters to this method if needed.
Public Sub Initialize(InternalPage As ABMPage, ID As String, value As Int, name As String)
  ABMComp.Initialize("ABMComp", Me, InternalPage, ID)
  myValue = value
  myLabel = name
End Sub

Sub ABMComp_Build(internalID As String) As String
  Return $"<div id="${internalID}"></div><script>var _${internalID};</script>"$
End Sub

' Is useful to run some initalisation script.
Sub ABMComp_FirstRun(InternalPage As ABMPage, internalID As String)
  Dim script As String = $"_${internalID} = new JustGage({
  id: "${internalID}",
  value: ${myValue},
  Min: 0,
  Max: 100,
  relativeGaugeSize: true,
  title: "${myLabel}"
  });"$

  InternalPage.ws.Eval(script, Array As Object(ABMComp.ID))
  ' flush not needed, it's done in the refresh method in the lib
End Sub

' runs when a refresh is called
Sub ABMComp_Refresh(InternalPage As ABMPage, internalID As String)
  Dim script As String = $"_${internalID}.refresh(${myValue});"$
  InternalPage.ws.Eval(script, Null)
End Sub

' do the stuff needed when the object is removed
Sub ABMComp_CleanUp(InternalPage As ABMPage, internalID As String)

End Sub

Usage:

We'll need to make our custGauge a global variable on the page.

B4X:
Sub Class_Globals
  Dim custGauge As CustomGauge
  ...

Sub BuildPage()
  ...
  page.AddExtraJavaScriptFile("custom/justgage.js")
  page.AddExtraJavaScriptFile("custom/raphael-2.1.4.min.js")
  ...

Sub ConnectPage()
  ...
  custGauge.Initialize(page, "custGauge", 25, "Test")
  page.Cell(7,1).AddComponent(custGauge.ABMComp)

  Dim custGaugebtn1 As ABMButton
  custGaugebtn1.InitializeRaised(page, "custGaugebtn1", "", "", "BUTTON", "")
   page.Cell(7,1).AddComponent(custGaugebtn1)
   ...

Sub custGaugebtn1_Clicked(Target As String)
   custGauge.myValue = Rnd(10,100)
   custGauge.ABMComp.Refresh
End Sub

And just like that, it looks like a fun new component we've got in ABMaterial!

abmcustgauge.png
 
Last edited:
Upvote 0
Top