16
Views
10
Comments
Solved
Having problems with a block's lifecycle...
Application Type
Reactive

Hi there.

I asked a somewhat similar question some time ago, but I'm having problems again.

Here's the deal:

I have a block that displays a different set of Images and an Inline SVG depending of the value of 2 of its Input Parameters.

I have to add some event listeners to the paths of the Inline SVG being shown. This is the code I try to execute:

var corrugador = document.getElementById("corrugador_d");

corrugador.addEventListener('click',

        function(e){

            e.target.setAttributeNS(null, 'stroke', 'red');

        }, false);


I try to get the path by its id. This code is being executed inside the OnParametersChanged action of the block, and I execute it only if the Input Parameters have a certain value assigned to them (which means the Inline SVG I want is going to be shown).

However, I am getting an error: Cannot read property 'addEventListener' of null

So, I'm assuming that at the moment when the code is executed, the Inline SVG hasn't been loaded yet? But how can I assure that this code only gets ran when the SVG is already loaded? Should I run this code in another action (not OnParametersChanged)?

Any help would be HIGHLY eppreciated :)

mvp_badge
MVP
Rank: #17
Solution

Hi,

I changed the JS in ComponentDidMount to:

document.addEventListener('click', function (event) {

    if (event.target.id === 'corrugador_d'

    ||  event.target.id === 'corrugador_i') 

    event.target.setAttribute('stroke', 'red');

console.log(event.target);

}, false);

Then the other issue was that I had to set the opacity to 1 for image MusclesImage via inline style (not via css). Only then the svg paths are clickable. With the opacity to 0 (default by OutSystems) the image blocks clicking the svg paths apparently

Regards,
Daniel  
mvp_badge
MVP
Rank: #17

Hi Yizuhi,

Running the following code in the OnParameterChanged event:

corrugador.addEventListener('click',

        function(e){

            e.target.setAttributeNS(null, 'stroke', 'red');

        }, false);

Will cause event handler to be added everytime OnParameterChanged is fired.

The error: Cannot read property 'addEventListener' of null , you get mostlikely because

var corrugador = document.getElementById("corrugador_d");

Is not resulting in the correct DOM element being assigned to corrugador variable.

 A better place to put this code is in the OnReady Event of the block.

Regards,

Daniel

Rank: #2828

Hi, thanks for your reply.

Please correct me if I'm wrong, but isn't the OnReady event only executed after the first render of the block? I think this would work if my block was static, but since its content is changing regularly depending on the parameters it's receiving, I don´'t know if the OnReady event would be the right place to execute my code. I'll try it anyways and see how that goes.

mvp_badge
MVP
Rank: #17

Well you are right about the onReady but, you also do not need to execute the code every time in the OnParameterChange event handler.

The OnReady event is perfect to define a javascript event handler in this case.

Look at the attached OML, it loads a big SVG inline and uses JavaScript to add a clickable area that executes a screen action.

SvgPathClickDemo.oml

Rank: #2828

Thanks for the example. However, I had already figured out how to do that before in this post (I think you were the person who helped me out?).

I am asking a new question because now, the block will be rendering different SVGs depending on the values it gets as its Input Parameters. If it were to only render the same SVG always, then what you're telling me would work. But since it has to get re-rendered quite often, I can't expect to set the event listeners in the OnReady event. That's why I thought it would work if I put it in the OnParametersChanged event handler: every time the input parameters changed, a new SVG would have to be loaded and I would have to set the corresponding event listeners for that SVG.

I hope I'm making sense...

mvp_badge
MVP
Rank: #17

Ha it was you then, I don't see that.

Could you share an OML?

Rank: #2828

Sure thing, here it is. 

MultipleSVGBlock.oml

mvp_badge
MVP
Rank: #17

Hi,

I changed your code, but I am hit with a 4mb upload limit to this reply. Don't know why you were able to upload a 9mb file, and I am not allowed.

So, will instead document the change here:


I remove the OnParameterChanged logic.

Instead, on the condition of 

FaceAngle = "f" And ShowMuscles

In your widget tree I added  on parent container of the SVG widget an onComponentMount event, (this is a javascript event fired if a specific DOM component is rendered, as opposed to the DOM of the complete outSystems block.

I debugged the code, and the event handler is added. The OnClick also fires. Just don't know what setting the stroke attribute setting to red should do I don't see effect.




Rank: #2828

Hi, thanks for your help.

I did what you told me, and I'm not getting the error anymore, so yay! The red stroke thing was supposed to set the stroke of the clicked path to a red color, but you're right, it's not working at all. So I decided to do ANYTHING (in this case, I decided to call the alert() function whenever the path was clicked) just to verify if it was working. But nothing is showing up. An alert pop-up with a message should be appearing, but it's like it didn't detect when I clicked on the path.

Any clue why this could be?

mvp_badge
MVP
Rank: #17
Solution

Hi,

I changed the JS in ComponentDidMount to:

document.addEventListener('click', function (event) {

    if (event.target.id === 'corrugador_d'

    ||  event.target.id === 'corrugador_i') 

    event.target.setAttribute('stroke', 'red');

console.log(event.target);

}, false);

Then the other issue was that I had to set the opacity to 1 for image MusclesImage via inline style (not via css). Only then the svg paths are clickable. With the opacity to 0 (default by OutSystems) the image blocks clicking the svg paths apparently

Regards,
Daniel  
Rank: #2828

Thanks SO SO much, that fixed it completely. The issue is that was the one to set the opacity to 0.2 (because the user is supposed to be able to change that image's opacity with a slider), so I guess I'll have to find a workaroud for that haha.

Thanks again for your help.