Mobile Javascript - Element is not defined ( Outsystems Glitch or My Mistake?)

Mobile Javascript - Element is not defined ( Outsystems Glitch or My Mistake?)

  

Cheers,

I'm writing this post because i found something that I don't fully understand. I fixed this, and it might already be common knowledge, yet I don't remember seeing it anywhere, so I just thought about sharing the knowledge. In a javascript like this:

--------------------------------------------------------------------------------------------------------

//Firebase by the way
var storage = window.firebase_access.storage().ref();
storage.child($parameters.Filename).getDownloadURL().then( function(url)
{

    var xhr = new XMLHttpRequest();
    xhr.responseType = 'blob';
    xhr.onload = function(event)
    {
        var reader = new FileReader();
        reader.onloadend = function(event)
        {  
            try
            {

                //ERROR OCCURS HERE
                document.getElementById( FirebaseStorageImage.Id ).value = reader.result;
            }
            catch (error)
            {
                alert ("Read ImageFromStorage ERROR: " + error);

                var all = document.getElementsByTagName("*");
                for (var i=0, max=all.length; i < max; i++) 

                {
                      text = text + all[i].id + '\n'
                }
                alert( text )
            }
        };
        reader.readAsText(xhr.response);
    };
    xhr.open('GET', url);
    xhr.send();
     
    }).catch(function(error)
    {
        alert("XML HTTP ERROR: " + error.message );
    }
);

--------------------------------------------------------------------------------------------------------

The problem is: ReferenceError: FirebaseStorageImage is not defined.

But that's not true. I can see the input in the screen. Furthermore, the catch part of the javascript prints the element's id as b3-FirebaseStorageImage. So the element is there. But FirebaseStorageImage is not defined? It's a widget. It exists on the screen. This javascript is called on the inputs' onchange, and there is no other javascript that changes the screen. 

It's not like I'm passing it a raw string. I understand that if I passed "FirebaseStorageImage" as an Id eventually it would give me trouble. But the FirebaseStorageImage is a widget. I copied and pasted it's name N times already, but it does not work. 

I assume the Javascript believes the FirebaseStorageImage to be a Javascript variable rather than a Outsystems widget, and since I never referenced a FiebaseStorageImage in Javascript, so the error occurs. But I believe I've used this sort of thing before without problems.

Eventually, I solved this problem, by passing the id as a parameter.

document.getElementById( $parameters.Input_ID ).value = reader.result;

And saying that Input_ID = FirebaseStorageImage.id

But I never had this problem before. Is this a glitch? A "feature"? Or did I miss/skip/forget some really important practice when studying for Outsystems Mobile?

Sorry if it's something really basic that I missed, just wanted to let other people know of this, to make sure it's knows, and doesn't steal time from other people as it did to me. :(

Outsystems Version 10.0.721.0

Hi Christian,

I'm not sure I can completely follow what you wrote above. An "OutSystems widget" is just an HTML element, and it has an Id. If you need to pass the widget to JavaScript, you always use "widget.Id". You can't directly use the widget's Service Studio name, as the Platform attaches some other stuff to it to get the actual Id.

Hey Kilian, Indeed. I guess what I meant with all of that above was that a widget was on the screen, it's name in the service center was "FirebaseStorageImage", yet in the Javascript, whenever i wrote FirebaseStorageImage.Id it threw an error saying "ReferenceError: FirebaseStorageImage is not defined". 

I assume Javascript thought it was a Javascript variable, so I passed the Id as an input parameter for the Javascript.

document.getElementById( FirebaseStorageImage.Id ).value = reader.result; // Error

document.getElementById( $parameters.Input_ID ).value = reader.result; // Works

And i gave FirebaseStorageImage.Id to the javascript input Input_Id.

Although it could because of all the (pardon me for an Grammar champion moment) "assynchronism" the javascript has. The then() and the onloadend() are assynchronous. 

So much so that I used to have output parameters, but they always came up empty, because the javascript ended and both of those functions did not run yet.

that why I have the 

document.getElementById( $parameters.Input_ID ).value = reader.result; 

it returns the value. At least after a 

document.getElementById( $parameters.Input_ID ).value = reader.result; 

document.getElementById( $parameters.Input_ID ).focus(); 

document.getElementById( $parameters.Input_ID ).blur(); // triggers on blur event, that triggers an event in a client action.

Sorry if I can't explain myself very well. :(


Solution

Hi Cristian,

FirebaseStorageImage.Id doesn't work inside a JavaScript script because FirebaseStorageImage is the name in the OutSystems context, but unknown when the browser is rendering/parsing it...

if you're building your dynamic JavaScript (in an Expression, for instance) you'd use something like:

"

{
    document.getElementById(" + FirebaseStorageImage.Id + ").value = reader.result;
}

"

If you're working on mobile, you'd want to pass the said Id as an input parameter, because those are accessible by using something $parameters.ImageID

For your JavaScript asynchronicity issues... you may want to read this. You can use the $resolve() function to force the JavaScript tool to finish only once the callback gets called.

Solution

Jorge Martins wrote:

Hi Cristian,

FirebaseStorageImage.Id doesn't work inside a JavaScript script because FirebaseStorageImage is the name in the OutSystems context, but unknown when the browser is rendering/parsing it...

if you're building your dynamic JavaScript (in an Expression, for instance) you'd use something like:

"

{
    document.getElementById(" + FirebaseStorageImage.Id + ").value = reader.result;
}

"

If you're working on mobile, you'd want to pass the said Id as an input parameter, because those are accessible by using something $parameters.ImageID

For your JavaScript asynchronicity issues... you may want to read this. You can use the $resolve() function to force the JavaScript tool to finish only once the callback gets called.

Hey Jorge, you answer worked perfectly. Looks like I did miss something. :( There goes my excuse. With $resolve() I managed to get the output without the document.getElementById().

I will have to pass ids by parameters from now on. Thank you and thanks to everyone that posted ( that means you kilian :D )


HI Christian,

Great you got it working. And thanks Jorge for the more comprehensive answer :).