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...");
};
<GoabButton onClick={() => setOpen(true)}>Open</GoabButton>
<GoabModal
  heading="Are you sure you want to change route?"
  open={open}
  onClose={() => setOpen(false)}
  actions={
    <GoabButtonGroup alignment="end">
      <GoabButton type="secondary" size="compact" onClick={() => setOpen(false)}>
        Cancel
      </GoabButton>
      <GoabButton type="primary" size="compact" onClick={handleChangeRoute}>
        Change route
      </GoabButton>
    </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);
}
<goab-button (onClick)="onOpen()">Open</goab-button>
<goab-modal
  [open]="open"
  heading="Are you sure you want to change route?"
  [actions]="actions"
>
  <ng-template #actions>
    <goab-button-group alignment="end">
      <goab-button type="secondary" size="compact" (onClick)="onClose()"
        >Cancel</goab-button
      >
      <goab-button type="primary" size="compact" (onClick)="onChangeRoute()"
        >Change route</goab-button
      >
    </goab-button-group>
  </ng-template>
</goab-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
View old example docs