diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1613b1548f..2a22d20a0d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,38 @@
## Unreleased
+### New features
+
+#### Check checkboxes by using the `values` Nunjucks option
+
+When using the `govukCheckboxes` Nunjucks macro, you can now use the `values` option to indicate which checkboxes should be checked when the page loads.
+
+For example, `values: ['red', 'blue']` would check any checkboxes that have a `value` of 'red' or 'blue'.
+
+This is an alternative to setting the boolean `checked` option on each individual checkbox.
+
+This change was introduced in [pull request #2616: Allow selecting options by passing current values](https://github.com/alphagov/govuk-frontend/pull/2616).
+
+#### Check a radio button by using the `value` Nunjucks option
+
+When using the `govukRadios` Nunjucks macro, you can now use the `value` option to indicate which radio should be checked when the page loads.
+
+For example, `value: 'red'` would check the radio that has a `value` of 'red'.
+
+This is an alternative to setting the boolean `checked` option on each individual radio.
+
+This change was introduced in [pull request #2616: Allow selecting options by passing current values](https://github.com/alphagov/govuk-frontend/pull/2616).
+
+#### Select an option in a select by using the `value` Nunjucks option
+
+When using the `govukSelect` Nunjucks macro, you can now use the `value` option to indicate which option should be selected when the page loads.
+
+For example, `value: 'red'` would select the option that has a `value` of 'red'.
+
+This is an alternative to setting the boolean `selected` option on each individual option.
+
+This change was introduced in [pull request #2616: Allow selecting options by passing current values](https://github.com/alphagov/govuk-frontend/pull/2616).
+
### Recommended changes
#### Replace deprecated `govuk-header__link--service-name` class in the header
diff --git a/src/govuk/components/checkboxes/checkboxes.yaml b/src/govuk/components/checkboxes/checkboxes.yaml
index 064ac665b1..151203f252 100644
--- a/src/govuk/components/checkboxes/checkboxes.yaml
+++ b/src/govuk/components/checkboxes/checkboxes.yaml
@@ -77,7 +77,7 @@ params:
- name: checked
type: boolean
required: false
- description: If `true`, checkbox will be checked.
+ description: Whether the checkbox should be checked when the page loads. Takes precedence over the top-level `values` option.
- name: conditional
type: boolean
required: false
@@ -98,6 +98,10 @@ params:
type: object
required: false
description: HTML attributes (for example data attributes) to add to the checkbox input tag.
+- name: values
+ type: array
+ required: false
+ description: Array of values for checkboxes which should be checked when the page loads. Use this as an alternative to setting the `checked` option on each individual item.
- name: classes
type: string
required: false
@@ -129,6 +133,28 @@ examples:
- value: other
text: Citizen of another country
+- name: with pre-checked values
+ data:
+ name: nationality
+ items:
+ - value: british
+ text: British
+ - value: irish
+ text: Irish
+ - value: other
+ text: Citizen of another country
+ conditional:
+ html: |
+
+
+
+
+ values:
+ - british
+ - other
+
- name: with divider and None
data:
name: with-divider-and-none
@@ -875,3 +901,17 @@ examples:
text: British
- value: irish
text: Irish
+
+- name: item checked overrides values
+ hidden: true
+ data:
+ name: colors
+ items:
+ - value: red
+ text: Red
+ - value: green
+ text: Green
+ checked: false
+ - value: blue
+ text: Blue
+ values: [red, green]
diff --git a/src/govuk/components/checkboxes/template.njk b/src/govuk/components/checkboxes/template.njk
index d87bbb9ffb..898ebd03d8 100644
--- a/src/govuk/components/checkboxes/template.njk
+++ b/src/govuk/components/checkboxes/template.njk
@@ -63,13 +63,14 @@
{%- if item.divider %}
{{ item.divider }}
{%- else %}
+ {% set isChecked = item.checked | default(params.values and item.value in params.values) %}
{% set hasHint = true if item.hint.text or item.hint.html %}
{% set itemHintId = id + "-item-hint" if hasHint else "" %}
{% set itemDescribedBy = describedBy if not hasFieldset else "" %}
{% set itemDescribedBy = (itemDescribedBy + " " + itemHintId) | trim %}
{% if item.conditional.html %}
-
+
{{ item.conditional.html | safe }}
{% endif %}
diff --git a/src/govuk/components/checkboxes/template.test.js b/src/govuk/components/checkboxes/template.test.js
index 786b5b30bf..03eb27331a 100644
--- a/src/govuk/components/checkboxes/template.test.js
+++ b/src/govuk/components/checkboxes/template.test.js
@@ -183,6 +183,24 @@ describe('Checkboxes', () => {
expect($lastInput.attr('checked')).toEqual('checked')
})
+ it('checks the checkboxes in values', () => {
+ const $ = render('checkboxes', examples['with pre-checked values'])
+
+ const $component = $('.govuk-checkboxes')
+ const $british = $component.find('input[value="british"]')
+ expect($british.attr('checked')).toEqual('checked')
+
+ const $other = $component.find('input[value="other"]')
+ expect($other.attr('checked')).toEqual('checked')
+ })
+
+ it('allows item.checked to override values', () => {
+ const $ = render('checkboxes', examples['item checked overrides values'])
+
+ const $green = $('.govuk-checkboxes').find('input[value="green"]')
+ expect($green.attr('checked')).toBeUndefined()
+ })
+
describe('when they include attributes', () => {
it('it renders the attributes', () => {
const $ = render('checkboxes', examples['items with attributes'])
@@ -241,6 +259,16 @@ describe('Checkboxes', () => {
expect($firstConditional.hasClass('govuk-checkboxes__conditional--hidden')).toBeFalsy()
})
+ it('visible when checked with pre-checked values', () => {
+ const $ = render('checkboxes', examples['with pre-checked values'])
+
+ const $component = $('.govuk-checkboxes')
+
+ const $firstConditional = $component.find('.govuk-checkboxes__conditional').first()
+ expect($firstConditional.text().trim()).toContain('Country')
+ expect($firstConditional.hasClass('govuk-checkboxes__conditional--hidden')).toBeFalsy()
+ })
+
it('with association to the input they are controlled by', () => {
const $ = render('checkboxes', examples['with conditional items'])
diff --git a/src/govuk/components/radios/radios.yaml b/src/govuk/components/radios/radios.yaml
index 81a5865e00..7eaa348dbd 100644
--- a/src/govuk/components/radios/radios.yaml
+++ b/src/govuk/components/radios/radios.yaml
@@ -69,7 +69,7 @@ params:
- name: checked
type: boolean
required: false
- description: If `true`, radio will be checked.
+ description: Whether the radio should be checked when the page loads. Takes precedence over the top-level `value` option.
- name: conditional
type: string
required: false
@@ -86,6 +86,10 @@ params:
type: object
required: false
description: HTML attributes (for example data attributes) to add to the radio input tag.
+- name: value
+ type: string
+ required: false
+ description: The value for the radio which should be checked when the page loads. Use this as an alternative to setting the `checked` option on each individual item.
- name: classes
type: string
required: false
@@ -116,7 +120,6 @@ examples:
text: Yes
- value: no
text: No
- checked: true
- name: inline
data:
@@ -382,6 +385,56 @@ examples:
+- name: prechecked
+ data:
+ name: example-default
+ hint:
+ text: This includes changing your last name or spelling your name differently.
+ items:
+ - value: yes
+ text: Yes
+ - value: no
+ text: No
+ checked: true
+
+- name: prechecked using value
+ data:
+ name: example-default
+ items:
+ - value: yes
+ text: Yes
+ - value: no
+ text: No
+ value: no
+
+- name: with conditional items and pre-checked value
+ data:
+ idPrefix: 'how-contacted-checked'
+ name: 'how-contacted-checked'
+ fieldset:
+ legend:
+ text: How do you want to be contacted?
+ items:
+ - value: email
+ text: Email
+ conditional:
+ html: |
+
+
+ - value: phone
+ text: Phone
+ conditional:
+ html: |
+
+
+ - value: text
+ text: Text message
+ conditional:
+ html: |
+
+
+ value: text
+
- name: with optional form-group classes showing group error
data:
idPrefix: 'how-contacted-2'
@@ -838,3 +891,17 @@ examples:
- value: no
text: No
checked: true
+
+- name: item checked overrides value
+ hidden: true
+ data:
+ name: colors
+ items:
+ - value: red
+ text: Red
+ - value: green
+ text: Green
+ checked: false
+ - value: blue
+ text: Blue
+ value: green
diff --git a/src/govuk/components/radios/template.njk b/src/govuk/components/radios/template.njk
index 9e3316d108..a7f677915e 100644
--- a/src/govuk/components/radios/template.njk
+++ b/src/govuk/components/radios/template.njk
@@ -56,11 +56,12 @@
{%- if item.divider %}
{{ item.divider }}
{%- else %}
+ {% set isChecked = item.checked | default(params.value and item.value == params.value) %}
{% set hasHint = true if item.hint.text or item.hint.html %}
{% set itemHintId = id + '-item-hint' %}
{% if item.conditional.html %}
-
+
{{ item.conditional.html | safe }}
{% endif %}
diff --git a/src/govuk/components/radios/template.test.js b/src/govuk/components/radios/template.test.js
index 7593bd0121..c2cf79c197 100644
--- a/src/govuk/components/radios/template.test.js
+++ b/src/govuk/components/radios/template.test.js
@@ -122,13 +122,28 @@ describe('Radios', () => {
})
it('render checked', () => {
- const $ = render('radios', examples.default)
+ const $ = render('radios', examples.prechecked)
const $component = $('.govuk-radios')
const $lastInput = $component.find('.govuk-radios__item:last-child input')
expect($lastInput.attr('checked')).toEqual('checked')
})
+ it('checks the radio that matches value', () => {
+ const $ = render('radios', examples['prechecked using value'])
+
+ const $component = $('.govuk-radios')
+ const $lastInput = $component.find('input[value="no"]')
+ expect($lastInput.attr('checked')).toEqual('checked')
+ })
+
+ it('allows item.checked to override value', () => {
+ const $ = render('radios', examples['item checked overrides value'])
+
+ const $green = $('.govuk-radios').find('input[value="green"]')
+ expect($green.attr('checked')).toBeUndefined()
+ })
+
describe('when they include attributes', () => {
it('it renders the attributes', () => {
const $ = render('radios', examples['items with attributes'])
@@ -177,6 +192,14 @@ describe('Radios', () => {
expect($hiddenConditional.hasClass('govuk-radios__conditional--hidden')).toBeTruthy()
})
+ it('visible when checked because of checkedValue', () => {
+ const $ = render('radios', examples['with conditional items and pre-checked value'])
+
+ const $conditional = $('.govuk-radios__conditional').last()
+ expect($conditional.text()).toContain('Mobile phone number')
+ expect($conditional.hasClass('govuk-radios__conditional--hidden')).toBeFalsy()
+ })
+
it('visible by default when checked', () => {
const $ = render('radios', examples['with conditional item checked'])
diff --git a/src/govuk/components/select/select.yaml b/src/govuk/components/select/select.yaml
index 85ad0445e6..1c6114c8b8 100644
--- a/src/govuk/components/select/select.yaml
+++ b/src/govuk/components/select/select.yaml
@@ -23,7 +23,7 @@ params:
- name: selected
type: boolean
required: false
- description: Sets the option as the selected.
+ description: Whether the option should be selected when the page loads. Takes precedence over the top-level `value` option.
- name: disabled
type: boolean
required: false
@@ -32,6 +32,10 @@ params:
type: object
required: false
description: HTML attributes (for example data attributes) to add to the option.
+- name: value
+ type: string
+ required: false
+ description: Value for the option which should be selected. Use this as an alternative to setting the `selected` option on each individual item.
- name: describedBy
type: string
required: false
@@ -88,6 +92,25 @@ examples:
value: 3
text: GOV.UK frontend option 3
disabled: true
+ - name: with selected value
+ data:
+ id: select-1
+ name: select-1
+ label:
+ text: Label text goes here
+ items:
+ -
+ value: 1
+ text: GOV.UK frontend option 1
+ -
+ value: 2
+ text: GOV.UK frontend option 2
+ selected: true
+ -
+ value: 3
+ text: GOV.UK frontend option 3
+ disabled: true
+ value: 3
- name: with hint text and error message
data:
id: select-2
@@ -282,3 +305,17 @@ examples:
-
value: 2
text: GOV.UK frontend option 2
+
+ - name: item selected overrides value
+ hidden: true
+ data:
+ name: colors
+ items:
+ - value: red
+ text: Red
+ - value: green
+ text: Green
+ selected: false
+ - value: blue
+ text: Blue
+ value: green
diff --git a/src/govuk/components/select/template.njk b/src/govuk/components/select/template.njk
index b9e22bd195..eea2a4dbbb 100644
--- a/src/govuk/components/select/template.njk
+++ b/src/govuk/components/select/template.njk
@@ -42,7 +42,7 @@
{% for item in params.items %}
{% if item %}
{% endif %}
diff --git a/src/govuk/components/select/template.test.js b/src/govuk/components/select/template.test.js
index 9bb4adc8ef..64659a3678 100644
--- a/src/govuk/components/select/template.test.js
+++ b/src/govuk/components/select/template.test.js
@@ -62,6 +62,20 @@ describe('Select', () => {
expect($selectedItem.attr('selected')).toBeTruthy()
})
+ it('selects options using selected value', () => {
+ const $ = render('select', examples['with selected value'])
+
+ const $selectedItem = $('option[value="2"]')
+ expect($selectedItem.attr('selected')).toBeTruthy()
+ })
+
+ it('allows item.selected to override value', () => {
+ const $ = render('select', examples['item selected overrides value'])
+
+ const $selectedItem = $('option[value="green"]')
+ expect($selectedItem.attr('selected')).toBeUndefined()
+ })
+
it('renders item with disabled', () => {
const $ = render('select', examples.default)