Lewati ke konten

Panduan Events

CATATAN: Panduan ini masih dalam proses penyusunan

Events adalah denyut nadi komunikasi di aplikasi Wails. Events memungkinkan berbagai bagian aplikasi Anda saling berkomunikasi tanpa ketergantungan yang ketat. Panduan ini akan memandu Anda melalui semua yang perlu diketahui tentang penggunaan events secara efektif di aplikasi Wails Anda.

Anggap events sebagai pesan yang disiarkan ke seluruh aplikasi Anda. Bagian mana pun dari aplikasi dapat mendengarkan pesan-pesan ini dan bereaksi sesuai kebutuhan. Ini sangat berguna untuk:

  • Merespons perubahan window: Mengetahui kapan window diminimalkan, dimaksimalkan, atau dipindahkan
  • Menangani system events: Bereaksi terhadap perubahan tema atau power events
  • Logika aplikasi kustom: Membuat events Anda sendiri untuk fitur seperti pembaruan data atau aksi pengguna
  • Komunikasi antar-komponen: Memungkinkan bagian berbeda dari aplikasi berkomunikasi tanpa ketergantungan langsung

Semua events Wails mengikuti pola namespace untuk menunjukkan asalnya dengan jelas:

  • common: - Events lintas platform yang berfungsi di Windows, macOS, dan Linux
  • windows: - Events khusus Windows
  • mac: - Events khusus macOS
  • linux: - Events khusus Linux

Contoh:

  • common:WindowFocus - Window mendapat fokus (berfungsi di semua platform)
  • windows:APMSuspend - Sistem sedang suspend (hanya Windows)
  • mac:ApplicationDidBecomeActive - Aplikasi menjadi aktif (hanya macOS)

Kasus penggunaan paling umum adalah mendengarkan events di kode frontend Anda:

import { Events } from '@wailsio/runtime';
// Dengarkan saat window mendapat fokus
Events.On('common:WindowFocus', () => {
console.log('Window is now focused!');
// Mungkin refresh beberapa data atau lanjutkan animasi
});
// Dengarkan perubahan tema
Events.On('common:ThemeChanged', (event) => {
console.log('Theme changed:', event.data);
// Perbarui tema aplikasi Anda sesuai kebutuhan
});
// Dengarkan custom events dari backend Go Anda
Events.On('my-app:data-updated', (event) => {
console.log('Data updated:', event.data);
// Perbarui UI dengan data baru
});

Dari kode Go Anda, Anda dapat mengirim events yang dapat didengarkan frontend:

package main
import (
"github.com/wailsapp/wails/v3/pkg/application"
"time"
)
func (s *Service) UpdateData() {
// Lakukan pemrosesan data...
// Beri tahu frontend
app := application.Get()
app.Event.Emit("my-app:data-updated",
map[string]interface{}{
"timestamp": time.Now(),
"count": 42,
},
)
}

Meskipun tidak seumum itu, Anda juga dapat mengirim events dari frontend yang dapat didengarkan kode Go:

import { Events } from '@wailsio/runtime';
// Event tanpa data
Events.Emit('myapp:close-window')
// Event dengan data
Events.Emit('myapp:disconnect-requested', 'id-123')

Jika Anda menggunakan TypeScript di frontend dan mendaftarkan events bertipe di kode Go, Anda akan mendapatkan autocomplete/pemeriksaan nama event dan pemeriksaan tipe data.

Selalu bersihkan event listener saat sudah tidak diperlukan:

import { Events } from '@wailsio/runtime';
// Simpan referensi handler
const focusHandler = () => {
console.log('Window focused');
};
// Tambahkan listener — tangkap fungsi unsubscribe yang dikembalikan
const unsubscribe = Events.On('common:WindowFocus', focusHandler);
// Nanti, hapus listener spesifik ini melalui unsubscribe yang dikembalikan
unsubscribe();
// Atau hapus SEMUA listener untuk satu (atau lebih) nama event — Events.Off hanya menerima string nama event
Events.Off('common:WindowFocus');
// Events.Off('common:WindowFocus', 'common:WindowLostFocus'); // variadic
// Events.OffAll(); // hapus setiap listener untuk setiap event (tanpa argumen)

Banyak aplikasi perlu menjeda aktivitas tertentu saat window kehilangan fokus:

import { Events } from '@wailsio/runtime';
let animationRunning = true;
Events.On('common:WindowLostFocus', () => {
animationRunning = false;
pauseBackgroundTasks();
});
Events.On('common:WindowFocus', () => {
animationRunning = true;
resumeBackgroundTasks();
});

Jaga aplikasi Anda selaras dengan tema sistem:

import { Events } from '@wailsio/runtime';
Events.On('common:ThemeChanged', (event) => {
const isDarkMode = event.data.isDarkMode;
if (isDarkMode) {
document.body.classList.add('dark-theme');
document.body.classList.remove('light-theme');
} else {
document.body.classList.add('light-theme');
document.body.classList.remove('dark-theme');
}
});

Buat aplikasi Anda menerima file yang di-drag:

import { Events } from '@wailsio/runtime';
Events.On('common:WindowFilesDropped', (event) => {
const files = event.data.files;
files.forEach(file => {
console.log('File dropped:', file);
// Proses file yang di-drop
handleFileUpload(file);
});
});

Tanggapi perubahan state window:

import { Events } from '@wailsio/runtime';
Events.On('common:WindowClosing', () => {
// Simpan data pengguna sebelum menutup
saveApplicationState();
// Anda juga bisa mencegah penutupan dengan mengembalikan false
// dari window close handler yang terdaftar
});
Events.On('common:WindowMaximise', () => {
// Sesuaikan UI untuk tampilan maksimal
adjustLayoutForMaximized();
});
Events.On('common:WindowRestore', () => {
// Kembalikan UI ke state normal
adjustLayoutForNormal();
});

Tangani events khusus platform saat diperlukan:

import { Events } from '@wailsio/runtime';
// Manajemen daya khusus Windows
Events.On('windows:APMSuspend', () => {
console.log('System is going to sleep');
saveState();
});
Events.On('windows:APMResumeSuspend', () => {
console.log('System woke up');
refreshData();
});
// Lifecycle aplikasi khusus macOS
Events.On('mac:ApplicationWillTerminate', () => {
console.log('App is about to quit');
performCleanup();
});

Anda dapat membuat events sendiri untuk kebutuhan spesifik aplikasi.

// Kirim custom event saat data berubah
func (s *Service) ProcessUserData(userData UserData) error {
// Proses data...
app := application.Get()
// Beri tahu semua listener
app.Event.Emit("user:data-processed",
map[string]interface{}{
"userId": userData.ID,
"status": "completed",
"timestamp": time.Now(),
},
)
return nil
}
// Kirim pembaruan berkala
func (s *Service) StartMonitoring() {
app := application.Get()
ticker := time.NewTicker(5 * time.Second)
go func() {
for range ticker.C {
stats := s.collectStats()
app.Event.Emit("monitor:stats-updated", stats)
}
}()
}
import { Events } from '@wailsio/runtime';
// Dengarkan custom events Anda
Events.On('user:data-processed', (event) => {
const { userId, status, timestamp } = event.data;
showNotification(`User ${userId} processing ${status}`);
updateUIWithNewData();
});
Events.On('monitor:stats-updated', (event) => {
updateDashboard(event.data);
});

Wails v3 mendukung events bertipe dengan type safety TypeScript penuh melalui registrasi event dan pembuatan binding otomatis.

Panggil application.RegisterEvent saat init untuk mendaftarkan nama custom event beserta tipe datanya:

package main
import "github.com/wailsapp/wails/v3/pkg/application"
type UserLoginData struct {
UserID string
Username string
LoginTime string
}
type MonitorStats struct {
CPUUsage float64
MemoryUsage float64
}
func init() {
// Daftarkan events beserta tipe datanya
application.RegisterEvent[UserLoginData]("user:login")
application.RegisterEvent[MonitorStats]("monitor:stats")
// Daftarkan events tanpa data (void events)
application.RegisterEvent[application.Void]("app:ready")
}

Setelah terdaftar, argumen data yang diteruskan ke Event.Emit diperiksa tipenya terhadap tipe yang ditentukan. Jika tidak cocok:

  • Error dikirim dan dicatat (atau diteruskan ke error handler yang terdaftar)
  • Event yang bermasalah tidak akan dipropagasi
  • Ini memastikan field data dari events terdaftar selalu dapat di-assign ke tipe yang dideklarasikan

Gunakan build tag strictevents untuk mengaktifkan peringatan event yang belum terdaftar saat development:

Terminal window
go build -tags strictevents

Dengan strict mode aktif, runtime mengirim paling banyak satu peringatan per nama event yang belum terdaftar untuk menghindari spam log.

Generator binding menghasilkan definisi TypeScript dan glue code untuk dukungan event bertipe transparan di frontend.

Di vite.config.ts Anda:

import { defineConfig } from 'vite'
import wails from '@wailsio/runtime/plugins/vite'
export default defineConfig({
plugins: [wails()],
})

Jalankan generator binding:

Terminal window
wails3 generate bindings

Ini membuat file TypeScript di direktori frontend Anda dengan event creator bertipe dan interface data.

import { Events } from '@wailsio/runtime'
import { UserLogin, MonitorStats } from './bindings/events'
// Emisi event type-safe dengan autocomplete
Events.Emit(UserLogin({
UserID: "123",
Username: "john_doe",
LoginTime: new Date().toISOString()
}))
// Pendengaran event type-safe
Events.On(UserLogin, (event) => {
// event.data bertipe UserLoginData
console.log(`User ${event.data.Username} logged in`)
})
Events.On(MonitorStats, (event) => {
// event.data bertipe MonitorStats
updateDashboard({
cpu: event.data.CPUUsage,
memory: event.data.MemoryUsage
})
})

Event bertipe menyediakan:

  • Autocomplete untuk nama event
  • Type checking untuk data event
  • Compile-time errors untuk tipe data yang tidak cocok
  • IntelliSense documentation

Events ini berfungsi di semua platform:

EventDeskripsiKapan Digunakan
common:ApplicationStartedAplikasi telah sepenuhnya dimulaiInisialisasi aplikasi, muat state tersimpan
common:WindowRuntimeReadyRuntime Wails siapMulai memanggil Wails API
common:ThemeChangedTema sistem berubahPerbarui tampilan aplikasi
common:SystemWillSleepSistem akan suspendFlush state, tutup socket
common:SystemDidWakeSistem bangun dari suspendReconnect, refresh data yang sudah usang
common:WindowFocusWindow mendapat fokusLanjutkan aktivitas, refresh data
common:WindowLostFocusWindow kehilangan fokusJeda aktivitas, simpan state
common:WindowMinimiseWindow diminimalkanJeda rendering, kurangi penggunaan resource
common:WindowMaximiseWindow dimaksimalkanSesuaikan layout untuk layar penuh
common:WindowRestoreWindow dipulihkan dari min/maxKembali ke layout normal
common:WindowClosingWindow akan ditutupSimpan data, bersihkan resource
common:WindowFilesDroppedFile di-drop ke windowTangani impor file
common:WindowDidResizeWindow di-resizeSesuaikan layout, render ulang chart
common:WindowDidMoveWindow dipindahkanPerbarui fitur yang bergantung posisi

Events penting untuk aplikasi Windows:

EventDeskripsiKasus Penggunaan
windows:SystemThemeChangedTema Windows berubahPerbarui warna aplikasi
windows:APMSuspendSistem suspendSimpan state, jeda operasi
windows:APMResumeAutomaticSistem bangun (selalu fire saat resume)Pulihkan state, refresh data
windows:APMResumeSuspendSistem bangun via input pengguna (setelah APMResumeAutomatic)Bedakan wake yang dipicu pengguna
windows:APMPowerStatusChangeStatus daya berubahSesuaikan pengaturan performa

Events aplikasi macOS penting:

EventDeskripsiKasus Penggunaan
mac:ApplicationDidBecomeActiveAplikasi menjadi aktifLanjutkan operasi
mac:ApplicationDidResignActiveAplikasi menjadi tidak aktifJeda operasi
mac:ApplicationWillTerminateAplikasi akan quitPembersihan akhir
mac:ApplicationWillSleepSistem akan suspendSimpan state, tutup socket
mac:ApplicationDidWakeSistem bangunReconnect, refresh
mac:ApplicationScreensDidSleepDisplay tidurJeda rendering (berbeda dari system sleep)
mac:ApplicationScreensDidWakeDisplay bangunLanjutkan rendering
mac:WindowDidEnterFullScreenMasuk fullscreenSesuaikan UI untuk fullscreen
mac:WindowDidExitFullScreenKeluar fullscreenPulihkan UI normal

Events window Linux inti:

EventDeskripsiKasus Penggunaan
linux:SystemThemeChangedTema desktop berubahPerbarui tema aplikasi
linux:SystemWillSleepSistem akan suspend (logind)Simpan state
linux:SystemDidWakeSistem bangun (logind)Reconnect, refresh
linux:WindowFocusInWindow mendapat fokusLanjutkan aktivitas
linux:WindowFocusOutWindow kehilangan fokusJeda aktivitas
linux:WindowLoadStartedWebView mulai loadingTampilkan indikator loading
linux:WindowLoadRedirectedWebView di-redirectLacak redirect navigasi
linux:WindowLoadCommittedWebView committed loadKonten sedang diterima
linux:WindowLoadFinishedWebView selesai loadingSembunyikan indikator loading, inject JS/CSS

Saat membuat custom events, gunakan namespace untuk menghindari konflik:

import { Events } from '@wailsio/runtime';
// Baik — events dengan namespace
Events.Emit('myapp:user:login');
Events.Emit('myapp:data:updated');
Events.Emit('myapp:network:connected');
// Hindari — nama generik yang mungkin konflik
Events.Emit('login');
Events.Emit('update');

Selalu hapus event listener saat komponen unmount:

import { Events } from '@wailsio/runtime';
// Contoh React
useEffect(() => {
const handler = (event) => {
// Tangani event
};
const off = Events.On('common:WindowDidResize', handler);
// Cleanup — panggil unsubscribe yang dikembalikan Events.On
return () => {
off();
};
}, []);

Periksa ketersediaan platform saat menggunakan events khusus platform:

import { Events } from '@wailsio/runtime';
// Events khusus platform dapat didaftarkan tanpa syarat;
// mereka hanya tidak akan pernah fire di platform yang tidak didukung.
Events.On('windows:APMSuspend', handleSuspend);
Events.On('mac:ApplicationWillTerminate', handleTerminate);

Meskipun events sangat powerful, jangan gunakan untuk segalanya:

  • ✅ Gunakan events untuk: Notifikasi sistem, perubahan lifecycle, broadcast update
  • ❌ Hindari events untuk: Return fungsi langsung, update komponen tunggal, operasi sinkron

Untuk debug masalah event:

import { Events } from '@wailsio/runtime';
// Log semua events (development saja)
if (isDevelopment) {
const originalOn = Events.On;
Events.On = function(eventName, handler) {
console.log(`[Event Registered] ${eventName}`);
return originalOn.call(this, eventName, function(event) {
console.log(`[Event Fired] ${eventName}`, event);
return handler(event);
});
};
}

Daftar lengkap events yang tersedia dapat ditemukan di source code Wails:

Selalu rujuk file-file ini untuk nama event dan ketersediaan terbaru.

Events di Wails menyediakan cara yang powerful dan terdecouple untuk menangani komunikasi di aplikasi Anda. Dengan mengikuti pola dan praktik dalam panduan ini, Anda dapat membangun aplikasi responsif yang aware terhadap platform dan bereaksi mulus terhadap perubahan sistem serta interaksi pengguna.

Ingat: mulai dengan common events untuk kompatibilitas lintas platform, tambahkan events khusus platform saat diperlukan, dan selalu bersihkan event listener untuk mencegah memory leak.