Execute JavaScript
webforJ draait op de server, maar er zijn momenten dat je de client moet bereiken: scrollen in het venster, een veld focussen, een browserwaarde lezen of een methode aanroepen op een webcomponent. De HasJsExecution interface biedt die brug. Het is op twee niveaus geïmplementeerd:
- De
Pagedraait script in de context van de hele pagina. - Een
Elementdraait script dat is beperkt tot een enkel clientelement.
Beide exposeren dezelfde drie methoden, dus zodra je de vormen hieronder kent, lezen ze hetzelfde, of je ze nu aanroept op Page of een Element.
Uitvoeringsmethoden
Elk niveau biedt een synchrone methode en twee asynchrone. Het verschil is of de aanroepende thread wacht en of er een resultaat terugkomt.
-
executeJs(String script): voert het script synchronisch uit. De uitvoerende thread is geblokkeerd totdat de client terugkomt, wat één server-client round trip kost. Het resultaat komt terug als eenObjectdat je kunt casten en gebruiken in Java. -
executeJsAsync(String script): voert het script asynchroon uit en blokkeert de uitvoerende thread niet. Het retourneert eenPendingResultdat voltooid wordt wanneer het script klaar is, zodat je later op het resultaat kunt reageren. -
executeJsVoidAsync(String script): voert het script asynchroon uit en retourneert niets naar de server. Gebruik het voor fire-and-forget werk waarbij je het resultaat niet nodig hebt. Beschikbaar sinds24.11.
Reik standaard naar executeJsVoidAsync wanneer je alleen een bijeffect op de client veroorzaakt (scrollen, focussen, een methode aanroepen). Gebruik executeJsAsync wanneer je de waarde nodig hebt, maar niet-blokkerend wilt blijven, en reserveer de synchrone executeJs voor het zeldzame geval waarin je het resultaat moet hebben voordat de volgende regel Java draait, omdat het de thread voor een volledige round trip vasthoudt.
Resultaten lezen
Wanneer een script een waarde retourneert, converteert webforJ deze naar het bijbehorende Java-type:
| JavaScript-waarde | Java-type |
|---|---|
| number | Integer, Long of Double |
| string | String |
| boolean | Boolean |
null of undefined | null |
| elk ander type | zijn stringrepresentatie |
Lees waarden met executeJsAsync, wat de conversie betrouwbaar toepast. Een geretourneerd nummer kan aankomen als Integer, Long of Double, dus lees het via Number:
Page.getCurrent()
.executeJsAsync("return window.innerWidth;")
.thenAccept(result -> {
int width = ((Number) result).intValue();
// gebruik width
});
De synchrone executeJs retourneert null wanneer de uitvoeringscontext niet gereed is, bijvoorbeeld wanneer het wordt aangeroepen voordat de component is gekoppeld. Gebruik executeJsAsync wanneer je afhankelijk bent van de geretourneerde waarde, en vermijd het casten van een synchrone resultaat naar een specifiek type.
App-niveau uitvoering
Roep de methoden aan op Page wanneer het script betrekking heeft op de pagina als geheel in plaats van één component. Verkrijg de huidige pagina met Page.getCurrent().
Een veelvoorkomend geval is terugscrollen naar de bovenkant na een routerwijziging. Er hoeft niets terug te komen, dus executeJsVoidAsync past:
Page.getCurrent().executeJsVoidAsync(
"window.scrollTo({ top: 0, behavior: 'smooth' });");
Wanneer je een clientwaarde op de server nodig hebt, lees deze dan asynchroon en reageer op het resultaat wanneer het aankomt:
Page.getCurrent()
.executeJsAsync("return navigator.language;")
.thenAccept(language -> {
// language is de browser locale, bijvoorbeeld "en-US"
applyLocale(String.valueOf(language));
});
Gebruik element-niveau uitvoering wanneer het script moet handelen op een specifiek clientelement in plaats van de pagina als geheel.
In de demo hieronder, het selecteren van Kopieer link voert een script uit via Page met executeJsVoidAsync om de uitnodigingslink naar het klembord van de bezoeker te schrijven. Kopiëren is een bijeffect met niets om terug te geven, dus de fire-and-forget methode is de juiste keuze.
Toon Code
- ExecuteJavaScriptView.java
Element-niveau uitvoering
Het aanroepen van dezelfde methoden op een Element beperkt het script tot dat element in plaats van de pagina. De retourwaarden en het synchrone en asynchrone gedrag komen overeen met de voorafgaande pagina-niveau methoden.
Elementscripts worden in de wachtrij geplaatst totdat het element aan de DOM is gekoppeld, en worden dan uitgevoerd, zodat je ze tijdens de opzet kunt aanroepen zonder te wachten op de koppeling zelf.
Een functie op een element aanroepen
Wanneer je een benoemde client-side functie wilt aanroepen in plaats van een scriptstring uit te voeren, biedt Element een parallel set van methoden. In plaats van een script geef je de functienaam en de argumenten door, die webforJ serialiseert en doorgeeft. Twee argumenttypes worden speciaal behandeld: this wordt vervangen door het clientelement, en elk Component argument wordt vervangen door zijn clientinstantie zodra deze is gekoppeld.
Deze spiegelen de uitvoermethoden, waarbij het enige verschil is of de thread wacht en of er een resultaat retourneert:
-
callJsFunction(String name, Object... args): roept de functie synchronisch aan en retourneert het resultaat als eenObject. De uitvoerende thread blokkeert voor één round trip. -
callJsFunctionAsync(String name, Object... args): roept de functie asynchroon aan zonder te blokkeren, en retourneert eenPendingResultdat voltooid wordt met het resultaat van de functie. Beschikbaar sinds24.11. -
callJsFunctionVoidAsync(String name, Object... args): roept de functie asynchroon aan en retourneert niets naar de server. Gebruik het voor fire-and-forget aanroepen waarbij je de retourwaarde niet nodig hebt. Beschikbaar sinds24.11.
Omdat de aanroep wacht op elke Component argument om te koppelen voordat deze wordt uitgevoerd, voltooit een aanroep die een component doorgeeft die nooit koppelt nooit.
// Focus een invoerveld van een webcomponent door de client-side methode aan te roepen
searchElement.callJsFunctionVoidAsync("focus");