Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

The [methodname]`Element.callJsFunction()` method allows you to run a client-side component function from the server side. The method accepts two parameters: the name of the function to call; and the arguments to pass to the function.

The arguments passed to the function must be a type supported by the communication mechanism. The supported types are `String`, `Boolean`, `Integer`, `Double`, `JsonNode`, `Element`, and `Component`.
The arguments passed to the function must be a type supported by the communication mechanism. The supported types are `String`, `Boolean`, `Integer`, `Double`, `JsonNode`, `Element`, `Component`, and `JsFunction` (see <<#js-function,Passing JavaScript Functions>>).

.Calling the `clearSelection()` JavaScript function on the root element from the server side
[example]
Expand Down Expand Up @@ -64,7 +64,7 @@

The [methodname]`executeJs()` method accepts two parameters: the JavaScript expression to invoke; and the parameters to pass to the expression. The given parameters are available as variables named `$0`, `$1`, and so on.

The arguments passed to the expression must be a type supported by the communication mechanism. The supported types are `String`, `Integer`, `Double`, `Boolean`, `JsonNode`, and `Element`.
The arguments passed to the expression must be a type supported by the communication mechanism. The supported types are `String`, `Integer`, `Double`, `Boolean`, `JsonNode`, `Element`, `Component`, and `JsFunction` (see <<#js-function,Passing JavaScript Functions>>).

.Calling `MyModule.complete(true)` on the client side
[example]
Expand Down Expand Up @@ -164,4 +164,81 @@
----


[[js-function]]
== Passing JavaScript Functions [since:com.vaadin:vaadin@V25.2]

Check failure on line 168 in articles/flow/component-internals/element-api/calling-javascript.adoc

View workflow job for this annotation

GitHub Actions / lint

[vale] reported by reviewdog 🐶 [Vale.Terms] Use '(?-i)Vaadin' instead of 'vaadin'. Raw Output: {"message": "[Vale.Terms] Use '(?-i)Vaadin' instead of 'vaadin'.", "location": {"path": "articles/flow/component-internals/element-api/calling-javascript.adoc", "range": {"start": {"line": 168, "column": 51}}}, "severity": "ERROR"}

Check failure on line 168 in articles/flow/component-internals/element-api/calling-javascript.adoc

View workflow job for this annotation

GitHub Actions / lint

[vale] reported by reviewdog 🐶 [Vale.Terms] Use '(?-i)Vaadin' instead of 'vaadin'. Raw Output: {"message": "[Vale.Terms] Use '(?-i)Vaadin' instead of 'vaadin'.", "location": {"path": "articles/flow/component-internals/element-api/calling-javascript.adoc", "range": {"start": {"line": 168, "column": 44}}}, "severity": "ERROR"}
Comment thread
Artur- marked this conversation as resolved.

A [classname]`JsFunction` lets you build a reusable JavaScript function on the server and pass it as a parameter to [methodname]`executeJs()` or [methodname]`callJsFunction()`. The function arrives on the client as a real callable function with its captured values pre-bound, so you don't need to concatenate JavaScript fragments to embed server-side values.

The first argument to [methodname]`JsFunction.of()` is a JavaScript function body. The remaining arguments are captured values, referenced inside the body as `$0`, `$1`, &hellip; using the same naming convention as [methodname]`executeJs()` parameters.

.Defining a function and invoking it
[example]
====
[source,java]
----
JsFunction greet = JsFunction.of(
"return $0 + ' ' + $1;", "Hello", "World");
getElement().executeJs(
"this.textContent = $0();", greet);
----
====

Captures may be any value supported as an [methodname]`executeJs()` parameter. An attached `Element` arrives as the corresponding DOM node; a detached `Element` arrives as `null`.

.Capturing an element
[example]
====
[source,java]
----
Div target = new Div();
add(target);

JsFunction mutate = JsFunction.of(
"$0.textContent = 'updated';",
target.getElement());
getElement().executeJs("$0();", mutate);
----
====


=== Declaring Runtime Arguments

Use [methodname]`withArguments()` to declare named parameters that the function accepts at call time. The body references them by name, and the JavaScript that invokes the function passes them positionally:

.A function with runtime arguments
[example]
====
[source,java]
----
JsFunction format = JsFunction
.of("return prefix + ':' + suffix;")
.withArguments("prefix", "suffix");
getElement().executeJs(
"this.textContent = $0('alpha', 'beta');", format);
----
====


=== Controlling `this`

In JavaScript, the value of `this` inside a function depends on how the function is invoked, not where it is defined. The body of a [classname]`JsFunction` follows this convention &ndash; `this` is not bound to the host element automatically.

When the function is invoked as `$0(...)` from inside an [methodname]`executeJs()` expression, the body's `this` is the global object (or `undefined` in strict mode), not the element on which [methodname]`executeJs()` was called. To set `this` explicitly, invoke the function with [methodname]`Function.prototype.call()`: its first argument becomes `this` inside the body.

.Calling the function with a specific `this`
[example]
====
[source,java]
----
JsFunction setOwnText = JsFunction
.of("this.textContent = msg;")
.withArguments("msg");
getElement().executeJs(
"$0.call(this, 'host element text');", setOwnText);
----
====

If the body always needs to reference the same element regardless of how the function is called, pass it as a capture instead of relying on `this`.


[discussion-id]`AB7EDF45-DB22-4560-AF27-FF1DC6944482`
Loading