WebView JavaScript Bridge untuk Navigasi
Menggunakan JavaScript Bridge untuk navigasi WebView
Panduan WebView JavaScript Bridge untuk Navigasi
Tutorial sederhana untuk membuat tombol dan link di halaman web (WebView) yang dapat menavigasi ke menu lain di aplikasi Hexaflate.
Apa itu JavaScript Bridge?
JavaScript Bridge memungkinkan halaman web di dalam aplikasi berkomunikasi dengan aplikasi native Flutter. Dengan fitur ini, Anda bisa:
- Navigasi ke menu lain (menuId)
- Buka screen tertentu (route)
- Buka WebView baru (nested webview)
- Buka submenu (bottom sheet atau full screen)
- Print struk/receipt (print)
- Buka URL eksternal (browser)
- Reload halaman atau kembali
Daftar Action yang Tersedia
| Action | Fungsi | URL Scheme |
|---|---|---|
menuId | Navigasi ke menu berdasarkan ID | ✅ Didukung |
navigate | Navigasi ke Flutter route | ✅ Didukung |
webview | Buka WebView baru | ✅ Didukung |
submenu | Tampilkan submenu | ❌ Via JS Bridge saja |
print | Tampilkan print preview dengan data custom | ❌ Via JS Bridge saja |
external | Buka URL di browser eksternal | ✅ Didukung |
reload | Refresh WebView | ✅ Didukung |
back | Kembali/tutup WebView | ✅ Didukung |
Bonus: URL Scheme Method
Selain JavaScript Bridge, ada dua cara alternatif menggunakan URL:
1. Eksternal Browser: ?newbrowser=ok
- Tambahkan
?newbrowser=okdi URL untuk otomatis buka di browser eksternal - Tidak perlu JavaScript! Contoh:
<a href="https://google.com?newbrowser=ok">Google</a> - Detail lengkap di bagian Buka URL di Browser Eksternal
2. Navigasi Aplikasi: hexaflate://
- Gunakan custom scheme
hexaflate://untuk navigasi internal tanpa JavaScript Bridge - Format:
hexaflate://<action>[/<route>]?<query_params> - Tidak perlu JavaScript! Cukup link atau redirect biasa
- Contoh:
<a href="hexaflate://navigate/history">Riwayat</a> - Detail lengkap di bagian Alternatif: URL Scheme Bridge
Cara Menggunakan JavaScript Bridge
Template Dasar
Semua action menggunakan format yang sama:
window.flutter_inappwebview.callHandler('AppBridge', JSON.stringify({
action: 'nama_action',
// parameter lainnya...
}));
1. Navigasi ke Menu Berdasarkan ID (menuId)
Prioritas Tertinggi - Sama seperti banner dan menu icon!
Cara Mendapatkan Menu ID
- Buka Admin Panel → Layout Aplikasi → Canvas
- Pilih screen yang memiliki menu
- Klik widget Grup Menu
- Klik Buka Editor Menu
- Copy ID dari menu yang ingin dituju
Contoh HTML + JavaScript
Via JavaScript Bridge:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Navigasi ke Menu</title>
</head>
<body>
<h1>Pilih Menu</h1>
<button onclick="goToMenu('pulsa-menu-001')">Beli Pulsa</button>
<button onclick="goToMenu('data-menu-002')">Beli Paket Data</button>
<button onclick="goToMenu('listrik-menu-003')">Bayar Listrik</button>
<script>
function goToMenu(menuId) {
window.flutter_inappwebview.callHandler('AppBridge', JSON.stringify({
action: 'menuId',
menuId: menuId
}));
}
</script>
</body>
</html>
Via URL Scheme (tanpa JavaScript):
<a href="hexaflate://menuId?menuId=pulsa-menu-001">Beli Pulsa</a>
<a href="hexaflate://menuId?menuId=data-menu-002">Paket Data</a>
2. Navigasi ke Flutter Route (navigate)
Buka screen tertentu di aplikasi (seperti /product, /history, /profile).
Contoh HTML + JavaScript
Via JavaScript Bridge:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Navigasi Route</title>
</head>
<body>
<h1>Navigasi Cepat</h1>
<button onclick="navigateToRoute('/product')">Beli Produk</button>
<button onclick="navigateToRoute('/history')">Lihat Riwayat</button>
<button onclick="navigateToRoute('/mutasi')">Mutasi Saldo</button>
<button onclick="navigateToRoute('/profile')">Profil</button>
<button onclick="navigateToRoute('/settings')">Pengaturan</button>
<button onclick="navigateToProductWithOperator()">Beli Pulsa Indosat</button>
<script>
function navigateToRoute(route) {
window.flutter_inappwebview.callHandler('AppBridge', JSON.stringify({
action: 'navigate',
route: route
}));
}
function navigateToProductWithOperator() {
window.flutter_inappwebview.callHandler('AppBridge', JSON.stringify({
action: 'navigate',
route: '/product',
args: {
operators: ['INDOSAT'],
hintText: 'Masukkan nomor Indosat',
screenTitle: 'Pulsa Indosat'
}
}));
}
</script>
</body>
</html>
Via URL Scheme (tanpa JavaScript):
<!-- Navigasi sederhana tanpa args -->
<a href="hexaflate://navigate/history">Riwayat Transaksi</a>
<a href="hexaflate://navigate/profile">Profil Saya</a>
<!-- Navigasi dengan args via query parameters -->
<a href="hexaflate://navigate/product?screenTitle=Pulsa%20Indosat&hintText=Masukkan%20nomor&operators=INDOSAT">
Beli Pulsa Indosat
</a>
Catatan: Query parameters diterjemahkan sebagai key-value string di
args. Parameter yang membutuhkan array (sepertioperators) hanya bisa menerima satu nilai via URL. Gunakan JavaScript Bridge jika perlu multiple values.
Route yang Tersedia
Main Screens:
/history- Riwayat transaksi/mutasi- Mutasi saldo/profileatau/profile_screen- Profil pengguna/settingsatau/settings_screen- Pengaturan aplikasi/product- Pencarian produk (mendukung arguments)/downline_list- Daftar downline/all_senders_screen- Daftar semua pengirim/jaringan- Informasi jaringan/network/pusat_bantuan- Pusat bantuan/tentang_aplikasiatau/about- Tentang aplikasi/menu_deposit- Menu deposit/balance_transfer- Transfer saldo/poin_exchange- Tukar poin/chat- Chat customer service/piutang- Piutang/hutang/bookkeeping- Pembukuan/register_downline- Daftar downline baru
Route Arguments yang Sering Dipakai
Untuk Route /product
{
operators: ['TELKOMSEL', 'INDOSAT'], // Filter operator
hintText: 'Masukkan nomor HP', // Hint input
alphanumeric: false, // Input alfanumerik?
screenTitle: 'Beli Pulsa' // Judul screen
}
Untuk Route /webview
{
url: 'https://example.com', // URL yang dibuka
title: 'Judul WebView' // Judul screen
}
3. Buka WebView Baru (webview)
Buka halaman web lain di dalam aplikasi (nested webview).
Contoh HTML + JavaScript
Via JavaScript Bridge:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Buka WebView</title>
</head>
<body>
<h1>Link Eksternal</h1>
<button onclick="openWebView('https://example.com/promo', 'Promo Spesial')">Lihat Promo</button>
<button onclick="openWebView('https://example.com/terms', 'Syarat & Ketentuan')">S&K</button>
<script>
function openWebView(url, title) {
window.flutter_inappwebview.callHandler('AppBridge', JSON.stringify({
action: 'webview',
url: url,
title: title
}));
}
</script>
</body>
</html>
Via URL Scheme (tanpa JavaScript):
<a href="hexaflate://webview?url=https://example.com/promo&title=Promo%20Spesial">
Lihat Promo
</a>
<a href="hexaflate://webview?url=https://example.com/help&title=Bantuan">
Bantuan
</a>
Catatan: Parameter
headerstidak bisa dikirim via URL scheme karena formatnya JSON. Gunakan JavaScript Bridge jika perlu custom headers.
4. Tampilkan Submenu (submenu)
Tampilkan daftar menu dalam bottom sheet atau full screen.
Contoh HTML + JavaScript
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Submenu</title>
</head>
<body>
<h1>Menu Layanan</h1>
<button onclick="showBottomSheetSubmenu()">Pilih Operator (Bottom Sheet)</button>
<button onclick="showFullScreenSubmenu()">Pilih Operator (Full Screen)</button>
<script>
function showBottomSheetSubmenu() {
window.flutter_inappwebview.callHandler('AppBridge', JSON.stringify({
action: 'submenu',
submenu: {
submenuTitle: 'Pilih Operator',
submenuStyle: 'bottomSheet',
submenuLayout: 'grid',
items: [
{
title: 'Telkomsel',
iconUrl: 'https://example.com/icon-telkomsel.png',
menuId: 'pulsa-telkomsel-001'
},
{
title: 'Indosat',
iconUrl: 'https://example.com/icon-indosat.png',
menuId: 'pulsa-indosat-002'
}
]
}
}));
}
function showFullScreenSubmenu() {
window.flutter_inappwebview.callHandler('AppBridge', JSON.stringify({
action: 'submenu',
submenu: {
submenuTitle: 'Pilih Operator',
submenuStyle: 'fullScreen',
submenuLayout: 'grid',
items: [
{
title: 'Telkomsel',
iconUrl: 'https://example.com/icon-telkomsel.png',
route: '/product',
routeArgs: {
operators: ['TELKOMSEL'],
screenTitle: 'Pulsa Telkomsel'
}
}
]
}
}));
}
</script>
</body>
</html>
5. Tampilkan Print Preview (print)
Tampilkan preview cetak struk/receipt dengan data custom dari WebView.
Struktur Data Print
{
action: 'print',
printData: {
// Data Utama (Required)
id: 'TRX001',
kode_produk: 'PLN20',
tujuan: '081234567890',
harga: 20000,
status: 20,
// Data Opsional
tgl_status: '2026-06-24 10:30:00',
jasa_outlet: 2000,
sn: 'SN123456789',
// Custom fields (akan muncul di struk)
token: '1234-5678-9012',
nama_pelanggan: 'John Doe'
}
}
Contoh HTML + JavaScript
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Print Receipt</title>
</head>
<body>
<h1>Detail Transaksi</h1>
<h2>Transaksi #TRX001</h2>
<p>Produk: Token PLN 20K</p>
<p>No. Meter: 12345678901</p>
<p>Token: 1234-5678-9012-3456</p>
<p>Total: Rp 20.000</p>
<p>Status: Berhasil</p>
<button onclick="printReceipt()">Cetak Struk</button>
<script>
function printReceipt() {
window.flutter_inappwebview.callHandler('AppBridge', JSON.stringify({
action: 'print',
printData: {
id: 'TRX001',
kode_produk: 'PLN20',
tujuan: '12345678901',
harga: 20000,
status: 20,
tgl_status: '2026-06-24 10:30:00',
sn: '1234-5678-9012-3456',
nama_pelanggan: 'John Doe',
daya: '900 VA'
}
}));
}
</script>
</body>
</html>
6. Buka URL di Browser Eksternal (external)
Buka URL di browser default sistem (Chrome, Safari, dll).
Cara 1: Menggunakan JavaScript Bridge
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Link Eksternal</title>
</head>
<body>
<h1>Link Eksternal</h1>
<button onclick="openExternal('https://www.google.com')">Buka Google</button>
<button onclick="openExternal('https://www.youtube.com')">Buka YouTube</button>
<script>
function openExternal(url) {
window.flutter_inappwebview.callHandler('AppBridge', JSON.stringify({
action: 'external',
url: url
}));
}
</script>
</body>
</html>
Via URL Scheme:
<a href="hexaflate://external?url=https://www.google.com">Buka Google</a>
<a href="hexaflate://external?url=https://www.youtube.com">Buka YouTube</a>
Cara 2: Menggunakan URL Parameter ?newbrowser=ok
Cara ini lebih sederhana karena tidak perlu JavaScript! Cukup tambahkan ?newbrowser=ok di URL.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Link Eksternal</title>
</head>
<body>
<h1>Link Eksternal (Tanpa JavaScript)</h1>
<a href="https://www.google.com?newbrowser=ok">Buka Google</a><br>
<a href="https://www.youtube.com?newbrowser=ok">Buka YouTube</a><br>
<a href="https://wa.me/6281234567890?newbrowser=ok">WhatsApp CS</a><br>
<!-- Jika URL sudah punya query parameter, gunakan & -->
<a href="https://example.com/page?id=123&newbrowser=ok">Link dengan Parameter Lain</a>
</body>
</html>
7. Reload & Back (reload, back)
Fungsi utilitas untuk refresh halaman atau kembali.
Contoh HTML + JavaScript
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Utilitas</title>
</head>
<body>
<h1>Utilitas WebView</h1>
<button onclick="reloadPage()">Refresh Halaman</button>
<button onclick="goBack()">Kembali</button>
<script>
function reloadPage() {
window.flutter_inappwebview.callHandler('AppBridge', JSON.stringify({
action: 'reload'
}));
}
function goBack() {
window.flutter_inappwebview.callHandler('AppBridge', JSON.stringify({
action: 'back'
}));
}
</script>
</body>
</html>
Via URL Scheme (tanpa JavaScript):
<a href="hexaflate://reload">Refresh Halaman</a>
<a href="hexaflate://back">Kembali</a>
Contoh Lengkap: Halaman Dashboard
Halaman lengkap dengan berbagai jenis navigasi.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Dashboard Layanan</title>
</head>
<body>
<h1>Dashboard Layanan</h1>
<p>Pilih layanan yang Anda butuhkan</p>
<h2>Menu Utama</h2>
<button onclick="goToMenu('pulsa-menu-001')">Beli Pulsa</button>
<button onclick="goToMenu('data-menu-002')">Paket Data</button>
<button onclick="goToMenu('listrik-menu-003')">Token Listrik</button>
<h2>Navigasi Cepat</h2>
<button onclick="navigateToRoute('/history')">Riwayat Transaksi</button>
<button onclick="navigateToRoute('/mutasi')">Mutasi Saldo</button>
<button onclick="navigateToRoute('/profile')">Profil Saya</button>
<button onclick="navigateToRoute('/settings')">Pengaturan</button>
<button onclick="navigateToRoute('/chat')">Chat CS</button>
<h2>Informasi</h2>
<button onclick="openWebView('https://example.com/promo', 'Promo')">Lihat Promo</button>
<button onclick="openWebView('https://example.com/help', 'Bantuan')">Bantuan</button>
<h2>Link Eksternal</h2>
<button onclick="openExternal('https://wa.me/6281234567890')">Hubungi CS via WhatsApp</button>
<script>
function goToMenu(menuId) {
window.flutter_inappwebview.callHandler('AppBridge', JSON.stringify({
action: 'menuId',
menuId: menuId
}));
}
function navigateToRoute(route) {
window.flutter_inappwebview.callHandler('AppBridge', JSON.stringify({
action: 'navigate',
route: route
}));
}
function openWebView(url, title) {
window.flutter_inappwebview.callHandler('AppBridge', JSON.stringify({
action: 'webview',
url: url,
title: title
}));
}
function openExternal(url) {
window.flutter_inappwebview.callHandler('AppBridge', JSON.stringify({
action: 'external',
url: url
}));
}
</script>
</body>
</html>
Alternatif: Halaman Sama dengan URL Scheme
Navigasi yang sama bisa dilakukan tanpa JavaScript sama sekali menggunakan tag <a>:
<h2>Menu Utama (URL Scheme)</h2>
<a href="hexaflate://menuId?menuId=pulsa-menu-001">Beli Pulsa</a><br>
<a href="hexaflate://menuId?menuId=data-menu-002">Paket Data</a><br>
<a href="hexaflate://menuId?menuId=listrik-menu-003">Token Listrik</a><br>
<h2>Navigasi Cepat (URL Scheme)</h2>
<a href="hexaflate://navigate/history">Riwayat Transaksi</a><br>
<a href="hexaflate://navigate/profile">Profil Saya</a><br>
<a href="hexaflate://navigate/product?screenTitle=Pulsa">Beli Produk</a><br>
<h2>Informasi (URL Scheme)</h2>
<a href="hexaflate://webview?url=https://example.com/promo&title=Promo">Lihat Promo</a><br>
<a href="hexaflate://webview?url=https://example.com/help&title=Bantuan">Bantuan</a><br>
<h2>Link Eksternal (URL Scheme)</h2>
<a href="hexaflate://external?url=https://wa.me/6281234567890">Hubungi CS via WhatsApp</a><br>
<a href="hexaflate://back">Kembali</a>
Referensi Lengkap Parameter
menuId Action
{
action: 'menuId',
menuId: 'string' // Required: ID menu dari admin panel
}
URL Scheme: hexaflate://menuId?menuId=<id>
navigate Action
{
action: 'navigate',
route: 'string', // Required: Route Flutter (contoh: '/product')
args: {} // Optional: Arguments untuk route
}
URL Scheme: hexaflate://navigate/<route>?<key>=<value>&...
webview Action
{
action: 'webview',
url: 'string', // Required: URL yang akan dibuka
title: 'string' // Optional: Judul WebView
}
URL Scheme: hexaflate://webview?url=<url>&title=<title>
submenu Action
{
action: 'submenu',
submenu: {
submenuTitle: 'string', // Required: Judul submenu
submenuStyle: 'string', // 'bottomSheet' atau 'fullScreen'
submenuLayout: 'string', // 'grid' atau 'list'
items: [ // Required: Array menu items
{
title: 'string', // Required
iconUrl: 'string', // Optional
menuId: 'string' // Option 1: Reference menu lain
}
]
}
}
print Action
{
action: 'print',
printData: {
id: 'string', // Required
kode_produk: 'string', // Required
tujuan: 'string', // Required
harga: number, // Required (integer)
status: number, // Required (20 = success)
tgl_status: 'string', // Optional
jasa_outlet: number, // Optional (integer)
sn: 'string' // Optional (akan di-highlight)
}
}
external Action
{
action: 'external',
url: 'string' // Required: URL yang dibuka di browser
}
URL Scheme: hexaflate://external?url=<url>
reload Action
{
action: 'reload' // Tidak perlu parameter tambahan
}
URL Scheme: hexaflate://reload
back Action
{
action: 'back' // Tidak perlu parameter tambahan
}
URL Scheme: hexaflate://back
Tips Penggunaan
-
Gunakan
menuIduntuk Fleksibilitas// Rekomendasi goToMenu('pulsa-telkomsel-001'); // Kurang fleksibel navigateToRoute('/product', { operators: ['TELKOMSEL'] }); -
Gunakan URL Scheme untuk Navigasi Sederhana Untuk navigasi tanpa argumen kompleks, URL scheme lebih praktis:
<!-- Rekomendasi untuk navigasi sederhana --> <a href="hexaflate://navigate/history">Riwayat</a> <a href="hexaflate://menuId?menuId=pulsa-menu-001">Pulsa</a> <a href="hexaflate://back">Kembali</a> <!-- Gunakan JavaScript Bridge untuk data kompleks --> <button onclick="navigateToProductWithOperator()">Pulsa Indosat</button> -
URL Parameter
?newbrowser=okuntuk Link Eksternal<!-- Rekomendasi untuk link eksternal statis --> <a href="https://wa.me/6281234567890?newbrowser=ok">Chat WhatsApp</a> <!-- Overkill --> <button onclick="openExternal('https://wa.me/6281234567890')">Chat</button> -
Encode Nilai Query Parameter Jika nilai parameter mengandung spasi atau karakter khusus, gunakan URL encoding:
<!-- Benar --> <a href="hexaflate://navigate/product?screenTitle=Pulsa%20Indosat">Pulsa</a> <!-- Salah (spasi tidak di-encode) --> <a href="hexaflate://navigate/product?screenTitle=Pulsa Indosat">Pulsa</a> -
Tambahkan Error Handling
function safeNavigate(action, params) { try { window.flutter_inappwebview.callHandler('AppBridge', JSON.stringify({ action: action, ...params })); } catch (error) { console.error('Navigation error:', error); alert('Gagal melakukan navigasi. Silakan coba lagi.'); } }
Troubleshooting
URL Scheme Tidak Bekerja
Masalah: Saat klik link hexaflate://..., tidak terjadi apa-apa (halaman tidak merespon).
Solusi:
- Pastikan aplikasi menggunakan versi terbaru yang mendukung URL scheme bridge
- Coba gunakan JavaScript Bridge sebagai alternatif
- Periksa console browser untuk error:
console.log('Navigating via URL scheme...'); window.location.href = 'hexaflate://navigate/history';
JavaScript Bridge Tidak Bekerja
Masalah:
Uncaught ReferenceError: flutter_inappwebview is not defined
Solusi: Tambahkan delay untuk memastikan bridge siap:
setTimeout(function() {
window.flutter_inappwebview.callHandler('AppBridge', ...);
}, 100);
Menu ID Tidak Ditemukan
Solusi:
- Periksa Menu ID di Admin Panel
- Pastikan menu sudah di-publish
- Gunakan console.log untuk debug:
console.log('Navigating to menu:', menuId);
Kesimpulan
Hexaflate WebView menyediakan dua metode untuk navigasi dari halaman web:
| Metode | Kelebihan | Cocok Untuk |
|---|---|---|
| JavaScript Bridge | Mendukung data kompleks (array, nested object), error handling | Navigasi dengan argumen dinamis, submenu, print |
URL Scheme (hexaflate://) | Sederhana, tanpa JavaScript, bisa pakai tag <a> biasa | Navigasi sederhana, link statis, tombol back/reload |
Action yang Tersedia
menuId- Reference menu lainnavigate- Navigate ke routewebview- Buka WebView barusubmenu- Tampilkan submenu (via JS Bridge saja)print- Print preview custom data (via JS Bridge saja)external- Buka browser eksternalreload- Refresh halamanback- Kembali/tutup