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)