Dim chosen As String = $"
<select id="prueba" data-placeholder="Choose a Country..." tabindex="2" class="chosen-select" ">
<option value=""></option>
<option value="United States">United States</option>
<option value="United Kingdom">United Kingdom</option>
<option value="Afghanistan">Afghanistan</option>
<option value="Aland Islands">Aland Islands</option>
<option value="Albania">Albania</option>
<option value="Algeria">Algeria</option>
<option value="American Samoa">American Samoa</option>
<option value="Andorra">Andorra</option>
<option value="Angola">Angola</option>
<option value="Anguilla">Anguilla</option>
<option value="Antarctica">Antarctica</option>
<option value="Antigua and Barbuda">Antigua and Barbuda</option>
<option value="Argentina">Argentina</option>
<option value="Armenia">Armenia</option>
<option value="Aruba">Aruba</option>
<option value="Australia">Australia</option>
<option value="Austria">Austria</option>
<option value="Azerbaijan">Azerbaijan</option>
<option value="Bahamas">Bahamas</option>
<option value="Bahrain">Bahrain</option>
</select>
"$
ABM.AddHTML(page,"r10c1",chosen)
page.Cell(10,1).SetOffsetSize(0,0,0,12,12,4)
page.Refresh
Dim script As String = $"
$(document).ready(function () {
$(".chosen-select").chosen({
disable_search_threshold: 10,
no_results_text: "Oops, nothing found!",
width: "110%"
});
$(".chosen-search-input").css("width","90%")
$(".chosen-search-input").prop("type","")
});
"$
' Tell the browser we finished loading
page.FinishedLoading
' restoring the navigation bar position
page.RestoreNavigationBarPosition
page.ws.Eval(script,Null)
page.AddExtraJavaScriptFile("custom/chosen.jquery.min.js")
page.AddExtraCSSFile("custom/chosen.min.css")
Dim cont As ABMContainer
cont.Initialize(page,"cont","")
cont.AddRows(1,False,"").AddCells12(2,"")
cont.BuildGrid
page.Cell(4,1).AddComponent(cont)
Dim selectize As SelectizeCus
Dim lista As List
lista.Initialize
lista = listaselectize(lista, "1a", "Prueba1", "Texto1")
lista = listaselectize(lista, "2b", "Prueba2", "Texto2")
lista = listaselectize(lista, "3c", "Prueba3", "Texto3")
lista = listaselectize(lista, "4f", "Prueba4", "Texto4")
selectize.Initialize(page, "selectize1", lista, "Select something", "asc")
cont.Cell(1,1).AddComponent(selectize.ABMComp)
Sub listaselectize(lista As List, id As String, campo1 As String, campo2 As String) As List
Dim elementos As Map
elementos.Initialize
elementos.Put("id",id)
elementos.Put("campo1",campo1)
elementos.Put("campo2",campo2)
lista.Add(elementos)
Return lista
End Sub
page.AddExtraJavaScriptFile("custom/selectize.min.js")
page.AddExtraCSSFile("custom/selectize.css")
page.AddExtraCSSFile("custom/selectize.bootstrap3.css")
page.AddExtraCSSFile("custom/selectize-doble.css")
You should always use an ABMCustomComponent. The way used above is only a component on the browserside, with no equivalent on the server side and will never work. (it has no refresh, no FirstRun etc) all stuff ABM does really need to function correctly. e.g. doing a cell refresh alone can undo whatever you have written.
' Class module
Sub Class_Globals
Dim ABM As ABMaterial 'ignore
Dim ABMComp As ABMCustomComponent
Dim options As String
Dim placeh As String
Dim orden As String
Dim myB4JID As String
Dim myHTMLID 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, lista_valores As List, placeholder As String, ordenamiento As String)
Dim CSS As String = $""$
myB4JID = ID.ToLowerCase ' for our javascript variable (1), our event (2) and ws.eval (3)
ABMComp.Initialize("ABMComp", Me, InternalPage, ID, CSS)
' see further in the text why we do this
ABMComp.Tag = Me
Dim json As JSONGenerator
Dim optionsmap As Map
optionsmap.Initialize
optionsmap.Put("options",lista_valores)
json.Initialize(optionsmap)
options = json.ToPrettyString(1)
placeh = placeholder
orden = ordenamiento
End Sub
Sub ABMComp_Build(InternalPage As ABMPage, internalID As String) As String
myHTMLID = internalID
Log("myB4JID: " & myB4JID)
Log("myHTMLID: " & myHTMLID)
Return $"<div class="control-group">
<select id="${internalID}" class="contacts" placeholder="${placeh}"></select>
</div>var _${myB4JID};"$ ' (1) don't forget making a variable if you want to use it later (e.g. to call a method of the javascript component
End Sub
' Is useful to run some initalisation script.
Sub ABMComp_FirstRun(InternalPage As ABMPage, internalID As String)
Dim script As String = $"_${myB4JID} = $('#${myHTMLID}').selectize({
maxItems: 1,
valueField: 'id',
labelField: 'campo1',
searchField: ['campo1','campo2'],
sortField: [
{field: 'campo1', direction: '${orden}'},
{field: 'campo2', direction: '${orden}'}
],
${options.SubString2(1,options.Length-1)},
render: {
item: function(item, escape) {
var name = item.campo1;
return '<div>' + (name ? '<span class="campo1">' + escape(name) + '</span>' : '') + '</div>';
},
option: function(item, escape) {
var name = item.campo1;
var label = name || item.campo2;
var caption = name ? item.campo2 : null;
return '<div>' +
'<span class="label">' + escape(label) + '</span>' +
(caption ? '<span class="caption">' + escape(caption) + '</span>' : '') +
'</div>';
}
},
onChange: function (value) {
b4j_raiseEvent('page_parseevent', {'eventname': '${myB4JID}' + '_onchange','eventparams': 'value', 'value': value}); // (2)
}
});
if (!($('#${myHTMLID}').hasClass('contacts'))) {
$('#${myHTMLID}').addClass('contacts');
}
if (!($('.selectize-control').hasClass('contacts'))) {
$('.selectize-control').addClass('contacts');
}"$
InternalPage.ws.Eval(script, Array As Object(myB4JID)) ' (3)
' here we don't need to flush as it passes through ABM
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)
ABMComp.Tag = null
End Sub
Public Sub Visibility(InternalPage As ABMPage, hide As Boolean)
Dim script As String = ""
If Not(hide) Then
script = $"$("#${myHTMLID}-selectized").parent('div').parent('div').attr("hidden","true");"$
Else
script = $"$("#${myHTMLID}-selectized").parent('div').parent('div').removeAttr( "hidden");"$
End If
InternalPage.ws.Eval(script, Null)
InternalPage.ws.Flush ' here we must manually flush as this does not pass through ABM
End Sub
Public Sub Enabled(InternalPage As ABMPage, enable As Boolean)
Dim script As String = ""
If enable Then
script = $"var $select = $("#${myHTMLID}").selectize();
$select[0].selectize.enable();"$
Else
script = $"var $select = $("#${myHTMLID}").selectize();
$select[0].selectize.disable();"$
End If
InternalPage.ws.Eval(script, Null) ' here we must manually flush as this does not pass through ABM
End Sub
Sub Class_Globals
...
Private visibleToggle As Boolean = True
Private enableToggle As Boolean = True
End Sub
page.AddExtraJavaScriptFile("custom/selectize.min.js")
page.AddExtraCSSFile("custom/selectize.css")
page.AddExtraCSSFile("custom/selectize.bootstrap3.css")
page.AddExtraCSSFile("custom/selectize-doble.css")
public Sub ConnectPage()
' connecting the navigation bar
ABMShared.ConnectNavigationBar(page)
Dim cont As ABMContainer
cont.Initialize(page,"cont","")
cont.AddRows(1,False,"").AddCells12(2,"")
cont.BuildGrid
page.Cell(1,1).AddComponent(cont)
Dim lista As List
lista.Initialize
lista = listaselectize(lista, "1a", "Prueba1", "Texto1")
lista = listaselectize(lista, "2b", "Prueba2", "Texto2")
lista = listaselectize(lista, "3c", "Prueba3", "Texto3")
lista = listaselectize(lista, "4f", "Prueba4", "Texto4")
Dim selectize As Selectisize
selectize.Initialize(page, "selectize1", lista, "Select something", "asc")
cont.Cell(1,1).AddComponent(selectize.ABMComp)
Dim btnToggleVisibility As ABMButton
btnToggleVisibility.InitializeFlat(page, "btnToggleVisibility", "", "", "Toggle Visibility", "")
page.Cell(3,1).AddComponent(btnToggleVisibility)
Dim btnToggleEnabled As ABMButton
btnToggleEnabled.InitializeFlat(page, "btnToggleEnabled", "", "", "Toggle Enabled", "")
page.Cell(4,1).AddComponent(btnToggleEnabled)
' refresh the page
page.Refresh
' Tell the browser we finished loading
page.FinishedLoading
' restoring the navigation bar position
page.RestoreNavigationBarPosition
End Sub
Sub listaselectize(lista As List, id As String, campo1 As String, campo2 As String) As List
Dim elementos As Map
elementos.Initialize
elementos.Put("id",id)
elementos.Put("campo1",campo1)
elementos.Put("campo2",campo2)
lista.Add(elementos)
Return lista
End Sub
Sub selectize1_OnChange(value As String)
Log(value)
End Sub
Sub btnToggleVisibility_Clicked(Target As String)
Dim cont As ABMContainer = page.Component("cont")
Dim selectizeABMComp As ABMCustomComponent = cont.Component("selectize1")
Dim selectize As Selectisize = selectizeABMComp.Tag
visibleToggle = Not(visibleToggle)
selectize.Visibility(page, visibleToggle)
End Sub
Sub btnToggleEnabled_Clicked(Target As String)
Dim cont As ABMContainer = page.Component("cont")
Dim selectizeABMComp As ABMCustomComponent = cont.Component("selectize1")
Dim selectize As Selectisize = selectizeABMComp.Tag
enableToggle = Not(enableToggle)
selectize.Enabled(page, enableToggle)
End Sub
You were pretty close, except you used some wrong IDs. Because you've put it in a container, the ID you pass is not necessary the same as the internalID passed. (you can see it in the logs in ABMComp_Build). So whenever you want to do some jQuery stuff (like a selector), you will have to use the passed InternalID (as this is the real one in the HTML).
To make it simple in this example I created two variables: myB4JID and myHTMLID.
We only use the original passed ID in Initialize() for 'B4J' stuff, like defining an event or running a page.ws.eval(). In this case I also used it for the variable in javascript that will hold the selectize var '_initialize1' because the interalID contains a dash (cont-initialize1) and that would create an invalid javascript variable '_cont-initialize1'.
This component may not look 100% as intended. This is because it uses Bootstrap and their CSS may conflict with Materialize CSS.
It is also better to use the typical ABM b4j_raiseEvent('page_parseevent', {'eventname': '${OriginalID}' + '_onchange','eventparams': 'value', 'value': value}); syntax as then it passes smoothly through ABMs event parser.
Our class Selectisize
B4X:' Class module Sub Class_Globals Dim ABM As ABMaterial 'ignore Dim ABMComp As ABMCustomComponent Dim options As String Dim placeh As String Dim orden As String Dim myB4JID As String Dim myHTMLID 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, lista_valores As List, placeholder As String, ordenamiento As String) Dim CSS As String = $""$ myB4JID = ID.ToLowerCase ' for our javascript variable (1), our event (2) and ws.eval (3) ABMComp.Initialize("ABMComp", Me, InternalPage, ID, CSS) ' see further in the text why we do this ABMComp.Tag = Me Dim json As JSONGenerator Dim optionsmap As Map optionsmap.Initialize optionsmap.Put("options",lista_valores) json.Initialize(optionsmap) options = json.ToPrettyString(1) placeh = placeholder orden = ordenamiento End Sub Sub ABMComp_Build(InternalPage As ABMPage, internalID As String) As String myHTMLID = internalID Log("myB4JID: " & myB4JID) Log("myHTMLID: " & myHTMLID) Return $"<div class="control-group"> <select id="${internalID}" class="contacts" placeholder="${placeh}"></select> </div>var _${myB4JID};"$ ' (1) don't forget making a variable if you want to use it later (e.g. to call a method of the javascript component End Sub ' Is useful to run some initalisation script. Sub ABMComp_FirstRun(InternalPage As ABMPage, internalID As String) Dim script As String = $"_${myB4JID} = $('#${myHTMLID}').selectize({ maxItems: 1, valueField: 'id', labelField: 'campo1', searchField: ['campo1','campo2'], sortField: [ {field: 'campo1', direction: '${orden}'}, {field: 'campo2', direction: '${orden}'} ], ${options.SubString2(1,options.Length-1)}, render: { item: function(item, escape) { var name = item.campo1; return '<div>' + (name ? '<span class="campo1">' + escape(name) + '</span>' : '') + '</div>'; }, option: function(item, escape) { var name = item.campo1; var label = name || item.campo2; var caption = name ? item.campo2 : null; return '<div>' + '<span class="label">' + escape(label) + '</span>' + (caption ? '<span class="caption">' + escape(caption) + '</span>' : '') + '</div>'; } }, onChange: function (value) { b4j_raiseEvent('page_parseevent', {'eventname': '${myB4JID}' + '_onchange','eventparams': 'value', 'value': value}); // (2) } }); if (!($('#${myHTMLID}').hasClass('contacts'))) { $('#${myHTMLID}').addClass('contacts'); } if (!($('.selectize-control').hasClass('contacts'))) { $('.selectize-control').addClass('contacts'); }"$ InternalPage.ws.Eval(script, Array As Object(myB4JID)) ' (3) ' here we don't need to flush as it passes through ABM 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) ABMComp.Tag = null End Sub Public Sub Visibility(InternalPage As ABMPage, hide As Boolean) Dim script As String = "" If Not(hide) Then script = $"$("#${myHTMLID}-selectized").parent('div').parent('div').attr("hidden","true");"$ Else script = $"$("#${myHTMLID}-selectized").parent('div').parent('div').removeAttr( "hidden");"$ End If InternalPage.ws.Eval(script, Null) InternalPage.ws.Flush ' here we must manually flush as this does not pass through ABM End Sub Public Sub Enabled(InternalPage As ABMPage, enable As Boolean) Dim script As String = "" If enable Then script = $"var $select = $("#${myHTMLID}").selectize(); $select[0].selectize.enable();"$ Else script = $"var $select = $("#${myHTMLID}").selectize(); $select[0].selectize.disable();"$ End If InternalPage.ws.Eval(script, Null) ' here we must manually flush as this does not pass through ABM End Sub
I also took the opportunity to demonstrate a good use of the .Tag to run our Visibility and Enabled methods: we attach the parent class of the component to our ABMComp component.
In the page, we add a couple of variables to simulate a toggle:
B4X:Sub Class_Globals ... Private visibleToggle As Boolean = True Private enableToggle As Boolean = True End Sub
in BuildPage we add the custom css/js files (TIP: try to merge the CSS files in one file, it will be faster)
B4X:page.AddExtraJavaScriptFile("custom/selectize.min.js") page.AddExtraCSSFile("custom/selectize.css") page.AddExtraCSSFile("custom/selectize.bootstrap3.css") page.AddExtraCSSFile("custom/selectize-doble.css")
In ConnectPage() we add out component and a couple of buttons:
B4X:public Sub ConnectPage() ' connecting the navigation bar ABMShared.ConnectNavigationBar(page) Dim cont As ABMContainer cont.Initialize(page,"cont","") cont.AddRows(1,False,"").AddCells12(2,"") cont.BuildGrid page.Cell(1,1).AddComponent(cont) Dim lista As List lista.Initialize lista = listaselectize(lista, "1a", "Prueba1", "Texto1") lista = listaselectize(lista, "2b", "Prueba2", "Texto2") lista = listaselectize(lista, "3c", "Prueba3", "Texto3") lista = listaselectize(lista, "4f", "Prueba4", "Texto4") Dim selectize As Selectisize selectize.Initialize(page, "selectize1", lista, "Select something", "asc") cont.Cell(1,1).AddComponent(selectize.ABMComp) Dim btnToggleVisibility As ABMButton btnToggleVisibility.InitializeFlat(page, "btnToggleVisibility", "", "", "Toggle Visibility", "") page.Cell(3,1).AddComponent(btnToggleVisibility) Dim btnToggleEnabled As ABMButton btnToggleEnabled.InitializeFlat(page, "btnToggleEnabled", "", "", "Toggle Enabled", "") page.Cell(4,1).AddComponent(btnToggleEnabled) ' refresh the page page.Refresh ' Tell the browser we finished loading page.FinishedLoading ' restoring the navigation bar position page.RestoreNavigationBarPosition End Sub Sub listaselectize(lista As List, id As String, campo1 As String, campo2 As String) As List Dim elementos As Map elementos.Initialize elementos.Put("id",id) elementos.Put("campo1",campo1) elementos.Put("campo2",campo2) lista.Add(elementos) Return lista End Sub
We define our event:
B4X:Sub selectize1_OnChange(value As String) Log(value) End Sub
And in our buttons we make use of the .Tag value we've set before to get our ABMCustomComponents 'wrapper' class:
B4X:Sub btnToggleVisibility_Clicked(Target As String) Dim cont As ABMContainer = page.Component("cont") Dim selectizeABMComp As ABMCustomComponent = cont.Component("selectize1") Dim selectize As Selectisize = selectizeABMComp.Tag visibleToggle = Not(visibleToggle) selectize.Visibility(page, visibleToggle) End Sub Sub btnToggleEnabled_Clicked(Target As String) Dim cont As ABMContainer = page.Component("cont") Dim selectizeABMComp As ABMCustomComponent = cont.Component("selectize1") Dim selectize As Selectisize = selectizeABMComp.Tag enableToggle = Not(enableToggle) selectize.Enabled(page, enableToggle) End Sub
I hope this will get you started!
Alwaysbusy