Skip to content

Commit

Permalink
Attributes for option select button
Browse files Browse the repository at this point in the history
- modify the option select component to allow it to accept data attributes to be added to the expand/collapse button
- the attributes are rendered on the parent element, then read in by JavaScript to be included in the JavaScript generated button, which replaces the title element of the component
- to be used for GA4 tracking purposes in finder-frontend, in place of an existing solution
- will be a breaking change, as removes the event listener that was previously being used for this
- credit to @floehopper
  • Loading branch information
andysellick committed Dec 7, 2023
1 parent 64cc74d commit 0ffde2c
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 8 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
useful summary for people upgrading their application, not a replication
of the commit log.

## Unreleased

* [BREAKING] Data attributes for option select button ([PR #3750](https://github.com/alphagov/govuk_publishing_components/pull/3750))

## 36.1.0

* Add heading option to file input component ([PR #3755](https://github.com/alphagov/govuk_publishing_components/pull/3755))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,17 +166,24 @@ window.GOVUK.Modules = window.GOVUK.Modules || {};
button.setAttribute('aria-expanded', true)
button.setAttribute('id', containerHead.getAttribute('id'))
button.setAttribute('aria-controls', this.$optionsContainer.getAttribute('id'))
button.innerHTML = jsContainerHeadHTML
containerHead.parentNode.replaceChild(button, containerHead)

// GA4 Accordion tracking. Relies on the ga4-finder-tracker setting the index first, so we wrap this in a custom event.
window.addEventListener('ga4-filter-indexes-added', function () {
if (window.GOVUK.analyticsGa4) {
if (window.GOVUK.analyticsGa4.Ga4FinderTracker) {
window.GOVUK.analyticsGa4.Ga4FinderTracker.addFilterButtonTracking(button, button.innerHTML)
var buttonAttributes = this.$optionSelect.getAttribute('data-button-data-attributes')
if (buttonAttributes) {
try {
buttonAttributes = JSON.parse(buttonAttributes)
for (var rawKey in buttonAttributes) {
var key = rawKey.replace(/_/i, '-').toLowerCase()
var rawValue = buttonAttributes[rawKey]
var value = typeof rawValue === 'object' ? JSON.stringify(rawValue) : rawValue
button.setAttribute('data-' + key, value)
}
} catch (e) {
console.error('Error with option select button data attributes, invalid JSON passed' + e.message, window.location)
}
})
}

button.innerHTML = jsContainerHeadHTML
containerHead.parentNode.replaceChild(button, containerHead)
}

OptionSelect.prototype.attachCheckedCounter = function attachCheckedCounter (checkedString) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
helper.add_data_attribute({ "closed-on-load-mobile": "true" }) if local_assigns.include?(:closed_on_load_mobile) && closed_on_load_mobile
helper.add_data_attribute({ "input-aria-controls": aria_controls_id }) if local_assigns.include?(:aria_controls_id)
helper.add_data_attribute({ "filter-element": filter_element }) if show_filter
helper.add_data_attribute({ "button-data-attributes": button_data_attributes }) if local_assigns.include?(:button_data_attributes)

options_container_classes = %w[gem-c-option-select__container js-options-container]
options_container_classes << "gem-c-option-select__container--large" if large
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,24 @@ examples:
track_label: "high_heels"
track_options:
dimension28: 1
with_button_data_attributes:
description: Allows data attributes to be passed to the component to be added to the expand/collapse button. The attributes are written to the parent element then read by the JavaScript and applied to the button. This is used for tracking purposes.
data:
key: market_sector
title: Market sector
options_container_id: list_of_sectors
button_data_attributes:
ga4_expandable: ""
ga4_event:
event_name: "select_content"
type: "finder"
options:
- value: aerospace
label: Aerospace
id: aerospace
- value: agriculture-environment-and-natural-resources
label: Agriculture, environment and natural resources
id: agriculture-environment-and-natural-resources
with_filter:
description: Adds a filter to allow users to narrow the checkboxes down. Checkboxes will only show if they match what the user has typed, or if they are already checked. The filter is case insensitive and strips out punctuation characters and duplicate whitespace, and sees '&' and 'and' as the same, to make filtering easier.
data:
Expand Down
14 changes: 14 additions & 0 deletions spec/components/option_select_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,20 @@ def option_select_with_tracking_arguments
expect(rendered).to have_no_selector(".gem-c-option-select__count")
end

it "accepts button data attributes" do
options = option_select_arguments
button_attrs = {
ga4_expandable: "true",
ga4_event: {
event_name: "select_content",
type: "finder",
},
}
options[:button_data_attributes] = button_attrs
render_component(options)
expect(rendered).to have_selector(".gem-c-option-select[data-button-data-attributes='#{button_attrs.to_json}']")
end

def expect_label_and_checked_checkbox(label, id, value)
expect_label_and_checkbox(label, id, value, checked: true)
end
Expand Down
26 changes: 26 additions & 0 deletions spec/javascripts/components/option-select-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,32 @@ describe('An option select component', function () {

expect($($element).find('button')).toBeDefined()
})

it('accepts data attributes to be applied to the button element', function () {
$element = document.createElement('div')
$element.innerHTML = html
var buttonAttrs = {
ga4_expandable: '',
ga4_event: {
event_name: 'select_content',
type: 'finder'
}
}
$element.querySelector('.gem-c-option-select').setAttribute('data-button-data-attributes', JSON.stringify(buttonAttrs))

new GOVUK.Modules.OptionSelect($element.querySelector('.gem-c-option-select')).init()
expect($($element).find('.gem-c-option-select__button').attr('data-ga4-expandable')).toBe('')
expect($($element).find('.gem-c-option-select__button').attr('data-ga4-event')).toBe(JSON.stringify(buttonAttrs.ga4_event))
})

it('does not error if invalid data attributes are passed for the button element', function () {
$element = document.createElement('div')
$element.innerHTML = html
$element.querySelector('.gem-c-option-select').setAttribute('data-button-data-attributes', 'not JSON')

new GOVUK.Modules.OptionSelect($element.querySelector('.gem-c-option-select')).init()
expect($($element).find('.gem-c-option-select__button').attr('data-ga4-expandable')).toBe(undefined)
})
})

describe('toggleOptionSelect', function () {
Expand Down

0 comments on commit 0ffde2c

Please sign in to comment.