Back to all examples

Confirm before navigating away

const [open, setOpen] = useState(false);

  const handleChangeRoute = () => {
    setOpen(false);
    // In a real app, you would use your router's navigate function
    // setTimeout(() => navigate("/some-path"), 300);
    console.log("Navigating to new route...");
  };
<GoabxButton onClick={() => setOpen(true)}>Open</GoabxButton>
      <GoabxModal
        heading="Are you sure you want to change route?"
        open={open}
        onClose={() => setOpen(false)}
        actions={
          <GoabButtonGroup alignment="end">
            <GoabxButton type="secondary" size="compact" onClick={() => setOpen(false)}>
              Cancel
            </GoabxButton>
            <GoabxButton type="primary" size="compact" onClick={handleChangeRoute}>
              Change route
            </GoabxButton>
          </GoabButtonGroup>
        }
      />
open = false;

  constructor(private router: Router) {}

  onOpen(): void {
    this.open = true;
  }

  onClose(): void {
    this.open = false;
  }

  onChangeRoute(): void {
    this.open = false;
    // setTimeout will allow any modal transitions to be run
    setTimeout(() => this.router.navigate(["/components"]), 0);
  }
<goabx-button (onClick)="onOpen()">Open</goabx-button>
<goabx-modal [open]="open" heading="Are you sure you want to change route?" [actions]="actions">
  <ng-template #actions>
    <goab-button-group alignment="end">
      <goabx-button type="secondary" size="compact" (onClick)="onClose()">Cancel</goabx-button>
      <goabx-button type="primary" size="compact" (onClick)="onChangeRoute()">Change route</goabx-button>
    </goab-button-group>
  </ng-template>
</goabx-modal>
const modal = document.getElementById('route-modal');
const openBtn = document.getElementById('open-btn');
const cancelBtn = document.getElementById('cancel-btn');
const changeRouteBtn = document.getElementById('change-route-btn');

openBtn.addEventListener('_click', () => {
  modal.setAttribute('open', 'true');
});

cancelBtn.addEventListener('_click', () => {
  modal.removeAttribute('open');
});

changeRouteBtn.addEventListener('_click', () => {
  modal.removeAttribute('open');
  // setTimeout will allow any modal transitions to be run
  setTimeout(() => {
    window.location.href = '/components';
  }, 300);
});

modal.addEventListener('_close', () => {
  modal.removeAttribute('open');
});
<goa-button version="2" id="open-btn">Open</goa-button>
<goa-modal version="2" id="route-modal" heading="Are you sure you want to change route?">
  <div slot="actions">
    <goa-button-group alignment="end">
      <goa-button version="2" type="secondary" size="compact" id="cancel-btn">Cancel</goa-button>
      <goa-button version="2" type="primary" size="compact" id="change-route-btn">Change route</goa-button>
    </goa-button-group>
  </div>
</goa-modal>

Prompt the user in a modal before navigating to a new route to preserve context.

When to use

Use this pattern when:

  • The user has unsaved changes that would be lost
  • Navigation would interrupt an important workflow
  • You need to confirm the user’s intent to leave the page
  • Context or data would be lost on navigation

Considerations

  • Allow users to cancel and stay on the current page
  • Use setTimeout for route changes after modal closes for smooth transitions
  • The secondary button should cancel the navigation
  • The primary button confirms the route change