Lewati ke konten

Menu

Wails v3 menyediakan sistem menu yang powerful yang memungkinkan Anda membuat menu aplikasi dan menu konteks. Panduan ini akan memandu Anda melalui berbagai fitur dan kemampuan sistem menu.

Untuk membuat menu baru, gunakan method New() dari manager Menus:

menu := app.Menu.New()

Wails mendukung beberapa tipe item menu, masing-masing dengan tujuan spesifik:

Item menu reguler adalah blok dasar menu. Item ini menampilkan teks dan dapat memicu aksi saat diklik:

menuItem := menu.Add("Click Me")

Item menu checkbox menyediakan state yang dapat di-toggle, berguna untuk mengaktifkan/menonaktifkan fitur atau pengaturan:

checkbox := menu.AddCheckbox("My checkbox", true) // true = initially checked

Grup radio memungkinkan pengguna memilih satu opsi dari sekumpulan pilihan yang saling eksklusif. Grup dibuat otomatis saat item radio ditempatkan berdampingan:

menu.AddRadio("Option 1", true) // true = initially selected
menu.AddRadio("Option 2", false)
menu.AddRadio("Option 3", false)

Separator adalah garis horizontal yang membantu mengorganisir item menu ke dalam grup logis:

menu.AddSeparator()

Submenu adalah menu bersarang yang muncul saat hover atau klik item menu. Berguna untuk mengorganisir struktur menu yang kompleks:

submenu := menu.AddSubmenu("File")
submenu.Add("Open")
submenu.Add("Save")

Menu dapat ditambahkan ke menu lain dengan append atau prepend.

menu := app.Menu.New()
menu.Add("First Menu")
secondaryMenu := app.Menu.New()
secondaryMenu.Add("Second Menu")
// insert 'secondaryMenu' after 'menu'
menu.Append(secondaryMenu)
// insert 'secondaryMenu' before 'menu'
menu.Prepend(secondaryMenu)
// update the menu
menu.Update()

Dalam beberapa kasus, lebih baik membangun menu baru jika Anda bekerja dengan jumlah item menu yang bervariasi.

Ini akan membersihkan semua item pada menu yang ada dan memungkinkan Anda menambahkan item lagi.

menu := app.Menu.New()
menu.Add("Waiting for update...")
// after certain logic, the menu has to be updated
menu.Clear()
menu.Add("Update complete!")
menu.Update()

Jika Anda ingin membersihkan dan melepaskan menu, gunakan method Destroy():

menu := app.Menu.New()
menu.Add("Waiting for update...")
// after certain logic, the menu has to be destroyed
menu.Destroy()

Item menu memiliki beberapa properti yang dapat dikonfigurasi:

PropertiMethodDeskripsi
LabelSetLabel(string)Mengatur teks tampilan
EnabledSetEnabled(bool)Mengaktifkan/menonaktifkan item
CheckedSetChecked(bool)Mengatur state checked (untuk checkbox/radio)
TooltipSetTooltip(string)Mengatur teks tooltip
HiddenSetHidden(bool)Menampilkan/menyembunyikan item
AcceleratorSetAccelerator(string)Mengatur keyboard shortcut

Item menu dapat berada dalam state berbeda yang mengontrol visibilitas dan interaktivitas:

Item menu dapat ditampilkan atau disembunyikan secara dinamis menggunakan method SetHidden():

menuItem := menu.Add("Dynamic Item")
// Hide the menu item
menuItem.SetHidden(true)
// Show the menu item
menuItem.SetHidden(false)
// Check current visibility
isHidden := menuItem.Hidden()

Item menu yang disembunyikan sepenuhnya dihapus dari menu hingga ditampilkan kembali. Berguna untuk item menu kontekstual yang hanya muncul dalam state aplikasi tertentu.

Item menu dapat diaktifkan atau dinonaktifkan menggunakan method SetEnabled():

menuItem := menu.Add("Save")
// Disable the menu item
menuItem.SetEnabled(false) // Item appears grayed out and cannot be clicked
// Enable the menu item
menuItem.SetEnabled(true) // Item becomes clickable again
// Check current enabled state
isEnabled := menuItem.Enabled()

Item menu yang dinonaktifkan tetap terlihat tetapi tampak abu-abu dan tidak dapat diklik. Umum digunakan untuk menandakan aksi saat ini tidak tersedia, seperti:

  • Menonaktifkan “Save” saat tidak ada perubahan untuk disimpan
  • Menonaktifkan “Copy” saat tidak ada yang dipilih
  • Menonaktifkan “Undo” saat tidak ada aksi untuk di-undo

Anda dapat menggabungkan state ini dengan event handler untuk membuat menu dinamis:

saveMenuItem := menu.Add("Save")
// Initially disable the Save menu item
saveMenuItem.SetEnabled(false)
// Enable Save only when there are unsaved changes
documentChanged := func() {
saveMenuItem.SetEnabled(true)
menu.Update() // Remember to update the menu after changing states
}
// Disable Save after saving
documentSaved := func() {
saveMenuItem.SetEnabled(false)
menu.Update()
}

Item menu dapat merespons event klik menggunakan method OnClick:

menuItem.OnClick(func(ctx *application.Context) {
// Handle the click event
println("Menu item clicked!")
})

Context menyediakan informasi tentang item menu yang diklik:

menuItem.OnClick(func(ctx *application.Context) {
// Get the clicked menu item
clickedItem := ctx.ClickedMenuItem()
// Get its current state
isChecked := clickedItem.Checked()
})

Wails menyediakan sekumpulan role menu yang telah didefinisikan yang secara otomatis membuat item menu dengan fungsionalitas standar. Berikut role menu yang didukung:

Role ini membuat struktur menu lengkap dengan fungsionalitas umum:

RoleDeskripsiCatatan Platform
AppMenuMenu aplikasi dengan About, Services, Hide/Show, dan QuitmacOS saja
EditMenuMenu Edit standar dengan Undo, Redo, Cut, Copy, Paste, dll.Semua platform
ViewMenuMenu View dengan kontrol Reload, Zoom, dan FullscreenSemua platform
WindowMenuKontrol window (Minimise, Zoom, dll.)Semua platform
HelpMenuMenu Help dengan tautan “Learn More” ke situs WailsSemua platform

Role ini dapat digunakan untuk menambahkan item menu individual:

RoleDeskripsiCatatan Platform
AboutMenampilkan dialog About aplikasiSemua platform
HideMenyembunyikan aplikasimacOS saja
HideOthersMenyembunyikan aplikasi lainmacOS saja
UnHideMenampilkan aplikasi yang disembunyikanmacOS saja
CloseWindowMenutup window saat iniSemua platform
MinimiseMeminimalkan windowSemua platform
ZoomZoom windowmacOS saja
FrontMembawa window ke depanmacOS saja
QuitKeluar dari aplikasiSemua platform
UndoUndo aksi terakhirSemua platform
RedoRedo aksi terakhirSemua platform
CutCut seleksiSemua platform
CopyCopy seleksiSemua platform
PastePaste dari clipboardSemua platform
PasteAndMatchStylePaste dan cocokkan stylemacOS saja
SelectAllPilih semuaSemua platform
DeleteHapus seleksiSemua platform
ReloadReload halaman saat iniSemua platform
ForceReloadForce reload halaman saat iniSemua platform
ToggleFullscreenToggle mode fullscreenSemua platform
ResetZoomReset level zoomSemua platform
ZoomInPerbesar zoomSemua platform
ZoomOutPerkecil zoomSemua platform

Berikut contoh penggunaan menu lengkap dan role individual:

menu := app.Menu.New()
// Add complete menu structures
menu.AddRole(application.AppMenu) // macOS only
menu.AddRole(application.EditMenu) // Common edit operations
menu.AddRole(application.ViewMenu) // View controls
menu.AddRole(application.WindowMenu) // Window controls
// Add individual role-based items to a custom menu
fileMenu := menu.AddSubmenu("File")
fileMenu.AddRole(application.CloseWindow)
fileMenu.AddSeparator()
fileMenu.AddRole(application.Quit)

Menu aplikasi adalah menu yang muncul di bagian atas window aplikasi (Windows/Linux) atau di bagian atas layar (macOS).

Saat Anda mengatur menu aplikasi menggunakan app.Menu.Set(), menu tersebut menjadi menu utama di macOS. Menu diatur per window untuk Windows/Linux.

app.Window.NewWithOptions(application.WebviewWindowOptions{
Title: "Custom Menu Window",
Windows: application.WindowsWindow{
Menu: customMenu, // Override application menu for this window
},
})

Berikut contoh lengkap yang menunjukkan perilaku menu berbeda:

func main() {
app := application.New(application.Options{})
// Create application menu
appMenu := app.Menu.New()
fileMenu := appMenu.AddSubmenu("File")
fileMenu.Add("New").OnClick(func(ctx *application.Context) {
// This will be available in all windows unless overridden
window := app.Window.Current()
window.SetTitle("New Window")
})
// Set as application menu - this is for macOS
app.Menu.Set(appMenu)
// Window with custom menu on Windows
customMenu := app.Menu.New()
customMenu.Add("Custom Action")
app.Window.NewWithOptions(application.WebviewWindowOptions{
Title: "Custom Menu",
Windows: application.WindowsWindow{
Menu: customMenu,
},
})
app.Run()
}

Menu konteks adalah menu popup yang muncul saat klik kanan elemen di aplikasi Anda. Menu ini memberikan akses cepat ke aksi yang relevan untuk elemen yang diklik.

Menu konteks default adalah menu konteks bawaan webview yang menyediakan operasi level sistem seperti:

  • Copy, Cut, dan Paste untuk manipulasi teks
  • Kontrol seleksi teks
  • Opsi spell checking

Anda dapat mengontrol kapan menu konteks default muncul menggunakan properti CSS --default-contextmenu:

<!-- Always show default context menu -->
<div style="--default-contextmenu: show">
<input type="text" placeholder="Right-click for text operations"/>
<textarea>Standard text operations available here</textarea>
</div>
<!-- Hide default context menu -->
<div style="--default-contextmenu: hide">
<div class="custom-component">Custom context menu only</div>
</div>
<!-- Smart context menu behaviour (default) -->
<div style="--default-contextmenu: auto">
<!-- Shows default menu when text is selected or in input fields -->
<p>Select this text to see the default menu</p>
<input type="text" placeholder="Default menu for input operations"/>
</div>

Saat menggunakan properti --default-contextmenu pada elemen bersarang, aturan berikut berlaku:

  1. Elemen anak mewarisi pengaturan menu konteks induk kecuali secara eksplisit di-override
  2. Pengaturan paling spesifik (terdekat) yang diutamakan
  3. Nilai auto dapat digunakan untuk reset ke perilaku default

Contoh perilaku menu konteks bersarang:

<!-- Parent sets hide -->
<div style="--default-contextmenu: hide">
<!-- This inherits hide -->
<p>No context menu here</p>
<!-- This overrides to show -->
<div style="--default-contextmenu: show">
<p>Context menu shown here</p>
<!-- This inherits show -->
<span>Also has context menu</span>
<!-- This resets to automatic behaviour -->
<div style="--default-contextmenu: auto">
<p>Shows menu only when text is selected</p>
</div>
</div>
</div>

Menu konteks kustom memungkinkan Anda menyediakan aksi spesifik aplikasi yang relevan dengan elemen yang diklik. Sangat berguna untuk:

  • Operasi file di document manager
  • Alat manipulasi gambar
  • Aksi kustom di data grid
  • Operasi spesifik komponen

Saat membuat menu konteks kustom, Anda menyediakan identifier unik (nama) yang menghubungkan menu ke elemen HTML:

// Create a context menu with identifier "imageMenu"
contextMenu := app.ContextMenu.New()
app.ContextMenu.Add("imageMenu", contextMenu)

Parameter name (“imageMenu” dalam contoh ini) berfungsi sebagai identifier unik yang akan digunakan untuk:

  1. Menghubungkan elemen HTML ke menu konteks spesifik ini
  2. Mengidentifikasi menu mana yang ditampilkan saat klik kanan
  3. Memungkinkan pembaruan dan pembersihan menu

Saat menangani event menu konteks, Anda dapat mengakses item menu yang diklik dan data konteks terkait:

contextMenu.Add("Process").OnClick(func(ctx *application.Context) {
// Get the clicked menu item
menuItem := ctx.ClickedMenuItem()
// Get the context data as a string
contextData := ctx.ContextMenuData()
// Check if the menu item is checked (for checkbox/radio items)
isChecked := ctx.IsChecked()
// Use the data
if contextData != "" {
processItem(contextData)
}
})

Data konteks diteruskan dari properti --custom-contextmenu-data elemen HTML dan tersedia di click handler melalui ctx.ContextMenuData(). Sangat berguna saat:

  • Bekerja dengan list atau grid di mana setiap item membutuhkan identifikasi unik
  • Menangani operasi pada komponen atau elemen spesifik
  • Meneruskan state atau metadata dari frontend ke backend

Setelah melakukan perubahan pada menu konteks, panggil method Update() untuk menerapkan perubahan:

contextMenu.Update()

Saat menu konteks tidak lagi diperlukan, Anda dapat menghancurkannya:

contextMenu.Destroy()

Berikut contoh lengkap implementasi menu konteks kustom untuk galeri gambar:

// Backend: Create the context menu
imageMenu := app.ContextMenu.New()
app.ContextMenu.Add("imageMenu", imageMenu)
// Add relevant operations
imageMenu.Add("View Full Size").OnClick(func(ctx *application.Context) {
// Get the image ID from context data
if imageID := ctx.ContextMenuData(); imageID != "" {
openFullSizeImage(imageID)
}
})
imageMenu.Add("Download").OnClick(func(ctx *application.Context) {
if imageID := ctx.ContextMenuData(); imageID != "" {
downloadImage(imageID)
}
})
imageMenu.Add("Share").OnClick(func(ctx *application.Context) {
if imageID := ctx.ContextMenuData(); imageID != "" {
showShareDialog(imageID)
}
})
<!-- Frontend: Image gallery implementation -->
<div class="gallery">
<!-- Each image container with context menu -->
<div class="image-container"
style="--custom-contextmenu: imageMenu; --custom-contextmenu-data: img_123">
<img src="/images/img_123.jpg" alt="Gallery Image"/>
<span class="caption">Nature Photo</span>
</div>
<div class="image-container"
style="--custom-contextmenu: imageMenu; --custom-contextmenu-data: img_124">
<img src="/images/img_124.jpg" alt="Gallery Image"/>
<span class="caption">City Photo</span>
</div>
</div>

Dalam contoh ini:

  1. Menu konteks dibuat dengan identifier “imageMenu”
  2. Setiap container gambar dihubungkan ke menu menggunakan --custom-contextmenu: imageMenu
  3. Setiap container menyediakan ID gambar sebagai data konteks menggunakan --custom-contextmenu-data
  4. Backend menerima ID gambar di click handler dan dapat melakukan operasi spesifik
  5. Menu yang sama digunakan ulang untuk semua gambar, tetapi data konteks memberi tahu gambar mana yang dioperasikan

Pola ini sangat powerful untuk:

  • Data grid di mana baris membutuhkan operasi spesifik
  • File manager di mana file membutuhkan aksi spesifik konteks
  • Alat desain di mana elemen berbeda membutuhkan operasi berbeda
  • Komponen apa pun di mana operasi yang sama berlaku untuk banyak instance