Mutually exclusive
Overview
When to use this component
The mutually exclusive component provides the user a way to give an opposing answer to the options provided and say none of the other options apply to them.
How to use this component
Inputs, radios, checkboxes, date inputs, and textareas all call this macro automatically when the mutuallyExclusive
parameter is set. This adds the mutually exclusive checkbox, the required aria-live alert markup and the classes required for the JavaScript to run.
Variants
Checkboxes
Example Mutually Exclusive Checkboxes contents
Nunjucks
{% from "components/checkboxes/_macro.njk" import onsCheckboxes %}
{% from "components/question/_macro.njk" import onsQuestion %}
{%
call onsQuestion({
"title": "What type of central heating do you have?",
"legendIsQuestionTitle": true
})
%}
{{
onsCheckboxes({
"id": "central-heating-answers",
"dontWrap": true,
"checkboxesLabel": "Select all that apply",
"name": "mutually-exclusive",
"checkboxes": [
{
"id": "gas-example-mutually-exclusive-checkbox",
"label": {
"text": "Gas"
},
"value": "gas"
},
{
"id": "electric-example-mutually-exclusive-checkbox",
"label": {
"text": "Electric"
},
"value": "electric"
},
{
"id": "solid-fuel-example-mutually-exclusive-checkbox",
"label": {
"text": "Solid fuel"
},
"value": "solid-fuel"
},
{
"id": "other-fuel-example-mutually-exclusive-checkbox",
"label": {
"text": "Other"
},
"value": "other",
"other": {
"id": "other-fuel-textbox-example-mutually-exclusive-checkbox",
"name": "other-fuel-answer",
"label": {
"text": "Please specify"
}
}
}
],
"mutuallyExclusive": {
"or": "Or",
"deselectMessage": "Selecting this will uncheck all other checkboxes",
"deselectGroupAdjective": "deselected",
"deselectExclusiveOptionAdjective": "deselected",
"exclusiveOptions": [
{
"id": "no-central-heating-example-mutually-exclusive-checkbox",
"label": {
"text": "No central heating"
},
"attributes": {
"data-attribute": "Example attribute"
},
"value": "no-central-heating"
}
]
}
})
}}
{% endcall %}
Nunjucks macro options
Name | Type | Required | Description |
---|---|---|---|
id | string | false | The HTML id of the fieldset |
classes | string | false | Classes to apply to the fieldset |
legend | string | true (unless legendIsQuestionTitle is set) | Text for the fieldset’s legend |
legendClasses | string | false | Classes to apply to the legend element |
legendIsQuestionTitle | boolean | true (unless legend is set) | Creates an h1 inside the legend . Use when there is only a single fieldset on the page |
description | string | false | Description for the fieldset |
attributes | object | false | HTML attributes (for example, data attributes) to add to the fieldset |
exclusiveOptions | Array<Checkbox> or Array<radio> | true | Configuration for the mutually exclusive options |
or | string | false | Text for the “Or” label that separates the mutually exclusive checkbox from the answer options, defaults to "Or". |
deselectMessage | string | true | The text the aria-live alert will announce to warn that selecting the exclusive checkbox will clear or unselect all other answer options. For example, ”Selecting this will uncheck all other checkboxes”. |
deselectGroupAdjective | string | true | The text the aria-live alert will announce when an answer option is cleared or unselected when the mutually exclusive checkbox is selected |
deselectExclusiveOptionAdjective | string | true | The text the aria-live alert will announce when an option is cleared or unselected when the mutually exclusive checkbox is selected |
error | Error (ref) | false | Configuration for validation errors |
dontWrap | boolean | false | Prevents fields,checkboxes,date input,duration,input and Textarea from being wrapped in a fieldset component |
autosuggestresults | string | false | Shows suggested options to users as they enter something into an input field |
HTML
<div class="ons-question ons-u-mb-xl">
<div class="ons-question__answer ons-u-mb-l">
<fieldset class="ons-fieldset">
<legend class="ons-fieldset__legend ons-u-mb-no">
<h1 id="fieldset-legend-title" class="ons-fieldset__legend-title">What type of central heating do you have?</h1>
</legend>
<div class="ons-input-items">
<div class="ons-js-mutually-exclusive ons-mutually-exclusive">
<p class="ons-checkboxes__label"> Select all that apply </p>
<div class="ons-checkboxes__items">
<span class="ons-checkboxes__item">
<span class="ons-checkbox">
<input type="checkbox" id="gas-example-mutually-exclusive-checkbox"
class="ons-checkbox__input ons-js-checkbox ons-js-exclusive-group-item" value="gas" />
<label class=" ons-checkbox__label" for="gas-example-mutually-exclusive-checkbox"
id="gas-example-mutually-exclusive-checkbox-label">Gas</label>
</span>
</span>
<br />
<span class="ons-checkboxes__item">
<span class="ons-checkbox">
<input type="checkbox" id="electric-example-mutually-exclusive-checkbox"
class="ons-checkbox__input ons-js-checkbox ons-js-exclusive-group-item" value="electric" />
<label class=" ons-checkbox__label" for="electric-example-mutually-exclusive-checkbox"
id="electric-example-mutually-exclusive-checkbox-label">Electric</label>
</span>
</span>
<br />
<span class="ons-checkboxes__item">
<span class="ons-checkbox">
<input type="checkbox" id="solid-fuel-example-mutually-exclusive-checkbox"
class="ons-checkbox__input ons-js-checkbox ons-js-exclusive-group-item" value="solid-fuel" />
<label class=" ons-checkbox__label" for="solid-fuel-example-mutually-exclusive-checkbox"
id="solid-fuel-example-mutually-exclusive-checkbox-label">Solid fuel</label>
</span>
</span>
<br />
<span class="ons-checkboxes__item">
<span class="ons-checkbox">
<input type="checkbox" id="other-fuel-example-mutually-exclusive-checkbox"
class="ons-checkbox__input ons-js-checkbox ons-js-exclusive-group-item ons-js-other" value="other"
aria-controls="other-fuel-example-mutually-exclusive-checkbox-other-wrap" aria-haspopup="true" />
<label class=" ons-checkbox__label" for="other-fuel-example-mutually-exclusive-checkbox"
id="other-fuel-example-mutually-exclusive-checkbox-label">Other</label>
<span class="ons-checkbox__other" id="other-fuel-example-mutually-exclusive-checkbox-other-wrap">
<label class="ons-label ons-u-fw-n" for="other-fuel-textbox-example-mutually-exclusive-checkbox"
id="other-fuel-textbox-example-mutually-exclusive-checkbox-label">Please specify</label>
<input type="text" id="other-fuel-textbox-example-mutually-exclusive-checkbox"
class="ons-input ons-input--text ons-input-type__input ons-js-exclusive-group-item ons-input--w-auto"
name="other-fuel-answer" />
</span>
</span>
</span>
</div>
<p class="ons-checkboxes--mutually-exclusive__item ons-u-mt-s">
<span class="ons-checkboxes__label ons-u-fs-r--b" aria-hidden="true">Or</span>
<span class="ons-checkbox">
<input type="checkbox" id="no-central-heating-example-mutually-exclusive-checkbox"
class="ons-checkbox__input ons-js-checkbox ons-js-exclusive-option" value="no-central-heating"
data-attribute="Example attribute"
data-deselect-message="Selecting this will uncheck all other checkboxes" />
<label class=" ons-checkbox__label" for="no-central-heating-example-mutually-exclusive-checkbox"
id="no-central-heating-example-mutually-exclusive-checkbox-label"><span class="ons-u-vh">Or, </span> No
central heating</label>
</span>
</p>
<span class="ons-js-exclusive-alert ons-u-vh" role="alert" aria-live="polite"
data-group-adjective="deselected" data-option-adjective="deselected"></span>
</div>
</div>
</fieldset>
</div>
</div>
Date
Example Mutually Exclusive Date contents
Nunjucks
{% from "components/date-input/_macro.njk" import onsDateInput %}
{% from "components/question/_macro.njk" import onsQuestion %}
{%
call onsQuestion({
"title": "When did you leave your last paid job?",
"description": "<p>For example, 31 3 2018</p>",
"legendIsQuestionTitle": true
})
%}
{{
onsDateInput({
"id": "date-mutually-exclusive",
"dontWrap": true,
"day": {
"label": {
"text": "Day"
},
"name": "day-exclusive"
},
"month": {
"label": {
"text": "Month"
},
"name": "month-exclusive"
},
"year": {
"label": {
"text": "Year"
},
"name": "year-exclusive"
},
"mutuallyExclusive": {
"or": "Or",
"deselectMessage": "Selecting this will clear the date if one has been inputted",
"deselectGroupAdjective": "cleared",
"deselectExclusiveOptionAdjective": "deselected",
"exclusiveOptions": [
{
"id": "date-exclusive-checkbox",
"name": "no-paid-job",
"value": "no-paid-job",
"label": {
"text": "I have never had a paid job"
}
}
]
}
})
}}
{% endcall %}
Nunjucks macro options
Name | Type | Required | Description |
---|---|---|---|
id | string | false | The HTML id of the fieldset |
classes | string | false | Classes to apply to the fieldset |
legend | string | true (unless legendIsQuestionTitle is set) | Text for the fieldset’s legend |
legendClasses | string | false | Classes to apply to the legend element |
legendIsQuestionTitle | boolean | true (unless legend is set) | Creates an h1 inside the legend . Use when there is only a single fieldset on the page |
description | string | false | Description for the fieldset |
attributes | object | false | HTML attributes (for example, data attributes) to add to the fieldset |
exclusiveOptions | Array<Checkbox> or Array<radio> | true | Configuration for the mutually exclusive options |
or | string | false | Text for the “Or” label that separates the mutually exclusive checkbox from the answer options, defaults to "Or". |
deselectMessage | string | true | The text the aria-live alert will announce to warn that selecting the exclusive checkbox will clear or unselect all other answer options. For example, ”Selecting this will uncheck all other checkboxes”. |
deselectGroupAdjective | string | true | The text the aria-live alert will announce when an answer option is cleared or unselected when the mutually exclusive checkbox is selected |
deselectExclusiveOptionAdjective | string | true | The text the aria-live alert will announce when an option is cleared or unselected when the mutually exclusive checkbox is selected |
error | Error (ref) | false | Configuration for validation errors |
dontWrap | boolean | false | Prevents fields,checkboxes,date input,duration,input and Textarea from being wrapped in a fieldset component |
autosuggestresults | string | false | Shows suggested options to users as they enter something into an input field |
HTML
<div class="ons-question ons-u-mb-xl">
<div class="ons-question__answer ons-u-mb-l">
<fieldset class="ons-fieldset">
<legend aria-describedBy="legend-description"
class="ons-fieldset__legend ons-u-mb-no ons-fieldset__legend--with-description">
<h1 id="fieldset-legend-title" class="ons-fieldset__legend-title">When did you leave your last paid job?</h1>
</legend>
<div id="legend-description" class="ons-fieldset__description ons-fieldset__description--title ons-u-mb-l">
<p>For example, 31 3 2018</p>
</div>
<div class="ons-input-items">
<div class="ons-js-mutually-exclusive ons-mutually-exclusive">
<div class="ons-field-group">
<div class="ons-field">
<label class="ons-label" for="date-mutually-exclusive-day"
id="date-mutually-exclusive-day-label">Day</label>
<input type="text" id="date-mutually-exclusive-day"
class="ons-input ons-input--text ons-input-type__input ons-js-exclusive-group-item ons-input-number--w-2"
name="day-exclusive" maxlength="2" pattern="[0-9]*" inputmode="numeric" />
</div>
<div class="ons-field">
<label class="ons-label" for="date-mutually-exclusive-month"
id="date-mutually-exclusive-month-label">Month</label>
<input type="text" id="date-mutually-exclusive-month"
class="ons-input ons-input--text ons-input-type__input ons-js-exclusive-group-item ons-input-number--w-2"
name="month-exclusive" maxlength="2" pattern="[0-9]*" inputmode="numeric" />
</div>
<div class="ons-field">
<label class="ons-label" for="date-mutually-exclusive-year"
id="date-mutually-exclusive-year-label">Year</label>
<input type="text" id="date-mutually-exclusive-year"
class="ons-input ons-input--text ons-input-type__input ons-js-exclusive-group-item ons-input-number--w-4"
name="year-exclusive" maxlength="4" pattern="[0-9]*" inputmode="numeric" />
</div>
</div>
<p class="ons-checkboxes--mutually-exclusive__item ons-u-mt-s">
<span class="ons-checkboxes__label ons-u-fs-r--b" aria-hidden="true">Or</span>
<span class="ons-checkbox">
<input type="checkbox" id="date-exclusive-checkbox"
class="ons-checkbox__input ons-js-checkbox ons-js-exclusive-option" value="no-paid-job"
name="no-paid-job"
data-deselect-message="Selecting this will clear the date if one has been inputted" />
<label class=" ons-checkbox__label" for="date-exclusive-checkbox" id="date-exclusive-checkbox-label"><span
class="ons-u-vh">Or, </span> I have never had a paid job</label>
</span>
</p>
<span class="ons-js-exclusive-alert ons-u-vh" role="alert" aria-live="polite" data-group-adjective="cleared"
data-option-adjective="deselected"></span>
</div>
</div>
</fieldset>
</div>
</div>
Textarea
Example Mutually Exclusive Textarea contents
Nunjucks
{% from "components/textarea/_macro.njk" import onsTextarea %}
{% from "components/question/_macro.njk" import onsQuestion %}
{%
call onsQuestion({
"title": "What do you think of this service?",
"legendIsQuestionTitle": true
})
%}
{{
onsTextarea({
"id": "feedback",
"name": "feedback",
"dontWrap": true,
"width": "30",
"label": {
"text": "Enter your feedback"
},
"charCheckLimit": {
"limit": 200,
"charCountSingular": "You have {x} character remaining",
"charCountPlural": "You have {x} characters remaining"
},
"mutuallyExclusive": {
"or": "Or",
"deselectMessage": "Selecting this will clear your feedback",
"deselectGroupAdjective": "cleared",
"deselectExclusiveOptionAdjective": "deselected",
"exclusiveOptions": [
{
"id": "feedback-checkbox",
"name": "no-feedback",
"value": "no-feedback",
"label": {
"text": "I don’t want to provide feedback"
}
}
]
}
})
}}
{% endcall %}
Nunjucks macro options
Name | Type | Required | Description |
---|---|---|---|
id | string | false | The HTML id of the fieldset |
classes | string | false | Classes to apply to the fieldset |
legend | string | true (unless legendIsQuestionTitle is set) | Text for the fieldset’s legend |
legendClasses | string | false | Classes to apply to the legend element |
legendIsQuestionTitle | boolean | true (unless legend is set) | Creates an h1 inside the legend . Use when there is only a single fieldset on the page |
description | string | false | Description for the fieldset |
attributes | object | false | HTML attributes (for example, data attributes) to add to the fieldset |
exclusiveOptions | Array<Checkbox> or Array<radio> | true | Configuration for the mutually exclusive options |
or | string | false | Text for the “Or” label that separates the mutually exclusive checkbox from the answer options, defaults to "Or". |
deselectMessage | string | true | The text the aria-live alert will announce to warn that selecting the exclusive checkbox will clear or unselect all other answer options. For example, ”Selecting this will uncheck all other checkboxes”. |
deselectGroupAdjective | string | true | The text the aria-live alert will announce when an answer option is cleared or unselected when the mutually exclusive checkbox is selected |
deselectExclusiveOptionAdjective | string | true | The text the aria-live alert will announce when an option is cleared or unselected when the mutually exclusive checkbox is selected |
error | Error (ref) | false | Configuration for validation errors |
dontWrap | boolean | false | Prevents fields,checkboxes,date input,duration,input and Textarea from being wrapped in a fieldset component |
autosuggestresults | string | false | Shows suggested options to users as they enter something into an input field |
HTML
<div class="ons-question ons-u-mb-xl">
<div class="ons-question__answer ons-u-mb-l">
<fieldset class="ons-fieldset">
<legend class="ons-fieldset__legend ons-u-mb-no">
<h1 id="fieldset-legend-title" class="ons-fieldset__legend-title">What do you think of this service?</h1>
</legend>
<div class="ons-input-items">
<div class="ons-js-mutually-exclusive ons-mutually-exclusive">
<label class="ons-label" for="feedback">Enter your feedback</label>
<textarea id="feedback"
class="ons-input ons-input--textarea ons-js-char-limit-input ons-js-exclusive-group-item ons-input--w-30"
name="feedback" rows="8" maxlength="200" data-char-limit-ref="feedback-lim"
aria-describedby="feedback-lim"></textarea>
<span id="feedback-lim" class="ons-input__limit ons-u-fs-s--b ons-u-d-no ons-u-mt-2xs"
data-charcount-singular="You have {x} character remaining"
data-charcount-plural="You have {x} characters remaining" data-charcount-limit-singular=""
data-charcount-limit-plural="">
</span>
<p class="ons-checkboxes--mutually-exclusive__item ons-u-mt-s">
<span class="ons-checkboxes__label ons-u-fs-r--b" aria-hidden="true">Or</span>
<span class="ons-checkbox">
<input type="checkbox" id="feedback-checkbox"
class="ons-checkbox__input ons-js-checkbox ons-js-exclusive-option" value="no-feedback"
name="no-feedback" data-deselect-message="Selecting this will clear your feedback" />
<label class=" ons-checkbox__label" for="feedback-checkbox" id="feedback-checkbox-label"><span
class="ons-u-vh">Or, </span> I don’t want to provide feedback</label>
</span>
</p>
<span class="ons-js-exclusive-alert ons-u-vh" role="alert" aria-live="polite" data-group-adjective="cleared"
data-option-adjective="deselected"></span>
</div>
</div>
</fieldset>
</div>
</div>
Example Mutually Exclusive Email contents
Nunjucks
{% from "components/input/_macro.njk" import onsInput %}
{% from "components/question/_macro.njk" import onsQuestion %}
{%
call onsQuestion({
"title": "Get a confirmation email",
"description": "<p>Enter your email address if you would like to be sent confirmation that you have completed your survey</p>",
"legendIsQuestionTitle": true
})
%}
{{
onsInput({
"id": "email-example-mutually-exclusive",
"type": "email",
"label": {
"text": "Email address",
"description": "This will not be stored and only used once to send your confirmation"
},
"dontWrap": true,
"mutuallyExclusive": {
"or": "Or",
"deselectMessage": "Selecting this will clear your email",
"deselectGroupAdjective": "cleared",
"deselectExclusiveOptionAdjective": "deselected",
"exclusiveOptions": [
{
"id": "email-checkbox-example-mutually-exclusive",
"name": "no-email",
"value": "no-email",
"label": {
"text": "I don’t want to receive a confirmation email"
}
}
]
}
})
}}
{% endcall %}
Nunjucks macro options
Name | Type | Required | Description |
---|---|---|---|
id | string | false | The HTML id of the fieldset |
classes | string | false | Classes to apply to the fieldset |
legend | string | true (unless legendIsQuestionTitle is set) | Text for the fieldset’s legend |
legendClasses | string | false | Classes to apply to the legend element |
legendIsQuestionTitle | boolean | true (unless legend is set) | Creates an h1 inside the legend . Use when there is only a single fieldset on the page |
description | string | false | Description for the fieldset |
attributes | object | false | HTML attributes (for example, data attributes) to add to the fieldset |
exclusiveOptions | Array<Checkbox> or Array<radio> | true | Configuration for the mutually exclusive options |
or | string | false | Text for the “Or” label that separates the mutually exclusive checkbox from the answer options, defaults to "Or". |
deselectMessage | string | true | The text the aria-live alert will announce to warn that selecting the exclusive checkbox will clear or unselect all other answer options. For example, ”Selecting this will uncheck all other checkboxes”. |
deselectGroupAdjective | string | true | The text the aria-live alert will announce when an answer option is cleared or unselected when the mutually exclusive checkbox is selected |
deselectExclusiveOptionAdjective | string | true | The text the aria-live alert will announce when an option is cleared or unselected when the mutually exclusive checkbox is selected |
error | Error (ref) | false | Configuration for validation errors |
dontWrap | boolean | false | Prevents fields,checkboxes,date input,duration,input and Textarea from being wrapped in a fieldset component |
autosuggestresults | string | false | Shows suggested options to users as they enter something into an input field |
HTML
<div class="ons-question ons-u-mb-xl">
<div class="ons-question__answer ons-u-mb-l">
<fieldset class="ons-fieldset">
<legend aria-describedBy="legend-description"
class="ons-fieldset__legend ons-u-mb-no ons-fieldset__legend--with-description">
<h1 id="fieldset-legend-title" class="ons-fieldset__legend-title">Get a confirmation email</h1>
</legend>
<div id="legend-description" class="ons-fieldset__description ons-fieldset__description--title ons-u-mb-l">
<p>Enter your email address if you would like to be sent confirmation that you have completed your survey</p>
</div>
<div class="ons-input-items">
<div class="ons-js-mutually-exclusive ons-mutually-exclusive">
<label class="ons-label ons-label--with-description" for="email-example-mutually-exclusive"
aria-describedby="description-hint">Email address</label>
<span id="description-hint" class="ons-label__description ons-input--with-description">This will not be stored
and only used once to send your confirmation</span>
<input type="email" id="email-example-mutually-exclusive"
class="ons-input ons-input--text ons-input-type__input ons-js-exclusive-group-item"
aria-describedby="description-hint" />
<p class="ons-checkboxes--mutually-exclusive__item ons-u-mt-s">
<span class="ons-checkboxes__label ons-u-fs-r--b" aria-hidden="true">Or</span>
<span class="ons-checkbox">
<input type="checkbox" id="email-checkbox-example-mutually-exclusive"
class="ons-checkbox__input ons-js-checkbox ons-js-exclusive-option" value="no-email" name="no-email"
data-deselect-message="Selecting this will clear your email" />
<label class=" ons-checkbox__label" for="email-checkbox-example-mutually-exclusive"
id="email-checkbox-example-mutually-exclusive-label"><span class="ons-u-vh">Or, </span> I don’t want to
receive a confirmation email</label>
</span>
</p>
<span class="ons-js-exclusive-alert ons-u-vh" role="alert" aria-live="polite" data-group-adjective="cleared"
data-option-adjective="deselected"></span>
</div>
</div>
</fieldset>
</div>
</div>
Number
Example Mutually Exclusive Number contents
Nunjucks
{% from "components/input/_macro.njk" import onsInput %}
{% from "components/question/_macro.njk" import onsQuestion %}
{%
call onsQuestion({
"title": "What was your annual income before tax in 2018/19?",
"legendIsQuestionTitle": true
})
%}
{{
onsInput({
"id": "currency",
"dontWrap": true,
"type": "number",
"width": "4",
"label": {
"text": "Gross annual income"
},
"prefix": {
"title": "British pounds (GBP)",
"text": "£",
"id": "annual-salary-gpb-prefix"
},
"mutuallyExclusive": {
"or": "Or",
"deselectMessage": "Selecting this will clear your inputted annual income",
"deselectGroupAdjective": "cleared",
"deselectExclusiveOptionAdjective": "deselected",
"exclusiveOptions": [
{
"id": "currency-checkbox",
"name": "no-currency",
"value": "no-currency",
"label": {
"text": "I prefer not to say"
}
}
]
}
})
}}
{% endcall %}
Nunjucks macro options
Name | Type | Required | Description |
---|---|---|---|
id | string | false | The HTML id of the fieldset |
classes | string | false | Classes to apply to the fieldset |
legend | string | true (unless legendIsQuestionTitle is set) | Text for the fieldset’s legend |
legendClasses | string | false | Classes to apply to the legend element |
legendIsQuestionTitle | boolean | true (unless legend is set) | Creates an h1 inside the legend . Use when there is only a single fieldset on the page |
description | string | false | Description for the fieldset |
attributes | object | false | HTML attributes (for example, data attributes) to add to the fieldset |
exclusiveOptions | Array<Checkbox> or Array<radio> | true | Configuration for the mutually exclusive options |
or | string | false | Text for the “Or” label that separates the mutually exclusive checkbox from the answer options, defaults to "Or". |
deselectMessage | string | true | The text the aria-live alert will announce to warn that selecting the exclusive checkbox will clear or unselect all other answer options. For example, ”Selecting this will uncheck all other checkboxes”. |
deselectGroupAdjective | string | true | The text the aria-live alert will announce when an answer option is cleared or unselected when the mutually exclusive checkbox is selected |
deselectExclusiveOptionAdjective | string | true | The text the aria-live alert will announce when an option is cleared or unselected when the mutually exclusive checkbox is selected |
error | Error (ref) | false | Configuration for validation errors |
dontWrap | boolean | false | Prevents fields,checkboxes,date input,duration,input and Textarea from being wrapped in a fieldset component |
autosuggestresults | string | false | Shows suggested options to users as they enter something into an input field |
HTML
<div class="ons-question ons-u-mb-xl">
<div class="ons-question__answer ons-u-mb-l">
<fieldset class="ons-fieldset">
<legend class="ons-fieldset__legend ons-u-mb-no">
<h1 id="fieldset-legend-title" class="ons-fieldset__legend-title">What was your annual income before tax in
2018/19?</h1>
</legend>
<div class="ons-input-items">
<div class="ons-js-mutually-exclusive ons-mutually-exclusive">
<label class="ons-label" for="currency">Gross annual income</label>
<span class="ons-input-type ons-input-type--prefix ons-js-input-container-abbr">
<span class="ons-input-type__inner">
<input type="text" id="currency"
class="ons-input ons-input--text ons-input-type__input ons-input-number--w-4 ons-js-exclusive-group-item"
aria-labelledby="currency annual-salary-gpb-prefix" pattern="[0-9]*" inputmode="numeric" />
<abbr id="annual-salary-gpb-prefix" class="ons-input-type__type ons-js-input-abbr"
aria-label="British pounds (GBP)" role="figure" title="British pounds (GBP)">£</abbr>
</span>
</span>
<p class="ons-checkboxes--mutually-exclusive__item ons-u-mt-s">
<span class="ons-checkboxes__label ons-u-fs-r--b" aria-hidden="true">Or</span>
<span class="ons-checkbox">
<input type="checkbox" id="currency-checkbox"
class="ons-checkbox__input ons-js-checkbox ons-js-exclusive-option" value="no-currency"
name="no-currency" data-deselect-message="Selecting this will clear your inputted annual income" />
<label class=" ons-checkbox__label" for="currency-checkbox" id="currency-checkbox-label"><span
class="ons-u-vh">Or, </span> I prefer not to say</label>
</span>
</p>
<span class="ons-js-exclusive-alert ons-u-vh" role="alert" aria-live="polite" data-group-adjective="cleared"
data-option-adjective="deselected"></span>
</div>
</div>
</fieldset>
</div>
</div>
Duration
Example Mutually Exclusive Duration contents
Nunjucks
{% from "components/question/_macro.njk" import onsQuestion %}
{% from "components/duration/_macro.njk" import onsDuration %}
{%
call onsQuestion({
"title": "How long have you lived at this address?",
"description": "<p>Enter “0” into the years field if you have lived at this address for less than a year</p>",
"legendIsQuestionTitle": true
})
%}
{{
onsDuration({
"id": "address-duration",
"dontWrap": true,
"field1": {
"id": "address-duration-years",
"name": "address-duration-years",
"suffix": {
"text": "Years",
"id": "address-duration-years-suffix"
}
},
"field2": {
"id": "address-duration-months",
"name": "address-duration-months",
"suffix": {
"text": "Months",
"id": "address-duration-months-suffix"
}
},
"mutuallyExclusive": {
"or": "Or",
"deselectMessage": "Selecting this will clear the date if one has been inputted",
"deselectGroupAdjective": "cleared",
"deselectExclusiveOptionAdjective": "deselected",
"exclusiveOptions": [
{
"id": "duration-exclusive-checkbox",
"name": "no-duration",
"value": "no-duration",
"label": {
"text": "I have not moved in to this address yet"
}
}
]
}
})
}}
{% endcall %}
Nunjucks macro options
Name | Type | Required | Description |
---|---|---|---|
id | string | false | The HTML id of the fieldset |
classes | string | false | Classes to apply to the fieldset |
legend | string | true (unless legendIsQuestionTitle is set) | Text for the fieldset’s legend |
legendClasses | string | false | Classes to apply to the legend element |
legendIsQuestionTitle | boolean | true (unless legend is set) | Creates an h1 inside the legend . Use when there is only a single fieldset on the page |
description | string | false | Description for the fieldset |
attributes | object | false | HTML attributes (for example, data attributes) to add to the fieldset |
exclusiveOptions | Array<Checkbox> or Array<radio> | true | Configuration for the mutually exclusive options |
or | string | false | Text for the “Or” label that separates the mutually exclusive checkbox from the answer options, defaults to "Or". |
deselectMessage | string | true | The text the aria-live alert will announce to warn that selecting the exclusive checkbox will clear or unselect all other answer options. For example, ”Selecting this will uncheck all other checkboxes”. |
deselectGroupAdjective | string | true | The text the aria-live alert will announce when an answer option is cleared or unselected when the mutually exclusive checkbox is selected |
deselectExclusiveOptionAdjective | string | true | The text the aria-live alert will announce when an option is cleared or unselected when the mutually exclusive checkbox is selected |
error | Error (ref) | false | Configuration for validation errors |
dontWrap | boolean | false | Prevents fields,checkboxes,date input,duration,input and Textarea from being wrapped in a fieldset component |
autosuggestresults | string | false | Shows suggested options to users as they enter something into an input field |
HTML
<div class="ons-question ons-u-mb-xl">
<div class="ons-question__answer ons-u-mb-l">
<fieldset class="ons-fieldset">
<legend aria-describedBy="legend-description"
class="ons-fieldset__legend ons-u-mb-no ons-fieldset__legend--with-description">
<h1 id="fieldset-legend-title" class="ons-fieldset__legend-title">How long have you lived at this address?</h1>
</legend>
<div id="legend-description" class="ons-fieldset__description ons-fieldset__description--title ons-u-mb-l">
<p>Enter “0” into the years field if you have lived at this address for less than a year</p>
</div>
<div class="ons-input-items">
<div class="ons-js-mutually-exclusive ons-mutually-exclusive">
<div class="ons-field-group">
<div class="ons-field">
<span class="ons-input-type ons-js-input-container-abbr">
<span class="ons-input-type__inner">
<input type="text" id="address-duration-years"
class="ons-input ons-input--text ons-input-type__input ons-js-exclusive-group-item ons-input-number--w-2"
aria-labelledby="address-duration-years-suffix"
aria-labelledby="address-duration-years address-duration-years-suffix" name="address-duration-years"
pattern="[0-9]*" inputmode="numeric" />
<span id="address-duration-years-suffix" class="ons-input-type__type ons-js-input-abbr" aria-label=""
role="figure">Years</span>
</span>
</span>
</div>
<div class="ons-field">
<span class="ons-input-type ons-js-input-container-abbr">
<span class="ons-input-type__inner">
<input type="text" id="address-duration-months"
class="ons-input ons-input--text ons-input-type__input ons-js-exclusive-group-item ons-input-number--w-2"
aria-labelledby="address-duration-months-suffix"
aria-labelledby="address-duration-months address-duration-months-suffix"
name="address-duration-months" pattern="[0-9]*" inputmode="numeric" />
<span id="address-duration-months-suffix" class="ons-input-type__type ons-js-input-abbr" aria-label=""
role="figure">Months</span>
</span>
</span>
</div>
</div>
<p class="ons-checkboxes--mutually-exclusive__item ons-u-mt-s">
<span class="ons-checkboxes__label ons-u-fs-r--b" aria-hidden="true">Or</span>
<span class="ons-checkbox">
<input type="checkbox" id="duration-exclusive-checkbox"
class="ons-checkbox__input ons-js-checkbox ons-js-exclusive-option" value="no-duration"
name="no-duration"
data-deselect-message="Selecting this will clear the date if one has been inputted" />
<label class=" ons-checkbox__label" for="duration-exclusive-checkbox"
id="duration-exclusive-checkbox-label"><span class="ons-u-vh">Or, </span> I have not moved in to this
address yet</label>
</span>
</p>
<span class="ons-js-exclusive-alert ons-u-vh" role="alert" aria-live="polite" data-group-adjective="cleared"
data-option-adjective="deselected"></span>
</div>
</div>
</fieldset>
</div>
</div>
Multiple mutually exclusive options
When more than one mutually exclusive option is provided the exclusive options become radio buttons.
Example Mutually Exclusive Multiple Options contents
Nunjucks
{% from "components/checkboxes/_macro.njk" import onsCheckboxes %}
{% from "components/question/_macro.njk" import onsQuestion %}
{%
call onsQuestion({
"title": "What type of central heating do you have?",
"legendIsQuestionTitle": true
})
%}
{{
onsCheckboxes({
"id": "central-heating-answers",
"dontWrap": true,
"checkboxesLabel": "Select all that apply",
"name": "mutually-exclusive",
"checkboxes": [
{
"id": "gas-example-mutually-exclusive-multiple-options",
"label": {
"text": "Gas"
},
"value": "gas"
},
{
"id": "electric-example-mutually-exclusive-multiple-options",
"label": {
"text": "Electric"
},
"value": "electric"
},
{
"id": "solid-fuel-example-mutually-exclusive-multiple-options",
"label": {
"text": "Solid fuel"
},
"value": "solid-fuel"
}
],
"mutuallyExclusive": {
"or": "Or",
"deselectMessage": "Selecting these will uncheck all other checkboxes",
"deselectGroupAdjective": "deselected",
"deselectExclusiveOptionAdjective": "deselected",
"exclusiveOptions": [
{
"id": "no-central-heating-example-mutually-exclusive-multiple-options",
"name": "no central heating",
"label": {
"text": "No central heating"
},
"value": "no-central-heating"
},
{
"id": "other-example-mutually-exclusive-multiple-options",
"name": "other",
"label": {
"text": "Other"
},
"value": "other"
}
]
}
})
}}
{% endcall %}
Nunjucks macro options
Name | Type | Required | Description |
---|---|---|---|
id | string | false | The HTML id of the fieldset |
classes | string | false | Classes to apply to the fieldset |
legend | string | true (unless legendIsQuestionTitle is set) | Text for the fieldset’s legend |
legendClasses | string | false | Classes to apply to the legend element |
legendIsQuestionTitle | boolean | true (unless legend is set) | Creates an h1 inside the legend . Use when there is only a single fieldset on the page |
description | string | false | Description for the fieldset |
attributes | object | false | HTML attributes (for example, data attributes) to add to the fieldset |
exclusiveOptions | Array<Checkbox> or Array<radio> | true | Configuration for the mutually exclusive options |
or | string | false | Text for the “Or” label that separates the mutually exclusive checkbox from the answer options, defaults to "Or". |
deselectMessage | string | true | The text the aria-live alert will announce to warn that selecting the exclusive checkbox will clear or unselect all other answer options. For example, ”Selecting this will uncheck all other checkboxes”. |
deselectGroupAdjective | string | true | The text the aria-live alert will announce when an answer option is cleared or unselected when the mutually exclusive checkbox is selected |
deselectExclusiveOptionAdjective | string | true | The text the aria-live alert will announce when an option is cleared or unselected when the mutually exclusive checkbox is selected |
error | Error (ref) | false | Configuration for validation errors |
dontWrap | boolean | false | Prevents fields,checkboxes,date input,duration,input and Textarea from being wrapped in a fieldset component |
autosuggestresults | string | false | Shows suggested options to users as they enter something into an input field |
HTML
<div class="ons-question ons-u-mb-xl">
<div class="ons-question__answer ons-u-mb-l">
<fieldset class="ons-fieldset">
<legend class="ons-fieldset__legend ons-u-mb-no">
<h1 id="fieldset-legend-title" class="ons-fieldset__legend-title">What type of central heating do you have?</h1>
</legend>
<div class="ons-input-items">
<div class="ons-js-mutually-exclusive ons-mutually-exclusive">
<p class="ons-checkboxes__label"> Select all that apply </p>
<div class="ons-checkboxes__items">
<span class="ons-checkboxes__item">
<span class="ons-checkbox">
<input type="checkbox" id="gas-example-mutually-exclusive-multiple-options"
class="ons-checkbox__input ons-js-checkbox ons-js-exclusive-group-item" value="gas" />
<label class=" ons-checkbox__label" for="gas-example-mutually-exclusive-multiple-options"
id="gas-example-mutually-exclusive-multiple-options-label">Gas</label>
</span>
</span>
<br />
<span class="ons-checkboxes__item">
<span class="ons-checkbox">
<input type="checkbox" id="electric-example-mutually-exclusive-multiple-options"
class="ons-checkbox__input ons-js-checkbox ons-js-exclusive-group-item" value="electric" />
<label class=" ons-checkbox__label" for="electric-example-mutually-exclusive-multiple-options"
id="electric-example-mutually-exclusive-multiple-options-label">Electric</label>
</span>
</span>
<br />
<span class="ons-checkboxes__item">
<span class="ons-checkbox">
<input type="checkbox" id="solid-fuel-example-mutually-exclusive-multiple-options"
class="ons-checkbox__input ons-js-checkbox ons-js-exclusive-group-item" value="solid-fuel" />
<label class=" ons-checkbox__label" for="solid-fuel-example-mutually-exclusive-multiple-options"
id="solid-fuel-example-mutually-exclusive-multiple-options-label">Solid fuel</label>
</span>
</span>
</div>
<p class="ons-checkboxes--mutually-exclusive__item ons-u-mt-s">
<span class="ons-checkboxes__label ons-u-fs-r--b" aria-hidden="true">Or</span>
<div class="ons-input-items">
<div class="ons-radios__items">
<span class="ons-radios__item">
<span class="ons-radio">
<input type="radio" id="no-central-heating-example-mutually-exclusive-multiple-options"
class="ons-radio__input ons-js-radio ons-js-exclusive-option" value="no-central-heating"
name="no central heating" />
<label class=" ons-radio__label" for="no-central-heating-example-mutually-exclusive-multiple-options"
id="no-central-heating-example-mutually-exclusive-multiple-options-label">No central heating</label>
</span>
</span>
<br />
<span class="ons-radios__item">
<span class="ons-radio">
<input type="radio" id="other-example-mutually-exclusive-multiple-options"
class="ons-radio__input ons-js-radio ons-js-exclusive-option" value="other"
name="no central heating" />
<label class=" ons-radio__label" for="other-example-mutually-exclusive-multiple-options"
id="other-example-mutually-exclusive-multiple-options-label">Other</label>
</span>
</span>
</div>
</div>
</p>
<span class="ons-js-exclusive-alert ons-u-vh" role="alert" aria-live="polite"
data-group-adjective="deselected" data-option-adjective="deselected"></span>
</div>
</div>
</fieldset>
</div>
</div>
How to check mutually exclusive answers
To help users answer a mandatory question using this component, you should:
- check they have selected at least one checkbox
- show an error message if they have not selected any checkbox, including the mutually exclusive checkbox
- show an error message if they have not entered something in any of the fields or selected the mutually exclusive checkbox
- show an error message if what has been entered in a field is not valid
Error messages
Use the correct errors pattern and show the error details above the fieldset.
Example Mutually Exclusive Date With Error contents
Nunjucks
{% from "components/date-input/_macro.njk" import onsDateInput %}
{{
onsDateInput({
"id": "date-mutually-exclusive-with-error",
"legendOrLabel": "When did you leave your last paid job?",
"legendClasses": "ons-u-vh",
"day": {
"label": {
"text": "Day"
},
"name": "day-exclusive"
},
"month": {
"label": {
"text": "Month"
},
"name": "month-exclusive"
},
"year": {
"label": {
"text": "Year"
},
"name": "year-exclusive"
},
"mutuallyExclusive": {
"or": "Or",
"deselectMessage": "Selecting this will clear the date if one has been inputted",
"deselectGroupAdjective": "cleared",
"deselectExclusiveOptionAdjective": "deselected",
"exclusiveOptions": [
{
"id": "date-exclusive-checkbox-with-error",
"name": "no-paid-job",
"value": "no-paid-job",
"label": {
"text": "I have never had a paid job"
}
}
]
},
"error": {
"id": 'date-mutually-exclusive-error',
"text": 'Enter when you left your last paid job'
}
})
}}
Nunjucks macro options
Name | Type | Required | Description |
---|---|---|---|
id | string | false | The HTML id of the fieldset |
classes | string | false | Classes to apply to the fieldset |
legend | string | true (unless legendIsQuestionTitle is set) | Text for the fieldset’s legend |
legendClasses | string | false | Classes to apply to the legend element |
legendIsQuestionTitle | boolean | true (unless legend is set) | Creates an h1 inside the legend . Use when there is only a single fieldset on the page |
description | string | false | Description for the fieldset |
attributes | object | false | HTML attributes (for example, data attributes) to add to the fieldset |
exclusiveOptions | Array<Checkbox> or Array<radio> | true | Configuration for the mutually exclusive options |
or | string | false | Text for the “Or” label that separates the mutually exclusive checkbox from the answer options, defaults to "Or". |
deselectMessage | string | true | The text the aria-live alert will announce to warn that selecting the exclusive checkbox will clear or unselect all other answer options. For example, ”Selecting this will uncheck all other checkboxes”. |
deselectGroupAdjective | string | true | The text the aria-live alert will announce when an answer option is cleared or unselected when the mutually exclusive checkbox is selected |
deselectExclusiveOptionAdjective | string | true | The text the aria-live alert will announce when an option is cleared or unselected when the mutually exclusive checkbox is selected |
error | Error (ref) | false | Configuration for validation errors |
dontWrap | boolean | false | Prevents fields,checkboxes,date input,duration,input and Textarea from being wrapped in a fieldset component |
autosuggestresults | string | false | Shows suggested options to users as they enter something into an input field |
HTML
<div class="ons-panel ons-panel--error ons-panel--no-title" id="date-mutually-exclusive-error">
<span class="ons-panel__assistive-text ons-u-vh">Error: </span>
<div class="ons-panel__body">
<p class="ons-panel__error">
<strong>Enter when you left your last paid job</strong>
</p>
<fieldset id="date-mutually-exclusive-with-error" class="ons-fieldset">
<legend class="ons-fieldset__legend ons-u-vh"><span class="ons-fieldset__legend-title ons-u-pb-no">When did you
leave your last paid job?</span></legend>
<div class="ons-js-mutually-exclusive ons-mutually-exclusive">
<div class="ons-field-group">
<div class="ons-field">
<label class="ons-label" for="date-mutually-exclusive-with-error-day"
id="date-mutually-exclusive-with-error-day-label">Day</label>
<input type="text" id="date-mutually-exclusive-with-error-day"
class="ons-input ons-input--text ons-input-type__input ons-input--error ons-js-exclusive-group-item ons-input-number--w-2"
name="day-exclusive" maxlength="2" pattern="[0-9]*" inputmode="numeric" />
</div>
<div class="ons-field">
<label class="ons-label" for="date-mutually-exclusive-with-error-month"
id="date-mutually-exclusive-with-error-month-label">Month</label>
<input type="text" id="date-mutually-exclusive-with-error-month"
class="ons-input ons-input--text ons-input-type__input ons-input--error ons-js-exclusive-group-item ons-input-number--w-2"
name="month-exclusive" maxlength="2" pattern="[0-9]*" inputmode="numeric" />
</div>
<div class="ons-field">
<label class="ons-label" for="date-mutually-exclusive-with-error-year"
id="date-mutually-exclusive-with-error-year-label">Year</label>
<input type="text" id="date-mutually-exclusive-with-error-year"
class="ons-input ons-input--text ons-input-type__input ons-input--error ons-js-exclusive-group-item ons-input-number--w-4"
name="year-exclusive" maxlength="4" pattern="[0-9]*" inputmode="numeric" />
</div>
</div>
<p class="ons-checkboxes--mutually-exclusive__item ons-u-mt-s">
<span class="ons-checkboxes__label ons-u-fs-r--b" aria-hidden="true">Or</span>
<span class="ons-checkbox">
<input type="checkbox" id="date-exclusive-checkbox-with-error"
class="ons-checkbox__input ons-js-checkbox ons-js-exclusive-option" value="no-paid-job" name="no-paid-job"
data-deselect-message="Selecting this will clear the date if one has been inputted" />
<label class=" ons-checkbox__label" for="date-exclusive-checkbox-with-error"
id="date-exclusive-checkbox-with-error-label"><span class="ons-u-vh">Or, </span> I have never had a paid
job</label>
</span>
</p>
<span class="ons-js-exclusive-alert ons-u-vh" role="alert" aria-live="polite" data-group-adjective="cleared"
data-option-adjective="deselected"></span>
</div>
</fieldset>
</div>
</div>
Error validation for this component varies according to the mutually exclusive answer type used.
If no option is selected for a checkbox-only answer
Use “Select [whatever it is]”.
For example, “Select what type of central heating you have”.
If all fields are empty and the mutually exclusive checkbox is not selected
Use “Enter [whatever the field asks for]”.
For example, “Enter your annual income before tax in 2018/19”.
If JavaScript is unavailable
If JavaScript is not available it is possible for the user to enter or select both an answer and the mutually exclusive checkbox.
If the mutually exclusive checkbox is selected as well as an answer checkbox
Use ‘Select [whatever it is], or select “[the mutually exclusive option]”’.
For example, ‘Select what type of central heating you have, or select “No central heating”’.
If the mutually exclusive checkbox is selected and an answer has been entered into the field
Use ‘Enter [whatever the field asks for], or select “[the mutually exclusive option]”’.
For example, ‘Enter your annual income before tax in 2018/19, or select “I prefer not to say”’.
Each pattern and component that uses the mutually exclusive component has specific guidance on writing error messages:
Help improve this page
Let us know how we could improve this page, or share your user research findings. Discuss the ‘Mutually Exclusive’ component on GitHub (opens in a new tab)