Webviewer: passing a list of lists (or array of arrays) + Sqlite

Hi,

Is it possible to send to the webviewer (and retrieve in the script in "WebView Javascript Processor.thml") a variable that is formatted as a list/array (without converting it to string)?

I am able to send and retrieve my data as a string with "window.AppInventor.getWebViewString()". But my items include all kind of special characters (including single quote, double quotes, backslashes...) so being limited to sending/receiving a string involves a lot of conversion.

I am also asking this because my items are not quoted which added several more conversion steps. This is because they are retrieved from an SQLite database. Even if I use "quote" in the SELECT, the null and integer values aren't quoted. So far what I am doing to solve this, is to loop through my values and add quotes before and after each of them, and I endoded them with URIencode. I didn't find a better way to do it.

So, are there other options to send data to and from the Webviewer than to use the "window.AppInventor.getWebViewString()"?

The webViewString, as its name indicates, handles strings.

It can return a stringified json array to the app, you would need to use the JSONDecodeText block from the web component to convert it to an array object (AI2 list)

You can send an AI2 list (json array) directly to the webViewString, this is converted to a stringified json on the way.

Thanks for your reply, you're right I wasn't precise enough: I can send a AI2 list to the webViewString but because it is stringified on the way, I am not receiving a list in the webviewer.
This requires several conversions to have a properly formatted string so that I can use JSON.parse() on this string in my js script. I wanted to find an easier way but I guess I will have to properly "manually" format my value with quotes.

You should only have to var arr = JSON.parse(webViewString()) if all you send is the AI2 list ?

You may need to show some examples of what you are attempting to pass/return to a webviewer with webviewstring....

Thanks so much for your help!

Yes JSON.parse() is working great! Sorry, I mixed up 2 problems in my question, one about webViewString and one about creating a list of lists. I had some trouble formatting my sql result in a proper way so that when I pass it to webViewString, JSON.parse() could recognize it.

Here is what I ended up doing. This is using Tab Bennedum Sqlite extension that returns a list of the values separated with commas. I was trying to find another way to split my SQL result than splitting at a comma, because the values in my database could contain commas. But I didn't find a solution so what I did was to encode the commas before saving the data in my database (ex: replace them with $$%%), so that they won't mix up the parsing. I am curious to know if there is a better way to do it than this!

Well as I said, show an example of the raw output from your sqlite query, then perhaps we can help ?

Sorry I didn't understand. Here is an example of a raw output with 4 rows. There are only 5 columns: id, name, date, comment1, symbol (comment includes characters like , " and '). There are other columns between comment and symbol, some formatted as text and some formated as integer.

[[1, Name1, 2022-03-10 16:11:08, Great selection of products, including some "hard-to-find" items,⚠], [2, Name2, 2021-09-13 06:51:19, Friendly and knowledgeable, providing excellent customer service, ●], [3, Name3, 2023-01-31 12:24:37, The prices were a bit high, but the quality of the products made it worth the extra cost, ≠], [4, Name4, 2022-12-01 18:27:09, null, ¤]]

Just off the top of my head...

Add the first three items and the last item,to a list. Remove the first three items and the last item. Add the remaining item the the list at index 4. Repeat for other lists.

Thanks a lot, I wouldn't have thought of doing it that way! That could have been a good solution but I have other columns in between that could also contain commas. I simplified the example, to keep it simple, but here is a more complete example:

[1, Name1, 2022-03-10 16:11:08, Great selection of products, including some "hard-to-find" items, top, right, round, red, shiny, 0,0,0, null, :warning:]

The middle part is actually 3 columns:

  • 1
  • Name1
  • 2022-03-10 16:11:08
  • Great selection of products, including some "hard-to-find" items
  • top, left, third row, behind
  • round 3, red, shiny 9
  • 0
  • 0
  • 0
  • null
  • :warning:

You might try this:

Thanks for taking the time to find these queries.

I tried concat but it's not working (in DB browser for SQLite the error is "no such function: concat", your Simplesqlite extension returns [completed]).

When I use the symbol || to add " around the value, strangely 2 double quotes are added on each side. For example, this query SELECT '"'|| comment || '"' from maintable returns:
[""some comment"", ""another comment"".....]. However, I am able to use the || as expected in other queries:

where events. Time < date('now',"-" || data. Delay || " hours")

or even

SELECT 
  'SELECT ' || 
  group_concat('QUOTE(' || t.table_name || '.' || c.name || ')', ', ') || 
  ' FROM ' || t.table_name || ';'
FROM (
  SELECT name AS table_name FROM sqlite_master WHERE type='table'
) t
JOIN pragma_table_info(t.table_name) c
GROUP BY t.table_name;

I tried several other combinaisons with the double quote and || but none returns just a single quote on each side of the value.

I would need to dig out an example project from my history to do some testing.....

Thanks a lot. For the moment, I will continue with "recoding" the commas and the double quotes in my db to prevent any column confusion in the output.

Does the ListFixer block not fix it all for you ?

image

Thanks so much for having looked into it. And, I am sorry, I should have done it. Once I got your extension to work, I totally forgot about this block. This is embarrassing, I am sorry.

I tried several combinations with comma, single and double quote and each time it was able to retrieve the whole value. So, it's working great on the block side.

But it doesn't work in webview: when I use double quotes in a value, then var arr = JSON.parse"window.AppInventor.getWebViewString()) doesn't work. If I escape the double quotes, then JSON.parse() works.

This is where a window.AppInventor.getWebViewList would come in handy so that we wouldn't have to escape the double quotes.

And again thanks so much for your help and your great extension!

I did a substitution of double quotes to single quotes in fields, this then appears to parse OK in the webviewer....

image

Thanks for your example and for the block picture. It's strange I am not able to make it work when replacing a double quote with a simple quote. I have tried several ways and triple check everything (even restarting twice from the very beginning) without success. What works though is to replace all the double quotes with \". In any case, I can't replace the double quotes with single quotes because my user will see the comment. By adding a , I can then properly recode the double quotes in .js (which I can't if there are turn into ' as I won't be able to differentiate them from real ').

But it gets more complicated because my users will not only see previous comments but also add new comments possibly with single quotes, doubles quotes and comma. And I am able to save new comments containing , " and ' but only if I add a second ' before any ' in the comment and if I had single quotes around the text as in 'a simple, short, "example" (double quotes), that ''works'' (double single quotes) great'.

But then JSON.parse isn't working anymore even after retrieving the data with ListFixer and using a replace block to replace all the double quotes with \". Simply deleting the double quote from the db (via a sqlite editor), makes JSON.parse work again. But if before saving in the db, I add a \ before each " then, I can do everything without any error: saving in db, retrieving from the db and JSON.parsing.

You have not really indicated what you are doing in your javascript? Does it have to be done there, or could this be done with blocks ?

For the test I am talking about here, I am only retrieving the webviewstring and parsing it in JSON and then set it as the content of a div:

var appInventorInput = window.AppInventor.getWebViewString();
var appInventorInputAsJSON = JSON.parse(appInventorInput)
document.getElementById("json").textContent = JSON.stringify(appInventorInputAsJSON, null, 2)
When I write that it's not working, it means that the div "json" doesn't display the json.

I am building a UI with the result of the query so it's more flexible to use the webview.

Another thing that could influence the problem with the double quotes, is that I was retrieving the sql without the column headers. I will test if this affects the parsing when I turn it on.