window.onload not firing in Reactive Web App (and questions about block lifecycle)

Hi

In summary, what I'm currently trying to make is a screen similar to the drawing below. The middle container will be a web block containing a 'textarea' widget, which I customized to auto-resize depending on its contents.



In this internal web block, the autoresize function of the 'textarea' is triggered via the js 'input' event, and it works. I also have functions attributed to 'contextmenu' events, and they also work.

One situation that the screen might encounter is having the internal web block already with an input text in it, therefore, the 'textarea' will have to autoresize during initialization, so all contents show properly to the user. This can be done (and was tested) by simply using js to manually trigger the 'input' event of the 'textarea'.

The problem comes here. When I test the internal web block isolated from the rest of the screen, everything works fine (I bind the triggering of the 'input' event to the web block's 'ready' state). However, when I test the full screen, the 'input' event ends up triggering sometime before the full content is loaded, and consequently the autoresize does not work.

My suspicion is that, as I bind the manual trigger of the event to the 'ready' state of the internal web block, the full screen reaches its 'ready' state at a different point and triggers the event at the incorrect time.

From my understating of js, I thought then that binding the same event to the 'load' event of the window would make the trigger occur at the correct time. However, I made several tests and came to the conclusion that the 'load' event never fires in my Web Reactive App. I used two syntaxes to bind the event - jquery and normal js - but still did not work. I even tested with chrome's debugger console to assure that the 'load' event was not overloaded or removed, and I saw that it returned the exact function that I declared before.

Are there issues withe the 'load' event in Reactive Web Apps? When using screens with processes during 'oninitialize', 'onready' and 'onready' sort of events and several web blocks within: is there some hierarchy between the order of the processes, or are these processes executed concurrently with one another? For example: two web blocks inside a screen have different js 'onready' processes set. Are they executed at the same time or is one executed before another, depending on element nesting, or screen position, for instance?

Just as an update: I ran the debugger on chrome and verified that the 'load' event actually fires when starting the page. I saw scripts related to 'include.preload.js' and two others running functions declared for the 'load' event.

However, I still didn't discover why my own defined 'load' functions don't work. The only way to fire them is to explicitly trigger them using the console. One thing I noticed is that the functions that are triggered during the page initialization aren't triggered when I manually call 'load', only my own defined function is called.

Hi Bruno,

I think your major problem is that you chose the ready event, but other than a http request in traditional, in reactive the screen or block being ready doesn't mean that all data is available yet.  I guess the text to show in your blocks text area is retrieved somehow by the screen or block through a server action or aggregate.  In that case, if this takes some time to come back from the server, your trigger has already passed, and then the value becomes available, meaning that the size of the input doesn't fit it.  

What you need is to trigger the adjusting of the width in the onRender event of the webblock instead of the OnREady event.

Hope this helps,

Dorine


EDIT , I tried this out in a small oml, I don't know javascript so I don't know how to get the oninput event and the right formula for calculating the correct lenght, but it does demonstrate how putting the javascript in the onrender makes sure the width adjusts when the value comes back from server.


EDIT2 : on a different note, I would imagine that it might be more appropriate to do this kind of styling using CSS, but wouldn't know how, just a feeling.

Thanks for the reply Dorine (and sorry for the late reply from my part).

I'll take a look to see how I implemented this, to verify if your solution works or not. The issue is that, even if I go in a blank page and set only a js block with an alert to be fire during the onload event (I set this using the oninitialize event of Outsystems, and using the 'window.onload = ... syntax'), nothing happens. I did some testing on my part and I believe that internal outsystems scripts actually fire during onload, however user scripts doesn't seem to work in the same way.


I also would like to solve this with css, but it doesn't seem to exist any 'resizable textarea' solution without the use of javascript. If there is, I'd like to know more about it.

Hiu Bruno,

I feel like you might be making it more difficult than it needs to be.

As far as I understand your first post, you have no problem resizing when user types into it, since then the input event triggers, you only have a problem whenever the widget renders with already a value in it, right ?

So you have at some point decided that, in order to do this, you need to 'manually trigger' the input event and are now down this unholy path of trying to find the right spot to do it.  You think the right spot is the window onload, but can't seem to get to it, right ?

As the data retrieval happens on a parallel path with all the screen events firing, I think the onRender is the only one of which you are sure it will run (again) after the data for you input becomes available.  Even if you can somehow hook into the onload, why do you think the value in the input will be already known at that point ?

Good luck and let us know how you made it work,

Dorine

Dorine Boudry wrote:

As far as I understand your first post, you have no problem resizing when user types into it, since then the input event triggers, you only have a problem whenever the widget renders with already a value in it, right ?

So you have at some point decided that, in order to do this, you need to 'manually trigger' the input event and are now down this unholy path of trying to find the right spot to do it.  You think the right spot is the window onload, but can't seem to get to it, right ?

 This is probably a perfect tl:dr for my problem.

Yes, it is very likely that I'm overcomplicating things. Also, I used a js approach for the auto-resizable feature because it was the only way I found to make it work.

I understand that the 'onrender' should be the point where the textarea receives/already received its content. However, just as with the 'onready' event, I already tried setting the trigger there and I obtained the same results. I also did tests asking chrome to return to me both the outsystems page input value (the text that is shown in the textarea as soon as the page is loaded) and the textarea's 'value' property (which holds its text content). Both events ('ready' and 'render') showed me the same results: the input content is known, but the 'value' property is set to "".

I don't know for sure if my approach will work if I finally manage to set up the trigger at the 'onload' event. However, this is the only way I didn't test yet, so I can't discard this option. Also, discovering that the 'onload' event doesn't work even in the simplest example with reactive apps is worrying, at least in my opinion. If it is my fault, I can't say... the fact is that it that I didn't manage to make it work yet

 

I found a 'solution'.

Inspired by my last reply, I decided to SET the value of the textarea's 'value' attribute during the 'onready' event, since the input value is known by outsystems. After setting it, I execute the auto-resize function and, from what I've seen so far, it works.

I don't think that this is the right way to do it, nor the correct way. But it works, given the circumstances.

Ok, 

glad you found something that works for you. 

So your problem got me curious, and I have found a way to make something happen at moment of window.onload.  Not sure that's the one you were looking for, when testing, it gets fired more than once ??

So here's what I've done :


I have a webblock, with an input that should have length adjusted to content.  

I have a script with a single function in it to do adjusting.  The script is added as required to the block.


In the OnReady of the block, I have a javascript node, attaching the function to the window.onload, and passing in the id of the input to be adjusted.

I have some test screens with several instances of the block on them.  They all get adjusted as window loads.

I hope this helps you further to maybe do it the way you consider correct.  Again, just executing a little javascript in the OnRender of the block also works fine, I think.


See attached oml

Dorine

Hi Dorine


I actually tried what you proposed (setting something to happen with 'window.onload''), but didn't work in my case. I have to assume that some library that I'm using, or whatever other implementation that I used, is interfering with the 'onload' event in my app.

Either way, the 'onreder' event should've worked, but didn't for my case, since the assignment that I needed to take place didn't naturally occur for some reason (the 'value' property of the textarea needed to have desired value at this point). In any case, I found an alternative work-around for this 'bug' (or feature).

Ok Bruno, 

let's put this to rest.  

But the onRender not firing when you need it to, i can only imagine that's because that assignment you are waiting for happens in javascript or something.  If values that affect screen change with OS code, OnRender fires every time.  So probably not a bug or feature, but a consequence of doing things in scripts outside the control of OS.

Anyway,

happy coding,

Dorine

I mean, the value that I need to be assigned is the 'value' property of the textarea. This can be set inside Outsystems by assigning the textarea variable to another local variable of the screen. In my case, I assigned it to an input variable of my web block. So, this is all done using the Outsystems framework.

Why this change isn't registered to the 'value' property of the textarea before/during 'onready' is beyond me.

Ah ok,

well I'm not sure about the onReady, but surely the onRender should fire again when you change the value.