B4J Question [SOLVED]ABMaterial - problem with $ in string literals

JackKirk

Well-Known Member
Licensed User
Longtime User
I have developed this little nugget of javascript using a WYSIWYG HTML editor and lots of grafting with Microsoft Copilot:

B4X:
    // Populate the select with the names
    for (let i = 1; i <= nonames; i++) {
        const option = document.createElement('option');
        //In following 2 statements backticks (`) are used for template
        //literals (also known as template strings) in JavaScript.
        //Template literals allow you to embed expressions within a string
        //using `${}` syntax
        option.value = eval(`name${i}`);
        option.textContent = eval(`name${i}`);
        selectName.appendChild(option);
    }

There is more than this but this is where my problem is.

I have it all working nicely external to ABMaterial.

When I insert this into ABMaterial as follows:
B4X:
Sub ABMComp_Refresh(Passed_page As ABMPage, Passed_Instance_Name As String)

    Private script_str As String = $"
 
...

    // Populate the select with the names
    for (let i = 1; i <= nonames; i++) {
        const option = document.createElement('option');
        //In following 2 statements backticks (`) are used for template
        //literals (also known as template strings) in JavaScript.
        //Template literals allow you to embed expressions within a string
        //using `${}` syntax
        option.value = eval(`name${i}`);
        option.textContent = eval(`name${i}`);
        selectName.appendChild(option);
    }

...
 
"$
 
    Parent_Page.ws.Eval(script_str, Array As Object(Passed_Instance_Name))
 
End Sub

The B4J IDE objects with "... Undeclared variable 'i' is used before it was assigned any value." - the i it is referring to is the i in eval(`name${i}`)

And I can find no way to fix it - any help greatly appreciated.
 
Last edited:

Daestrum

Expert
Licensed User
Longtime User
Will
B4X:
    Private dollar As String = "$"
    Private script_str As String = $"   
    // Populate the select with the names
    for (let i = 1; i <= nonames; i++) {
        const option = document.createElement('option');
        //In following 2 statements backticks (`) are used for template
        //literals (also known as template strings) in JavaScript.
        //Template literals allow you to embed expressions within a string
        //using `${dollar}{}` syntax
        option.value = eval(`name${dollar}{i}`);
        option.textContent = eval(`name${dollar}{i}`);
        selectName.appendChild(option);
    }
"$

work for you?
It produces:

// Populate the select with the names
for (let i = 1; i <= nonames; i++) {
const option = document.createElement('option');
//In following 2 statements backticks (`) are used for template
//literals (also known as template strings) in JavaScript.
//Template literals allow you to embed expressions within a string
//using `${}` syntax
option.value = eval(`name${i}`);
option.textContent = eval(`name${i}`);
selectName.appendChild(option);
}
 
Last edited:
Upvote 0

JackKirk

Well-Known Member
Licensed User
Longtime User
work for you?
Daestrum, thanks for your response - it works!

Overnight I also came up with an alternate fix:
B4X:
Sub ABMComp_Refresh(Passed_page As ABMPage, Passed_Instance_Name As String)

    Private script_str As String = $"
 
...

    // Populate the select with the names
    for (let i = 1; i <= nonames; i++) {
        const option = document.createElement('option');
        //In following 2 statements backticks (`) are used for template
        //literals (also known as template strings) in JavaScript.
        //Template literals allow you to embed expressions within a string
        //using string1 syntax
        option.value = eval(string2);
        option.textContent = eval(string2);
        selectName.appendChild(option);
    }

...
 
"$
 
    script_str = script_str.Replace("string1", "`${}`")   
    script_str = script_str.Replace("string2", "`name${i}`")   
 
    Parent_Page.ws.Eval(script_str, Array As Object(Passed_Instance_Name))
 
End Sub
which also works - but I will use yours as it seems a little more elegant :)
 
Upvote 0
Top