DEV Community

Cover image for The next web component interacts with h5
liu yang
liu yang

Posted on

The next web component interacts with h5

H5 and ArkUI Interaction

H5 Calling ArkUI Methods

H5 Code Implementation

<!-- MainPage.html -->
<!DOCTYPE html>
<html>
<head>
    <link rel="stylesheet" type="text/css" href="./css/main.css">
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Test App</title>
</head>
<script>
    window.ohosCallNative = {
        callNative: function (func, params, callback) {
            // This is a placeholder for the actual native call implementation
            if (typeof callback === 'function') {
                callback('Mock Data from Native');
            }
        }
    };

    // Simulating getting the proportion and setting font size
    document.addEventListener('DOMContentLoaded', function () {
        window.ohosCallNative.callNative('getProportion', {}, function (data) {
            document.getElementsByTagName("html")[0].style.fontSize = data + 'px';
        });
    });

    function changeVal(event) {
        // This function can be used to handle input changes if needed
    }

    function towebview() {
        const tel = document.getElementById('phone').value;
        window.ohosCallNative.callNative('changeTel', { tel: tel });
    }
</script>
<body>
    <div class="container">
        <div class="selectConcat">
            <div class="flex-input">
                <input type="tel" id="phone" placeholder="Enter data to transfer" oninput="changeVal(event)" value=""/>
            </div>
        </div>
        <div class="bottom-tip" onclick="towebview()">Send Data to ArkUI</div>
        <div class="select_tips">
            <div id="phone_tip">Data from ArkUI</div>
            <div id="concat_tip"></div>
        </div>
    </div>
    <script src="./js/mainPage.js"></script>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

ArkUI Code Implementation

import { webview } from '@kit.ArkWeb';
import { display } from '@kit.ArkUI';
import { promptAction } from '@kit.ArkUI';
import JSBridge from '../common/utils/JsBridge';
import { CommonConstants } from '../common/constant/CommonConstant';
import Logger from '../common/utils/Logger';

@Extend(TextInput)
function inputStyle() {
    return {
        placeholderColor: $r('app.color.placeholder_color'),
        height: 45,
        fontSize: 18,
        backgroundColor: $r('app.color.background'),
        width: '80%',
        padding: { left: 0 },
        margin: { top: 12 }
    };
}

@Extend(Line)
function lineStyle() {
    return {
        width: '100%',
        height: 1,
        backgroundColor: $r('app.color.line_color')
    };
}

@Extend(Text)
function blackTextStyle(size?: number, height?: number) {
    return {
        fontColor: $r('app.color.black_text_color'),
        fontSize: 18,
        fontWeight: FontWeight.Medium
    };
}

@Entry
@Component
struct SelectContact {
    @StorageLink('isClick') isClick: boolean = false;
    @StorageLink('tel') phoneNumber: string = '';
    @StorageLink('proportion') proportion: number = 0;
    @State towebstr: string = '';

    @State chargeTip: Resource = $r('app.string.recharge_button');
    webController: webview.WebviewController = new webview.WebviewController();
    private jsBridge: JSBridge = new JSBridge(this.webController, this.towebstr, "Data received from H5");

    aboutToAppear() {
        display.getAllDisplays((err, displayClass: display.Display[]) => {
            if (err.code) {
                Logger.error('SelectContact Page', 'Failed to obtain all display objects. Code: ' + JSON.stringify(err));
                return;
            }
            this.proportion = displayClass[0].densityDPI / CommonConstants.COMMON_VALUE;
            Logger.info('SelectContact Page', 'Succeeded in obtaining all display objects. Data: ' + JSON.stringify(displayClass));
        });
    }

    build() {
        Column() {
            Web({
                src: $rawfile('MainPage.html'),
                controller: this.webController
            })
                .javaScriptAccess(true)
                .javaScriptProxy(this.jsBridge.javaScriptProxy)
                .height('50%')
                .onPageBegin(() => {
                    this.jsBridge.initJsBridge();
                });

            Row() {
                Text('Native').blackTextStyle();
                TextInput({ placeholder: 'Enter data to send to H5' })
                    .maxLength(12)
                    .type(InputType.Normal)
                    .inputStyle()
                    .onChange((value: string) => {
                        this.towebstr = value;
                    }).margin({ left: 20 });
            }.justifyContent(FlexAlign.SpaceBetween)
            .width('100%')
            .margin({ top: 8 });

            Line().lineStyle().margin({ left: 80 });

            Button('Send Data to Web')
                .width(CommonConstants.FULL_SIZE)
                .height($r('app.float.button_height'))
                .margin({ bottom: $r('app.float.button_margin_bottom'), top: 20 })
                .onClick(() => {
                    Logger.error("Data to send: " + this.towebstr);
                    this.jsBridge.chooseContact();
                    this.webController.runJavaScript(`window.fromNative("${this.towebstr}")`);
                });

            Row() {
                Text('Data from H5').fontSize(15).fontColor(Color.Gray);
                Text(this.phoneNumber).fontSize(20).fontColor(Color.Red);
            }.justifyContent(FlexAlign.Center).margin({ top: 20 });
        }
        .width(CommonConstants.FULL_SIZE)
        .height(CommonConstants.FULL_SIZE)
        .backgroundColor($r('app.color.page_color'))
        .padding({
            left: $r('app.float.margin_left_normal'),
            right: $r('app.float.margin_right_normal')
        });
    }
}
Enter fullscreen mode Exit fullscreen mode

JavaScript Bridge Implementation

import { WebviewController } from '@ohos.arkui';

interface ParamsItem {
    callID?: string;
    data?: { tel?: string };
}

interface JavaScriptItem {
    object: {
        call: (func: string, params: string) => void;
    };
    name: string;
    methodList: string[];
    controller: WebviewController;
}

class JSBridge {
    private webController: WebviewController;
    private towebstr: string;
    private bridgeName: string;

    constructor(webController: WebviewController, towebstr: string, bridgeName: string) {
        this.webController = webController;
        this.towebstr = towebstr;
        this.bridgeName = bridgeName;
    }

    get javaScriptProxy(): JavaScriptItem {
        return {
            object: {
                call: this.call
            },
            name: 'JSBridgeHandle',
            methodList: ['call'],
            controller: this.webController
        };
    }

    initJsBridge() {
        // Initialization logic if needed
    }

    call = (func: string, params: string): void => {
        const paramsObject: ParamsItem = JSON.parse(params);
        let result: Promise<string> = new Promise((resolve) => resolve(''));
        switch (func) {
            case 'chooseContact':
                result = this.chooseContact();
                break;
            case 'changeTel':
                result = this.changeTel(paramsObject);
                break;
            case 'changeAmount':
                result = this.changeAmount();
                break;
            case 'getProportion':
                result = this.getProportion();
                break;
            default:
                break;
        }
        result.then((data: string) => {
            this.callback(paramsObject?.callID, data);
        });
    }

    private callback(callID: string | undefined, data: string) {
        if (callID) {
            this.webController.runJavaScript(`window.handleNativeCallback(${callID}, '${data}')`);
        }
    }

    private chooseContact(): Promise<string> {
        return new Promise((resolve) => {
            // Implementation logic
            resolve('Contact chosen');
        });
    }

    private changeTel(params: ParamsItem): Promise<string> {
        const tel: string = params.data?.tel ?? '';
        // Store the phone number or perform other operations
        return new Promise((resolve) => {
            resolve('Phone number updated');
        });
    }

    private changeAmount(): Promise<string> {
        return new Promise((resolve) => {
            // Implementation logic
            resolve('Amount changed');
        });
    }

    private getProportion(): Promise<string> {
        return new Promise((resolve) => {
            // Implementation logic
            resolve('Proportion retrieved');
        });
    }
}
Enter fullscreen mode Exit fullscreen mode

H5 Receiving Data from ArkUI

window.fromNative = (text) => {
    document.getElementById('concat_tip').textContent = text;
};
Enter fullscreen mode Exit fullscreen mode

Top comments (0)