My app structure is as follows:
MainForm --> component-panel --> ComponentForm --> component-panel --> multiple componenets each of which is SubForm containing a textArea.
I want to change the behaviour of the Enter Key for the textareas.
I think I’m close but I don’t understand how to correctly select the SubForm as the DOM element argument in anvil.call
on the ComponentForm show event I have:
anvil.js.call_js('set_enter_behaviour')
in the native library, I have a function that sets the keydown behaviour for the enter key.
function enter_behaviour(e){
if(e.which==13){
e.preventDefault()
linkElement = this
anvil.call(this,'textarea_pressed_enter')
};
};
function set_enter_behaviour() {
$('textarea').on('keydown',enter_behaviour);
};
The error I get is as follows
Exception: Attempted to call non-existent method from Javascript: <MainForm object> has no attribute 'textarea_pressed_enter'.
at <template>, line <unknown>
So it seems that this is the MainForm, whereas I want this to be the correct SubForm that the textarea is contained within. Help…
I have pushed the enter trap code into a self contained function in the custom HTML code for the text area form. Each one should act independently.
See if it makes sense. If not, I’ll try and explain it later.
edit just updated it to assign a random id to each instance so you can tell which textarea is getting the event. Note the JS is not the best - I am an amateur at it - and it can probably be simplified/bettered by someone on here, but it does work.
I think you might want to use self.call_js(...) here rather than anvil.js.call_js(...). Some background:
There are two ways to call JS from Python in Anvil: locally (on a component) and globally (not on a particular component):
Locally, you can call self.call_js(...) from any HTML-templated form. You will call the Javascript with this set to the DOM element from the form you’re calling in.
This is really useful if you’re creating a custom component and you expect to have multiple instances on the page – you can tell the Javascript to do something to this instance.
Globally, you can call anvil.js.call_js(...) from anywhere. There’s no local context here - you’re not calling the Javascript on a particular DOM element.
This is really useful if you want to do something that’s not specific to a particular part of the page (eg calling a JS library to pop up a dialog box).
It looks like, for what you’re doing, you want to operate on on a particular instance of your custom component, so I would recommend using self.call_js() in the custom component, and using this in Javascript to work out which DOM element(s) to operate on.
I see - yes so the conclusion - whenever you want to augment the behaviour of an anvil component…
Turn this into a custom HTML component and use self.call_js to augment that behaviour.
This allows one to have multiple instances of that component.