22
Views
11
Comments
Solved
My JavaScript code isn't behaving as expected...
Question
Application Type
Reactive

Hi there.

First of all, I'm sorry for the extremely vague title. This is my situation:

I'm working on a block, not really a screen.

I placed an HTML Tag inside my block. It's an <object> tag. I gave it a data property with the value of the URL of an SVG file in my app. I also gave it a type property, with the value "image/svg+xml".

Then, on my block's OnReady event handler, I am running the following JavaScript code:

var rootObject = document.getElementById($parameters.ObjectId).contentDocument;
var corrugador = rootObject.getElementById("corrugador");
corrugador.addEventListener('click', $actions.OnMuscleSelected())

But I get the following error:


Cannot read property 'addEventListener' of null

So my corrugador variable evaluates to null? I'm 100% sure I typed the right id, and I know that element is there, inside my SVG. So I don't understand why it is evaluating to null. I would really appreciate some help :(

I attached my SVG file just in case, but I must warn you: it's very long. You can find the element with id "corrugador" by the end of the file, though.


Thanks in advance.

musclestest.svg

mvp_badge
MVP
Rank: #17
Solution

See attached

SvgPathClickDemo.oap

Rank: #2817

Thank you so so much for that. I figured out what my mistake was using your example. I was running my JavaScript code inside a block's On Ready action. This block contained the SVG and was placed in my screen. What I had to do, was run the JavaScript code inside the screen's On Ready action. I'm gonna be honest, I don't know why that fixed the problem, but it did.

Thanks again for your help.

mvp_badge
MVP
Rank: #17
mvp_badge
MVP
Rank: #17

Hi Yizuhi,

Regarding your  JavaScript, the most obvious reason is that the statement

var corrugador = rootObject.getElementById("corrugador");

Did not return the HTML element, as such corrugador is null.

The easiest (low-code) way to include an SVG in an OutSystems Reactive application, is to go to the Logic tab and under the Images folder add the SVG as Image.Then add an Image widget to your screen and select the the Image widget property Image the SVG images from the Image folder.

Now you can add on the Image widget the OnClick event. As you see no JavaScript required.


Regards,

Daniel

Hi Yizuhi, 


Daniel's solution should also do the trick when an onClick is needed, but I think you want to differentiate between the muscles in the image (with an image/area/map?) or is this assumption wrong?

Some of my thoughts when reading your post:

  • Is the object "corrugador" available within the page, or is it an OutSystems generated object (in that case the name will be different).
  • Are you also doing something in the On Destroy with these Event Listeners?
  • Be aware the On Destroy is activated after the new screen is displayed. When removing things like listeners, this could be a problem for items which have the same name and position in the DOM.
  • Also, if both (old and new screen) have a "corrugador" named item, you could end up with the wrong one (in certain cases)
  • Also, document is not destroyed. Only the content is replaced. Any object in "document" will not be removed



Rank: #2817

Yeah, thank you so much, that IS what I'm trying to do.

  • The object "corrugador" is a path already inside the SVG, that's why I thought there would be no problems trying to get it by its id.
  • No, I'm not doing anything in the On Destroy.

If I, for example, try to get the "corrugador" object using Chrome's DevTools console (using the same code I used in my JavaScript block), it works fine. So I'm really confused about why it isn't working :(

I could really use some extra help...

I apologize for my ignorance, this is my first time working with SVGs.

mvp_badge
MVP
Rank: #17

Hi Yizuhi,

How did you load the SVG in the DOM? Please keep in mind OutSystems Reactive Web app uses ReactJs as underlying technology. It is reactJS that is maintaining the DOM. Did you check in your browser the SVG is loaded? 

You could try and leverage the InlineSVG widget from OutSystems UI:

And set the expression of its SVGCode parameter to your SVG code. This way you ensure the SVG is correctly loaded.

 In the OnRender event handler of your screen you can add the JavaScript to add your OnClickEvent handler logic.

Regarding that your code is:

var rootObject = document.getElementById($parameters.ObjectId).contentDocument;
var corrugador = rootObject.getElementById("corrugador");
corrugador.addEventListener('click', $actions.OnMuscleSelected())

But the element in your SVG is identified by the id "currugador" so there is no need to first get the content document and from that the element, you can get it straight from the document object

var corrugador = document.getElementById("corrugador");
corrugador .addEventListener('click', $actions.OnMuscleSelected, false);

Regards,

Daniel

Rank: #2817

Thanks for your response.

I loaded the SVG using an HTML Tag widget. I set its tag property to object, its data property to the URL of my SVG file and its data property to "image/svg+xml".

Regarding the use of the InlineSVG widget, am I supposed to paste all my SVG file inside of its SVGCode parameter expression? My SVG file contains 30,000+ lines of code...

I changed my code, though, so that it gets the "corrugador" object straight from the document object. When I open my app in the browser, I can see the SVG, but I keep getting the error telling me that the "corrugador" object is null. 

mvp_badge
MVP
Rank: #17

I did load your complete SVG in the InliveSVG it works the click on the one path also worked.

Before you add the SVG to the inlineSVG first replace " with ' and then include the complete text between "".

This code must work, it does for me:

var corrugador = document.getElementById("corrugador");
corrugador .addEventListener('click', $actions.OnMuscleSelected, false);

Rank: #2817

Alright. Now I'm using the InlineSVG widget. I loaded all my SVG code on it like you said.

I also replaced my code with yours.

I'm not getting the error anymore (woohoo!), but when I click on the "corrugador" path nothing happens. In the action I defined, a Message is supposed to be appearing on screen. But it's not.

This is truly driving me insane.

mvp_badge
MVP
Rank: #17

i  will sent you a working module. Give me 10 minutes.

mvp_badge
MVP
Rank: #17
Solution

See attached

SvgPathClickDemo.oap

Rank: #2817

Thank you so so much for that. I figured out what my mistake was using your example. I was running my JavaScript code inside a block's On Ready action. This block contained the SVG and was placed in my screen. What I had to do, was run the JavaScript code inside the screen's On Ready action. I'm gonna be honest, I don't know why that fixed the problem, but it did.

Thanks again for your help.

mvp_badge
MVP
Rank: #17