# Invoking Application Functions on the Frontend Page
Register your application code with frontend pages. Then you can invoke application methods with the registered object names on frontend pages.
## Establishing an Interaction Channel Between the Application Side and the HTML5 Page
Two methods are available for registering the application code: Call [javaScriptProxy()](../reference/apis-arkweb/arkts-basic-components-web-attributes.md#javascriptproxy) during **Web** component initialization. Call [registerJavaScriptProxy()](../reference/apis-arkweb/arkts-apis-webview-WebviewController.md#registerjavascriptproxy) after **Web** component initialization. The two methods must be used together with the [deleteJavaScriptRegister](../reference/apis-arkweb/arkts-apis-webview-WebviewController.md#deletejavascriptregister) API to prevent memory leaks.
The following example registers the **test()** function with the frontend page. This way, the **test()** function can be triggered and run on the frontend page.
- Sample code for using [javaScriptProxy()](../reference/apis-arkweb/arkts-basic-components-web-attributes.md#javascriptproxy):
```ts
// xxx.ets
import { webview } from '@kit.ArkWeb';
import { BusinessError } from '@kit.BasicServicesKit';
class TestClass {
constructor() {
}
test(): string {
return 'ArkTS Hello World!';
}
}
@Entry
@Component
struct WebComponent {
webviewController: webview.WebviewController = new webview.WebviewController();
// Declare the object to be registered.
@State testObj: TestClass = new TestClass();
build() {
Column() {
Button('deleteJavaScriptRegister')
.onClick(() => {
try {
this.webviewController.deleteJavaScriptRegister("testObjName");
} catch (error) {
console.error(`ErrorCode: ${(error as BusinessError).code}, Message: ${(error as BusinessError).message}`);
}
})
// Load the local index.html page.
Web({ src: $rawfile('index.html'), controller: this.webviewController})
// Inject the object to the web client.
.javaScriptProxy({
object: this.testObj,
name: "testObjName",
methodList: ["test"],
controller: this.webviewController,
// Optional parameter.
asyncMethodList: [],
permission: '{"javascriptProxyPermission":{"urlPermissionList":[{"scheme":"resource","host":"rawfile","port":"","path":""},' +
'{"scheme":"e","host":"f","port":"g","path":"h"}],"methodList":[{"methodName":"test","urlPermissionList":' +
'[{"scheme":"https","host":"xxx.com","port":"","path":""},{"scheme":"resource","host":"rawfile","port":"","path":""}]},' +
'{"methodName":"test11","urlPermissionList":[{"scheme":"q","host":"r","port":"","path":"t"},' +
'{"scheme":"u","host":"v","port":"","path":""}]}]}}'
})
}
}
}
```
- Sample code for the application using [registerJavaScriptProxy()](../reference/apis-arkweb/arkts-apis-webview-WebviewController.md#registerjavascriptproxy) for registration:
```ts
// xxx.ets
import { webview } from '@kit.ArkWeb';
import { BusinessError } from '@kit.BasicServicesKit';
class TestClass {
constructor() {
}
test(): string {
return "ArkUI Web Component";
}
toString(): void {
console.log('Web Component toString');
}
}
@Entry
@Component
struct Index {
webviewController: webview.WebviewController = new webview.WebviewController();
@State testObj: TestClass = new TestClass();
build() {
Column() {
Button('refresh')
.onClick(() => {
try {
this.webviewController.refresh();
} catch (error) {
console.error(`ErrorCode: ${(error as BusinessError).code}, Message: ${(error as BusinessError).message}`);
}
})
Button('Register JavaScript To Window')
.onClick(() => {
try {
this.webviewController.registerJavaScriptProxy(this.testObj, "testObjName", ["test", "toString"],
// Optional parameter: asyncMethodList
[],
// Optional parameter: permission
'{"javascriptProxyPermission":{"urlPermissionList":[{"scheme":"resource","host":"rawfile","port":"","path":""},' +
'{"scheme":"e","host":"f","port":"g","path":"h"}],"methodList":[{"methodName":"test","urlPermissionList":' +
'[{"scheme":"https","host":"xxx.com","port":"","path":""},{"scheme":"resource","host":"rawfile","port":"","path":""}]},' +
'{"methodName":"test11","urlPermissionList":[{"scheme":"q","host":"r","port":"","path":"t"},' +
'{"scheme":"u","host":"v","port":"","path":""}]}]}}'
);
} catch (error) {
console.error(`ErrorCode: ${(error as BusinessError).code}, Message: ${(error as BusinessError).message}`);
}
})
Button('deleteJavaScriptRegister')
.onClick(() => {
try {
this.webviewController.deleteJavaScriptRegister("testObjName");
} catch (error) {
console.error(`ErrorCode: ${(error as BusinessError).code}, Message: ${(error as BusinessError).message}`);
}
})
Web({ src: $rawfile('index.html'), controller: this.webviewController })
}
}
}
```
> **NOTE**
>
> - You need to call the [refresh()](../reference/apis-arkweb/arkts-apis-webview-WebviewController.md#refresh) method for the registration to take effect after using the [registerJavaScriptProxy()](../reference/apis-arkweb/arkts-apis-webview-WebviewController.md#registerjavascriptproxy) method.
- The optional parameter permission is a JSON string. The following is an example:
```json
{
"javascriptProxyPermission": {
"urlPermissionList": [ // Object-level permission. If it is granted, all methods are available.
{
"scheme": "resource", // Exact match. This field is mandatory and cannot be empty.
"host": "rawfile", // Exact match. This field is mandatory and cannot be empty.
"port": "", // Exact match. If the value is empty, the check is not performed. This field is mandatory.
"path": "" // Prefix match. If the value is empty, the check is not performed. This field is mandatory.
},
{
"scheme": "https", // Exact match. This field is mandatory and cannot be empty.
"host": "xxx.com", // Exact match. This field is mandatory and cannot be empty.
"port": "8080", // Exact match. If the value is empty, the check is not performed. This field is mandatory.
"path": "a/b/c" // Prefix match. If the value is empty, the check is not performed. This parameter is mandatory.
}
],
"methodList": [
{
"methodName": "test",
"urlPermissionList": [ // Method-level permission.
{
"scheme": "https", // Exact match. This field is mandatory and cannot be empty.
"host": "xxx.com", // Exact match. This field is mandatory and cannot be empty.
"port": "", // Exact match. If the value is empty, the check is not performed. This field is mandatory.
"path": "" // Prefix match. If the value is empty, the check is not performed. This parameter is mandatory.
},
{
"scheme": "resource",// Exact match. This field is mandatory and cannot be empty.
"host": "rawfile", // Exact match. This field is mandatory and cannot be empty.
"port": "", // Exact match. If the value is empty, the check is not performed. This field is mandatory.
"path": "" // Prefix match. If the value is empty, the check is not performed. This field is mandatory.
}
]
},
{
"methodName": "test11",
"urlPermissionList": [ // Method-level permission.
{
"scheme": "q", // Exact match. This field is mandatory and cannot be empty.
"host": "r", // Exact match. This field is mandatory and cannot be empty.
"port": "", // Exact match. If the value is empty, the check is not performed. This field is mandatory.
"path": "t" // Prefix match. If the value is empty, the check is not performed. This field is mandatory.
},
{
"scheme": "u", // Exact match. This field is mandatory and cannot be empty.
"host": "v", // Exact match. This field is mandatory and cannot be empty.
"port": "", // Exact match. If the value is empty, the check is not performed. This field is mandatory.
"path": "" // Prefix match. If the value is empty, the check is not performed. This field is mandatory.
}
]
}
]
}
}
```
- Sample code for invoking application functions on the **index.html** frontend page:
```html
```
## Usage of Complex Types
### Passing Arrays Between the Application and the Frontend Page
Arrays can be used as parameters or return values of object registration methods and passed between applications and frontend pages.
```ts
// xxx.ets
import { webview } from '@kit.ArkWeb';
import { BusinessError } from '@kit.BasicServicesKit';
class TestClass {
constructor() {
}
test(): Array {
return [1, 2, 3, 4]
}
toString(param: String): void {
console.log('Web Component toString' + param);
}
}
@Entry
@Component
struct Index {
webviewController: webview.WebviewController = new webview.WebviewController();
@State testObj: TestClass = new TestClass();
build() {
Column() {
Button('refresh')
.onClick(() => {
try {
this.webviewController.refresh();
} catch (error) {
console.error(`ErrorCode: ${(error as BusinessError).code}, Message: ${(error as BusinessError).message}`);
}
})
Button('Register JavaScript To Window')
.onClick(() => {
try {
this.webviewController.registerJavaScriptProxy(this.testObj, "testObjName", ["test", "toString"]);
} catch (error) {
console.error(`ErrorCode: ${(error as BusinessError).code}, Message: ${(error as BusinessError).message}`);
}
})
Button('deleteJavaScriptRegister')
.onClick(() => {
try {
this.webviewController.deleteJavaScriptRegister("testObjName");
} catch (error) {
console.error(`ErrorCode: ${(error as BusinessError).code}, Message: ${(error as BusinessError).message}`);
}
})
Web({ src: $rawfile('index.html'), controller: this.webviewController })
}
}
}
```
```html
```
### Using Complex Types Excluding Functions
Sample code for passing complex types (excluding functions) as parameters or return values in object registration methods between the application and the frontend page:
```ts
// xxx.ets
import { webview } from '@kit.ArkWeb';
import { BusinessError } from '@kit.BasicServicesKit';
class Student {
name: string = '';
age: string = '';
}
class TestClass {
constructor() {
}
// Data of primitive types to pass: name:"jeck", age:"12"
test(): Student {
let st: Student = { name: "jeck", age: "12" };
return st;
}
toString(param: ESObject): void {
console.log('Web Component toString' + param["name"]);
}
}
@Entry
@Component
struct Index {
webviewController: webview.WebviewController = new webview.WebviewController();
@State testObj: TestClass = new TestClass();
build() {
Column() {
Button('refresh')
.onClick(() => {
try {
this.webviewController.refresh();
} catch (error) {
console.error(`ErrorCode: ${(error as BusinessError).code}, Message: ${(error as BusinessError).message}`);
}
})
Button('Register JavaScript To Window')
.onClick(() => {
try {
this.webviewController.registerJavaScriptProxy(this.testObj, "testObjName", ["test", "toString"]);
} catch (error) {
console.error(`ErrorCode: ${(error as BusinessError).code}, Message: ${(error as BusinessError).message}`);
}
})
Button('deleteJavaScriptRegister')
.onClick(() => {
try {
this.webviewController.deleteJavaScriptRegister("testObjName");
} catch (error) {
console.error(`ErrorCode: ${(error as BusinessError).code}, Message: ${(error as BusinessError).message}`);
}
})
Web({ src: $rawfile('index.html'), controller: this.webviewController })
}
}
}
```
```html
```
### Invoking a Callback of the Frontend Page from the Application
Callbacks can be used as parameters or return values of object registration methods and passed between applications and frontend pages.
```ts
// xxx.ets
import { webview } from '@kit.ArkWeb';
import { BusinessError } from '@kit.BasicServicesKit';
class TestClass {
constructor() {
}
test(param: Function): void {
param("call callback");
}
toString(param: String): void {
console.log('Web Component toString' + param);
}
}
@Entry
@Component
struct Index {
webviewController: webview.WebviewController = new webview.WebviewController();
@State testObj: TestClass = new TestClass();
build() {
Column() {
Button('refresh')
.onClick(() => {
try {
this.webviewController.refresh();
} catch (error) {
console.error(`ErrorCode: ${(error as BusinessError).code}, Message: ${(error as BusinessError).message}`);
}
})
Button('Register JavaScript To Window')
.onClick(() => {
try {
this.webviewController.registerJavaScriptProxy(this.testObj, "testObjName", ["test", "toString"]);
} catch (error) {
console.error(`ErrorCode: ${(error as BusinessError).code}, Message: ${(error as BusinessError).message}`);
}
})
Button('deleteJavaScriptRegister')
.onClick(() => {
try {
this.webviewController.deleteJavaScriptRegister("testObjName");
} catch (error) {
console.error(`ErrorCode: ${(error as BusinessError).code}, Message: ${(error as BusinessError).message}`);
}
})
Web({ src: $rawfile('index.html'), controller: this.webviewController })
}
}
}
```
```html
```
### Calling the Function in an Object of the Frontend Page from the Application Side
The function in an object of the frontend page can be used as the parameter or return value of the registration object method and passed between the application side and the frontend page.
```ts
// xxx.ets
import { webview } from '@kit.ArkWeb';
import { BusinessError } from '@kit.BasicServicesKit';
class TestClass {
constructor() {
}
test(param: ESObject): void {
param.hello("call obj func");
}
toString(param: String): void {
console.log('Web Component toString' + param);
}
}
@Entry
@Component
struct Index {
webviewController: webview.WebviewController = new webview.WebviewController();
@State testObj: TestClass = new TestClass();
build() {
Column() {
Button('refresh')
.onClick(() => {
try {
this.webviewController.refresh();
} catch (error) {
console.error(`ErrorCode: ${(error as BusinessError).code}, Message: ${(error as BusinessError).message}`);
}
})
Button('Register JavaScript To Window')
.onClick(() => {
try {
this.webviewController.registerJavaScriptProxy(this.testObj, "testObjName", ["test", "toString"]);
} catch (error) {
console.error(`ErrorCode: ${(error as BusinessError).code}, Message: ${(error as BusinessError).message}`);
}
})
Button('deleteJavaScriptRegister')
.onClick(() => {
try {
this.webviewController.deleteJavaScriptRegister("testObjName");
} catch (error) {
console.error(`ErrorCode: ${(error as BusinessError).code}, Message: ${(error as BusinessError).message}`);
}
})
Web({ src: $rawfile('index.html'), controller: this.webviewController })
}
}
}
```
```html
```
### Calling the Function in an Object of the Application Side from the Frontend Page
The function in an object of the application side can be used as the parameter or return value of the registration object method and passed between the application side and the frontend page.
```ts
// xxx.ets
import { webview } from '@kit.ArkWeb';
import { BusinessError } from '@kit.BasicServicesKit';
class ObjOther {
methodNameListForJsProxy: string[]
constructor(list: string[]) {
this.methodNameListForJsProxy = list
}
testOther(json: string): void {
console.info(json)
}
}
class TestClass {
ObjReturn: ObjOther
constructor() {
this.ObjReturn = new ObjOther(["testOther"]);
}
test(): ESObject {
return this.ObjReturn
}
toString(param: string): void {
console.log('Web Component toString' + param);
}
}
@Entry
@Component
struct Index {
webviewController: webview.WebviewController = new webview.WebviewController();
@State testObj: TestClass = new TestClass();
build() {
Column() {
Button('refresh')
.onClick(() => {
try {
this.webviewController.refresh();
} catch (error) {
console.error(`ErrorCode: ${(error as BusinessError).code}, Message: ${(error as BusinessError).message}`);
}
})
Button('Register JavaScript To Window')
.onClick(() => {
try {
this.webviewController.registerJavaScriptProxy(this.testObj, "testObjName", ["test", "toString"]);
} catch (error) {
console.error(`ErrorCode: ${(error as BusinessError).code}, Message: ${(error as BusinessError).message}`);
}
})
Button('deleteJavaScriptRegister')
.onClick(() => {
try {
this.webviewController.deleteJavaScriptRegister("testObjName");
} catch (error) {
console.error(`ErrorCode: ${(error as BusinessError).code}, Message: ${(error as BusinessError).message}`);
}
})
Web({ src: $rawfile('index.html'), controller: this.webviewController })
}
}
}
```
```html
```
### Using Promises
Create a promise on the application side. Use the promise as the parameter or return value of the object method and pass it to the frontend page.
```ts
// xxx.ets
import { webview } from '@kit.ArkWeb';
import { BusinessError } from '@kit.BasicServicesKit';
class TestClass {
constructor() {
}
test(): Promise {
let p: Promise = new Promise((resolve, reject) => {
setTimeout(() => {
console.log ('Execution completed');
reject('fail');
}, 10000);
});
return p;
}
toString(param: String): void {
console.log(" " + param);
}
}
@Entry
@Component
struct Index {
webviewController: webview.WebviewController = new webview.WebviewController();
@State testObj: TestClass = new TestClass();
build() {
Column() {
Button('refresh')
.onClick(() => {
try {
this.webviewController.refresh();
} catch (error) {
console.error(`ErrorCode: ${(error as BusinessError).code}, Message: ${(error as BusinessError).message}`);
}
})
Button('Register JavaScript To Window')
.onClick(() => {
try {
this.webviewController.registerJavaScriptProxy(this.testObj, "testObjName", ["test", "toString"]);
} catch (error) {
console.error(`ErrorCode: ${(error as BusinessError).code}, Message: ${(error as BusinessError).message}`);
}
})
Button('deleteJavaScriptRegister')
.onClick(() => {
try {
this.webviewController.deleteJavaScriptRegister("testObjName");
} catch (error) {
console.error(`ErrorCode: ${(error as BusinessError).code}, Message: ${(error as BusinessError).message}`);
}
})
Web({ src: $rawfile('index.html'), controller: this.webviewController })
}
}
}
```
```html
```
Create a promise on the frontend page. Use the promise as the parameter or return value of the object method and pass it to the application side.
```ts
// xxx.ets
import { webview } from '@kit.ArkWeb';
import { BusinessError } from '@kit.BasicServicesKit';
class TestClass {
constructor() {
}
test(param:Function): void {
setTimeout( () => { param("suc") }, 10000)
}
toString(param:String): void {
console.log(" " + param);
}
}
@Entry
@Component
struct Index {
webviewController: webview.WebviewController = new webview.WebviewController();
@State testObj: TestClass = new TestClass();
build() {
Column() {
Button('refresh')
.onClick(() => {
try {
this.webviewController.refresh();
} catch (error) {
console.error(`ErrorCode: ${(error as BusinessError).code}, Message: ${(error as BusinessError).message}`);
}
})
Button('Register JavaScript To Window')
.onClick(() => {
try {
this.webviewController.registerJavaScriptProxy(this.testObj, "testObjName", ["test", "toString"]);
} catch (error) {
console.error(`ErrorCode: ${(error as BusinessError).code}, Message: ${(error as BusinessError).message}`);
}
})
Button('deleteJavaScriptRegister')
.onClick(() => {
try {
this.webviewController.deleteJavaScriptRegister("testObjName");
} catch (error) {
console.error(`ErrorCode: ${(error as BusinessError).code}, Message: ${(error as BusinessError).message}`);
}
})
Web({ src: $rawfile('index.html'), controller: this.webviewController })
}
}
}
```
```html
```
## Checking Whether the Channel Is Successfully Established
1. Enable web debugging.
For details about how to enable web debugging, see [Debugging Frontend Pages by Using DevTools](web-debugging-with-devtools.md).
2. Use an example to check whether the channel is successfully established.
The following example passes arrays between the application side and the frontend page described in [Usage of Complex Types](#usage-of-complex-types). The debugging result is shown in the following figure.
