UCloud logo UCloud logo UCloud
v2026.3.0
  1. UCloud/Core
  2. 1. Introduction
  3. 2. Projects
  4. 3. Accounting
  5. 4. Orchestration
  6. 5. Frontend
  7. UCloud/IM for Slurm-based HPC
  8. 6. Installation
  9. 7. Architecture and Networking
  10. 8. User and Project Management
  11. 9. Filesystem Integration
    1. 9.1. Inter-provider file transfers
  12. 10. Slurm Integration
    1. 10.1. Application Management
    2. 10.2. Built-in Applications
  13. 11. Reference
    1. 11.1. Configuration
    2. 11.2. CLI
  14. 12. Appendix
    1. 12.1. Built-in Application Index
  15. UCloud/IM for Kubernetes
  16. 13. Installation
  17. 14. Architecture and Networking
  18. 15. Filesystem Integration
  19. 16. Compute Jobs
    1. 16.1. Public Links
    2. 16.2. Public IPs
    3. 16.3. License Servers
    4. 16.4. SSH Servers
    5. 16.5. Job Audit Log
    6. 16.6. Virtual machines
  20. 17. Integrated applications
    1. 17.1. Syncthing
    2. 17.2. Integrated terminal
  21. 18. UCX applications
    1. 18.1. Hello world
    2. 18.2. Data binding
    3. 18.3. UI events
    4. 18.4. Component reference
    5. 18.5. API reference
  22. 19. Reference
    1. 19.1. Configuration
    2. 19.2. CLI
  23. Branding for UCloud
  24. 20. Branding and identity for UCloud
  25. H: Procedures
  26. 21. H: Procedures
  27. 22. H: Introduction
  28. 23. H: Auditing
  29. 24. H: Auditing scenario
  30. 25. H: GitHub actions
  31. 26. H: Deployment
  32. 27. H: 3rd party dependencies (risk assesment)
  1. Links
  2. Source Code
  3. Releases

UI events

UCX has two interaction channels:

  • Model input (OpModelInput) for bound field changes.
  • UI events (OpUiEvent) for component events such as button clicks and form submit.

Registering handlers

Attach handlers directly on nodes with .On(...):

ucx.Button("submit", "Submit", ucx.ColorPrimaryMain).
    On(ucx.UiEventClick, func(ev ucx.UiEvent) {
        app.Errors = validateState(app)
        if len(app.Errors) == 0 {
            app.SubmissionMessage = "Submission accepted"
        }
    })

Event types include:

  • ucx.UiEventClick
  • ucx.UiEventSubmit
  • ucx.UiEventChange
  • ucx.UiEventFocus
  • ucx.UiEventBlur

Reading event payloads

Event values are ucx.Value. Convert with helpers like ucx.ValueAsString(...):

ucx.ButtonEx("remove", "Remove", ucx.ColorErrorMain, ucx.IconHeroTrash, "", "./id").
    On(ucx.UiEventClick, func(ev ucx.UiEvent) {
        id := strings.TrimSpace(ucx.ValueAsString(ev.Value))
        if id == "" {
            return
        }
        removeTodoById(id)
    })

Updating model vs updating UI

In most handlers you only mutate state fields. UCX then sends a model patch automatically.

Use ucx.AppUpdateUi(app) only when the UI tree itself changed (for example component structure changes).

Common examples where AppUpdateUi(...) is needed:

  • switching between pages rendered via ucx.Router(...) + ucx.Link(...),
  • conditionally adding/removing sections,
  • changing the set of action buttons in a toolbar.

Concurrency and blocking handlers

Default .On(...) handlers are non-blocking and run in a goroutine. For long operations, keep this default and update status fields while work progresses.

If you must run synchronously, use .OnEx(..., ucx.EventHandlerBlocking, ...).

ucx.Button("syncAction", "Run", ucx.ColorWarningMain).
    OnEx(ucx.UiEventClick, ucx.EventHandlerBlocking, func(session *ucx.Session, ev ucx.UiEvent) {
        app.LastActionMessage = "Ran in blocking mode"
    })

For background tasks started outside normal handlers, manually hold app.Mutex() before mutating state and calling ucx.AppUpdateModel(app).

Previous Data binding
Next Component reference