Call_js() from a module (not server module, not inside a form)

I have included a script in the HTML that loads a javascript library (jsMath) and everything works fine when I use call_js() from the code in a Form.

After refactoring to move most of the logic of the program into modules, I encountered a challenge: I could not call js from a module.

Or maybe I just do not know how to do it?

Is it possible to call js from a module? A simple module, inside Anvil, not the server module or the code in the form.

I suspect this might be impossible, since the js function is connected to the HTML that is loaded at the form level: self.call_js. This is specific to the form and not available outside.

I tried to import the form (MarkovGui) in the module and use the following:

MarkovGui.call_js(…)

But it seems like this does not work - and cannot be made to work(?)

It is not a big issue. It would just be useful when I separate the gui from the code. As it is I have to leave some of the code logic in the form where the gui is, since this is the only place where js can be called.

Solutions? Either to be able to load the js or the form into the module, or tell Anvil that a js library is globally available from all modules? But I see why this might be difficult.

And, when I think about it: I guess a workaround would be to just create separate Forms. One with the gui and another with the code logic.

Have you tried with get_openform?

Something like this should work:

from anvil import get_open_form
get_open_form().call_js('f')

You can put your JS functions into the “Native Libraries” section (under Theme in the project manager) :

image

Click that and enter this into the editor that appears :

<script>
  function testing() {
    alert("In JS function");
  }
</script>

So, let’s say Form1 is your default form. This JS function will now be available to call from there.

Next, create a module (not a server module) :

from anvil import get_open_form
...
def show_alert():
  get_open_form().call_js("testing")

Assuming Form1 is your master form and always open, you will be able to call the module from anywhere :

import Module1
...
def button_1_click(self, **event_args):
  Module1.show_alert()

Assuming I’ve understood correctly, does that make sense?

3 Likes

Thank you, both Stafano and David.

Yes!

get_open_form().call_js(‘f’)

is what I was looking for!

This allows me to call a javascript from a module (loaded in Native Libraries of the form).

Great!

(Specifically I use math.eval since this allows me to evaluate a string expression, and eval is not implemented in Skulpt)

2 Likes

I didn’t know Javascript had an eval that helps evaluating expressions, thanks for the suggestion!

There is an eval in javascript, but there is also a separate eval in the math.js library which is, maybe, a little safter than the javscript eval if you only need to calculate math string expressions.

4 posts were split to a new topic: NoneType has no attribute call_js