Skip to content

Alert ​

An alert is a dialog that shows a message, or asks for a choice, on top of the app. The user has to answer it before going back to the app.

IonAlert is the declarative component. IonAlertController creates the same alert from code. See Overlays for where overlays render, what has to be in place, and how dismiss results work.

Basic usage ​

Header, SubHeader, and Message fill the alert. All three are plain text. Buttons takes a list of IonAlertButton; IonAlertButton.FromText("OK") builds a button from its label. Bind IsOpen with @bind-IsOpen. Without the binding the alert still closes after a button tap, but the parent keeps passing true, so it opens again the next time the parent re-renders.

razor
<IonButton OnClick="@(() => _isOpen = true)">Show alert</IonButton>

<IonAlert @bind-IsOpen="_isOpen"
          Header="Update available"
          SubHeader="Version 2.4"
          Message="Restart the app to finish installing the update."
          Buttons="@_buttons" />

@code {
    private bool _isOpen;

    // FromText builds a plain button; the role is "cancel" only for the text "Cancel".
    private readonly IReadOnlyList<IonAlertButton> _buttons = [IonAlertButton.FromText("OK")];
}

Buttons ​

Any button closes the alert. OnDidDismiss reports the tapped button's Role, or "backdrop" when the user tapped outside the alert. A button's optional Handler runs before the alert closes; it cannot keep the alert open. With one or two buttons they sit in a row; with three or more, they stack vertically. The system back button closes it with role "back". BackdropDismiss="false" leaves only the buttons to close it, so the back button then passes through.

razor
<IonButton OnClick="@(() => _isOpen = true)">Sign out</IonButton>
<p>@_status</p>

<IonAlert @bind-IsOpen="_isOpen"
          Header="Sign out?"
          Message="You will need to sign in again to sync your notes."
          Buttons="@_buttons"
          OnDidDismiss="OnDismissed" />

@code {
    private bool _isOpen;
    private string _status = "Signed in";

    private readonly IReadOnlyList<IonAlertButton> _buttons =
    [
        new() { Text = "Cancel", Role = "cancel" },
        new() { Text = "Sign out", Role = "confirm" },
    ];

    // Role is the tapped button's role, or "backdrop" when the user tapped outside.
    private void OnDismissed(IonOverlayDismissEventArgs e)
    {
        if (e.Role == "confirm")
            _status = "Signed out";
    }
}

Radio inputs ​

Inputs adds a group of IonAlertInputs. All inputs of one alert must be the same kind, because the alert renders the group matching the first input's Type. With Type = "radio", tapping a row selects it. On dismiss, Data is the checked input's Value, or null when none is checked.

razor
<IonButton OnClick="@(() => _isOpen = true)">Theme: @_theme</IonButton>

<IonAlert @bind-IsOpen="_isOpen"
          Header="Theme"
          Inputs="@_inputs"
          Buttons="@_buttons"
          OnDidDismiss="OnDismissed" />

@code {
    private bool _isOpen;
    private string _theme = "system";

    // Tapping a radio checks it and unchecks the others (it updates these objects' Checked).
    private readonly IReadOnlyList<IonAlertInput> _inputs =
    [
        new() { Type = "radio", Label = "Light", Value = "light" },
        new() { Type = "radio", Label = "Dark", Value = "dark" },
        new() { Type = "radio", Label = "System", Value = "system", Checked = true },
    ];

    private readonly IReadOnlyList<IonAlertButton> _buttons =
    [
        new() { Text = "Cancel", Role = "cancel" },
        new() { Text = "OK", Role = "confirm" },
    ];

    // For radio inputs Data is the checked input's Value.
    private void OnDismissed(IonOverlayDismissEventArgs e)
    {
        if (e.Role == "confirm" && e.Data is string theme)
            _theme = theme;
    }
}

Tapping a row changes Checked on your IonAlertInput objects, and the alert reports Data on every dismiss, including Cancel and backdrop taps. Check the role before applying it. Also note that a choice made before Cancel stays checked the next time the same list is shown.

Checkbox inputs ​

With Type = "checkbox", each row toggles on its own. Data is a List<string?> of the checked inputs' Values.

razor
<IonButton OnClick="@(() => _isOpen = true)">Toppings (@_toppings.Count)</IonButton>

<IonAlert @bind-IsOpen="_isOpen"
          Header="Toppings"
          Inputs="@_inputs"
          Buttons="@_buttons"
          OnDidDismiss="OnDismissed" />

@code {
    private bool _isOpen;
    private List<string?> _toppings = ["cheese"];

    private readonly IReadOnlyList<IonAlertInput> _inputs =
    [
        new() { Type = "checkbox", Label = "Cheese", Value = "cheese", Checked = true },
        new() { Type = "checkbox", Label = "Mushrooms", Value = "mushrooms" },
        new() { Type = "checkbox", Label = "Olives", Value = "olives" },
    ];

    private readonly IReadOnlyList<IonAlertButton> _buttons =
    [
        new() { Text = "Cancel", Role = "cancel" },
        new() { Text = "OK", Role = "confirm" },
    ];

    // For checkbox inputs Data is a List<string?> of the checked inputs' Values.
    private void OnDismissed(IonOverlayDismissEventArgs e)
    {
        if (e.Role == "confirm" && e.Data is List<string?> values)
            _toppings = values;
    }
}

Text inputs ​

Any other Type ("text", "number", "password", "email", "tel", …) renders one text field per input, with Placeholder and an initial Value, and "textarea" a multi-line field. The alert writes the typed text back to each input's Value, and Data is the list of those values in input order (Ionic returns an object keyed by name). A Disabled text field is dimmed and cannot be focused or edited; CssClass is added to the field.

Using the controller ​

IonAlertController.CreateAsync takes an IonAlertOptions with the same header, message, buttons, inputs, and BackdropDismiss settings. OnDidDismissAsync() completes with the same role and data as OnDidDismiss.

razor
@inject IonAlertController AlertController

<IonButton Color="danger" OnClick="DeleteAsync">Delete account</IonButton>

@code {
    private async Task DeleteAsync()
    {
        var alert = await AlertController.CreateAsync(new IonAlertOptions
        {
            Header = "Delete account?",
            Message = "This cannot be undone.",
            BackdropDismiss = false, // only the buttons close it
            Buttons =
            [
                new() { Text = "Cancel", Role = "cancel" },
                new() { Text = "Delete", Role = "destructive" },
            ],
        });
        await alert.PresentAsync();

        var result = await alert.OnDidDismissAsync();
        if (result.Role == "destructive")
        {
            // delete the account…
        }
    }
}

API ​

Every component also accepts Class (extra CSS classes), Style (an inline Style object) and Id (the root element's id) — see Conventions.

IonAlert ​

ParameterTypeDefaultDescription
BackdropDismissbooltrueIf true (default), tapping the backdrop dismisses the alert.
ButtonsIReadOnlyList<IonAlertButton>[]The buttons to show. Use IonAlertButton.FromText to build them from bare strings (Ionic buttons={['Action']}).
Headerstring?nullThe alert title.
InputsIReadOnlyList<IonAlertInput>[]Optional inputs (all the same kind: text, radio, or checkbox).
IsOpenboolfalseWhether the alert is presented. Bind two-way with IsOpenChanged. Two-way bindable: @bind-IsOpen.
Messagestring?nullThe body message.
OverlayIdstring?nullOptional stable identifier used by the root overlay registry.
SubHeaderstring?nullThe secondary title under the header.
Triggerstring?nullId of the element that opens the alert when clicked (Ionic trigger), e.g. <IonButton Id="open-alert">. Opening sets IsOpen and raises IsOpenChanged. The page must be inside an IonApp.
EventTypeDescription
IsOpenChangedEventCallback<bool>Raised with the new open state when the alert opens/closes.
OnDidDismissEventCallback<IonOverlayDismissEventArgs>Raised when the alert dismisses, with the tapped button's role (or "backdrop").

Types ​

IonAlertButton ​

A single alert button. Mirrors Ionic's AlertButton interface. A string button (e.g. ['Action']) is normalized to a button whose Text is that string and whose Role is "cancel" only when the text is "cancel" (case-insensitive) — see FromText. Role is stamped as alert-button-role-{role}.

PropertyTypeDefaultDescription
Textstring?nullThe button label.
Rolestring?nullOptional role: "cancel", "destructive", or a custom string.
CssClassstring?nullExtra CSS class(es) to add to the button.
HandlerAction?nullOptional handler run when the button is tapped (cancel buttons included), before the alert dismisses. It cannot keep the alert open.
IsCancelboolfalseTrue when Role is "cancel" (case-insensitive). (read-only)
MethodReturnsDescription
FromText(string text)IonAlertButtonBuilds a button from a bare string, as Ionic's alert does for string buttons: the text becomes the label, and the role is "cancel" only when the text is "cancel" (case-insensitive).

IonAlertInput ​

A single alert input. Mirrors Ionic's AlertInput interface. Inputs of one alert must all be the same kind (all text/textarea-style, all radio, or all checkbox) — the alert renders the group matching the first input's Type.

PropertyTypeDefaultDescription
Typestring"text"Input type: "radio", "checkbox", or a text-field type such as "text" (default), "number", "password", "email", "tel", or "textarea" for a multi-line field.
Namestring?nullForm field name (Ionic name). Not used by this port.
Placeholderstring?nullPlaceholder text for text-style inputs.
Valuestring?nullThe input value, reported in the dismiss Data. For a text field it starts as the initial text and follows what the user types (as in Ionic, the alert writes it back).
Labelstring?nullLabel shown beside a radio/checkbox.
CheckedboolfalseWhether a radio/checkbox is checked. The alert updates it when a row is tapped.
DisabledboolfalseWhen true, a radio/checkbox row ignores taps and a text field cannot be focused or edited; both are dimmed.
CssClassstring?nullExtra CSS class(es) (Ionic cssClass), added to the input element or the radio/checkbox button.
IsRadioboolfalseTrue for a radio input. (read-only)
IsCheckboxboolfalseTrue for checkbox inputs. (read-only)
IsTextareaboolfalseTrue for a textarea input. (read-only)

IonAlertOptions ​

Options for IonAlertController.CreateAsync. Each property maps to the IonAlert parameter of the same name.

PropertyTypeDefaultDescription
Headerstring?nullThe alert title.
SubHeaderstring?nullThe secondary title under the header.
Messagestring?nullThe body message.
ButtonsIReadOnlyList<IonAlertButton>[]The buttons to show.
InputsIReadOnlyList<IonAlertInput>[]Optional inputs, all of the same kind.
BackdropDismissbooltrueIf true (default), tapping the backdrop dismisses the alert.
CssClassstring?nullExtra CSS class(es) for the alert host (its Class).

IonAlertController ​

Creates alerts from code (Ionic's alertController). Inject it; AddIonic() registers it.

MethodReturnsDescription
CreateAsync(IonAlertOptions options)Task<IonOverlayReference>Creates an alert from options. Call IonOverlayReference.PresentAsync on the result to show it.

Styling ​

Theme tokens ​

Theme token IonicTheme.Alert (AlertToken). Assign only the values you want to change — the rest keep the mode defaults below. App-wide: builder.AddIonic(o => o.Theme.Alert = new AlertToken { … }); for one subtree: a ConfigProvider. See Theming.

TokenTypemdios
BackdropColorColor#000000#000000
BackdropOpacityfloat0.320.4
BackgroundColor#ffffff#f9f9f9
BorderRadiusfloat413
BoxShadowList<BoxShadow>0 11px 15px -7px rgba(0, 0, 0, 0.2), 0 24px 38px 3px rgba(0, 0, 0, 0.14), 0 9px 46px 8px rgba(0, 0, 0, 0.12)none
ButtonBorderRadiusfloat20
ButtonColorColor#0054e9#0054e9
ButtonFontSizefloat1417
ButtonFontWeightFontWeightFontWeight.MediumFontWeight.Normal
ButtonGroupFlexWrapFlexWrapFlexWrap.WrapReverseFlexWrap.Wrap
ButtonGroupJustifyJustifyContentJustifyContent.FlexEndJustifyContent.Center
ButtonGroupPaddingfloat80
ButtonMarginXfloat80
ButtonPaddingfloat108
ButtonTextTransformTextTransformTextTransform.UppercaseTextTransform.None
ControlAccentColor#0054e9#0054e9
ControlBorderColorOffColor#737373#bfbfbf
HeadPaddingXfloat2316
HeadPaddingYfloat2012
HeadTextAlignTextAlignTextAlign.LeftTextAlign.Center
ListBorderColorColor#d9d9d9rgba(0, 0, 0, 0.2)
MaxWidthfloat280270
MessageColorColor#737373#000000
MessageFontSizefloat1613
MessagePaddingXfloat2416
MessagePaddingYfloat2012
MinWidthfloat250250
SubTitleColorColor#000000#666666
SubTitleFontSizefloat1614
TappableHeightfloat4844
TitleColorColor#000000#000000
TitleFontSizefloat2017
TitleFontWeightFontWeightFontWeight.MediumFontWeight.SemiBold

IonicTheme.Alert.BackdropColor also colors the backdrop of IonModal and IonPopover.

CSS classes ​

App stylesheet rules always win over Ionic's own rules (see Theming), so these classes can be targeted directly from GlobalStyles.cs.

SelectorElement
.ion-alertThe full-screen host that centers the alert. Also carries the mode (md / ios); .overlay-hidden while closed.
.alert-backdropThe dim layer behind the alert (also .ion-backdrop).
.alert-wrapperThe alert card.
.alert-head, .alert-title, .alert-sub-titleThe header block, Header, and SubHeader.
.alert-messageMessage.
.alert-button-groupThe button row; .alert-button-group-vertical with three or more buttons.
.alert-button, .alert-button-innerOne button and its label.
.alert-button-role-{role}A button's Role, e.g. .alert-button-role-cancel.
.alert-radio-group, .alert-checkbox-group, .alert-input-groupThe inputs group, by input kind.
.alert-radio-button, .alert-checkbox-buttonOne radio / checkbox row (also .alert-tappable); -checked / -disabled variants, e.g. .alert-radio-button-checked.
.alert-radio-icon, .alert-radio-label, .alert-checkbox-icon, .alert-checkbox-labelThe parts of a radio / checkbox row.
.alert-inputA text field; .alert-input-disabled when Disabled.

A button's CssClass and the alert's Class (or IonAlertOptions.CssClass) add your own classes:

csharp
// GlobalStyles.cs — new IonAlertButton { Text = "Delete", CssClass = "alert-danger" }
[".ion-alert .alert-button.alert-danger"] = new()
{
    Color = Color.FromHex("#c5000f"),
},

Released under the MIT License.