Skip to content

Commit d4f90a8

Browse files
task/CDD-3293-CMS-FIX-Dual-category-chart-component
fix multiple charts issue: - DualCategoryChartCardBlockDefinition is a singleton and so the code needs to treat each chart as a new instance. - CSS queries must be scoped to rootNode, this being the DOM root element on which each chart is rendered.
1 parent f10a091 commit d4f90a8

1 file changed

Lines changed: 36 additions & 31 deletions

File tree

cms/dashboard/static/js/dual_category_chart_form.js

Lines changed: 36 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,15 @@ class FormStateManger {
8787

8888

8989
class DualCategoryChartCardBlockDefinition extends globalThis.wagtailStreamField.blocks.StructBlockDefinition {
90+
render(placeholder, prefix, initialState, initialError) {
91+
const block = super.render(placeholder, prefix, initialState, initialError);
92+
const chart = new DualCategoryChartCard()
93+
chart.render(prefix, initialState, block)
94+
return block;
95+
}
96+
}
9097

98+
class DualCategoryChartCard {
9199
static SELECTORS = {
92100
SEGMENTS_CONTAINER: '.dual-category-chart-segments-container-form',
93101
SEGMENT_ITEM: '.dual-category-chart-card__segments',
@@ -132,7 +140,7 @@ class DualCategoryChartCardBlockDefinition extends globalThis.wagtailStreamField
132140
* @param prefix - {string} html form prefix for element IDs
133141
*/
134142
setupDataScript(prefix) {
135-
const script_id = `${prefix}-${DualCategoryChartCardBlockDefinition.FIELD_SUFFIXES.DATA_SCRIPT}`;
143+
const script_id = `${prefix}-${DualCategoryChartCard.FIELD_SUFFIXES.DATA_SCRIPT}`;
136144
this.data_script = document.getElementById(script_id);
137145

138146
if (!this.data_script) {
@@ -158,12 +166,12 @@ class DualCategoryChartCardBlockDefinition extends globalThis.wagtailStreamField
158166
* `primary_field_values` options with age related options.
159167
* @param prefix - {string} html form prefix for element IDs
160168
*/
161-
setupCategoryFormFields(prefix) {
162-
const { FIELD_SUFFIXES } = DualCategoryChartCardBlockDefinition;
169+
setupCategoryFormFields(prefix, rootNode) {
170+
const { FIELD_SUFFIXES } = DualCategoryChartCard;
163171

164-
this.x_axis_field = document.getElementById(`${prefix}-${FIELD_SUFFIXES.X_AXIS}`);
165-
this.geography_type_field = document.getElementById(`${prefix}-${FIELD_SUFFIXES.GEOGRAPHY}`);
166-
this.secondary_category_field = document.getElementById(`${prefix}-${FIELD_SUFFIXES.SECONDARY_CATEGORY}`);
172+
this.x_axis_field = rootNode.querySelector(`select#${prefix}-${FIELD_SUFFIXES.X_AXIS}`);
173+
this.geography_type_field = rootNode.querySelector(`select#${prefix}-${FIELD_SUFFIXES.GEOGRAPHY}`);
174+
this.secondary_category_field = rootNode.querySelector(`select#${prefix}-${FIELD_SUFFIXES.SECONDARY_CATEGORY}`);
167175

168176
const missingFields = [];
169177
if (!this.x_axis_field) missingFields.push(FIELD_SUFFIXES.X_AXIS);
@@ -187,13 +195,13 @@ class DualCategoryChartCardBlockDefinition extends globalThis.wagtailStreamField
187195
* to the category selected in `x_axis` field from our `primary form fields`
188196
* @param prefix
189197
*/
190-
setupSubCategoryFormFields(prefix) {
191-
const { FIELD_SUFFIXES, SELECTORS } = DualCategoryChartCardBlockDefinition;
198+
setupSubCategoryFormFields(prefix, rootNode) {
199+
const { FIELD_SUFFIXES, SELECTORS } = DualCategoryChartCard;
192200

193-
this.primary_field_values_inputs = document.getElementById(
194-
`${prefix}-${FIELD_SUFFIXES.PRIMARY_VALUES}`
201+
this.primary_field_values_inputs = rootNode.querySelector(
202+
`select#${prefix}-${FIELD_SUFFIXES.PRIMARY_VALUES}`
195203
);
196-
this.secondary_field_value_inputs = document.querySelectorAll(
204+
this.secondary_field_value_inputs = rootNode.querySelectorAll(
197205
`[id^="${prefix}-${FIELD_SUFFIXES.SEGMENTS}-"]${SELECTORS.SECONDARY_FIELD_VALUE}`
198206
);
199207

@@ -219,7 +227,7 @@ class DualCategoryChartCardBlockDefinition extends globalThis.wagtailStreamField
219227
return;
220228
}
221229

222-
const { DEFAULT_OPTION } = DualCategoryChartCardBlockDefinition;
230+
const { DEFAULT_OPTION } = DualCategoryChartCard;
223231

224232
if (this.x_axis_field && this.primary_field_values_inputs) {
225233
this.updatePrimaryFieldValueOptions(this.x_axis_field.value);
@@ -248,7 +256,7 @@ class DualCategoryChartCardBlockDefinition extends globalThis.wagtailStreamField
248256
* @param subcategory_key {string} representing the sub category key (primary category)
249257
*/
250258
getFieldOptions(subcategory_key) {
251-
const { GEOGRAPHY_SUBCATEGORY_KEY } = DualCategoryChartCardBlockDefinition.FIELD_SUFFIXES
259+
const { GEOGRAPHY_SUBCATEGORY_KEY } = DualCategoryChartCard.FIELD_SUFFIXES
252260

253261
if (subcategory_key && subcategory_key !== GEOGRAPHY_SUBCATEGORY_KEY) {
254262
return this.secondary_category_choices[subcategory_key] || [];
@@ -267,7 +275,7 @@ class DualCategoryChartCardBlockDefinition extends globalThis.wagtailStreamField
267275
* @param subcategory_key - {string} the subcategory key used to retrieve the primary field value options.
268276
*/
269277
updatePrimaryFieldValueOptions(subcategory_key) {
270-
const { DEFAULT_OPTION } = DualCategoryChartCardBlockDefinition;
278+
const { DEFAULT_OPTION } = DualCategoryChartCard;
271279

272280
this.primary_field_values_inputs.innerHTML = `<option value="${DEFAULT_OPTION.VALUE}">${DEFAULT_OPTION.TEXT}</option>`;
273281

@@ -292,7 +300,7 @@ class DualCategoryChartCardBlockDefinition extends globalThis.wagtailStreamField
292300
* @param subcategory_key - {string} the subcategory key used to retrieve the primary field value options.
293301
*/
294302
updateSecondaryFieldValueOptions(subcategory_key) {
295-
const { DEFAULT_OPTION } = DualCategoryChartCardBlockDefinition;
303+
const { DEFAULT_OPTION } = DualCategoryChartCard;
296304

297305
this.secondary_field_value_inputs.forEach((secondary_field_value, index) => {
298306
secondary_field_value.innerHTML = `<option value="${DEFAULT_OPTION.VALUE}">${DEFAULT_OPTION.TEXT}</option>`;
@@ -320,9 +328,9 @@ class DualCategoryChartCardBlockDefinition extends globalThis.wagtailStreamField
320328
* `SecondaryFormFields` and then update the options of these lists to ensure they align with the primary fields.
321329
* @param prefix
322330
*/
323-
observeSegmentBlocks(prefix) {
324-
const { SELECTORS } = DualCategoryChartCardBlockDefinition;
325-
const segments_container = document.querySelector(SELECTORS.SEGMENTS_CONTAINER)
331+
observeSegmentBlocks(prefix, rootNode) {
332+
const { SELECTORS } = DualCategoryChartCard;
333+
const segments_container = rootNode.querySelector(SELECTORS.SEGMENTS_CONTAINER)
326334

327335
if (!segments_container) {
328336
console.warn("Segments container not found - observer disabled");
@@ -336,7 +344,7 @@ class DualCategoryChartCardBlockDefinition extends globalThis.wagtailStreamField
336344
if (node.nodeType === 1 && node.matches(SELECTORS.SEGMENT_ITEM)) {
337345
this.stateManager.storeCurrentSelections(this.secondary_field_value_inputs);
338346

339-
this.setupSubCategoryFormFields(prefix);
347+
this.setupSubCategoryFormFields(prefix, rootNode);
340348
if (this.secondary_category_field.value) {
341349
this.updateSecondaryFieldValueOptions(this.secondary_category_field.value);
342350
}
@@ -358,8 +366,8 @@ class DualCategoryChartCardBlockDefinition extends globalThis.wagtailStreamField
358366
* @name setupEvents
359367
* @description Setup event handlers for dynamic choice fields `secondary_category` and `x_axis_field`.
360368
*/
361-
setupEvents() {
362-
const { FIELD_SUFFIXES } = DualCategoryChartCardBlockDefinition;
369+
setupEvents(rootNode) {
370+
const { FIELD_SUFFIXES } = DualCategoryChartCard;
363371

364372
this.x_axis_field.addEventListener("change", (evt) => {
365373
this.stateManager.clearPrimaryFieldState();
@@ -371,7 +379,7 @@ class DualCategoryChartCardBlockDefinition extends globalThis.wagtailStreamField
371379
this.updateSecondaryFieldValueOptions(evt.target.value);
372380

373381
// clear all segments
374-
document
382+
rootNode
375383
.querySelectorAll('.dual-category-chart-card__segments')
376384
.forEach(segments => {
377385
const section = segments.closest('section[id$="-section"]');
@@ -394,9 +402,8 @@ class DualCategoryChartCardBlockDefinition extends globalThis.wagtailStreamField
394402
});
395403
}
396404

397-
render(placeholder, prefix, initialState, initialError) {
398-
399-
const block = super.render(placeholder, prefix, initialState, initialError);
405+
render(prefix, initialState, block) {
406+
const rootNode = block.container[4]
400407

401408
// initialise form state
402409
this.stateManager.initialise(initialState);
@@ -405,17 +412,15 @@ class DualCategoryChartCardBlockDefinition extends globalThis.wagtailStreamField
405412
this.setupDataScript(prefix);
406413

407414
// setup primary and secondary form fields
408-
this.setupCategoryFormFields(prefix);
409-
this.setupSubCategoryFormFields(prefix);
415+
this.setupCategoryFormFields(prefix, rootNode);
416+
this.setupSubCategoryFormFields(prefix, rootNode);
410417

411418
// Initial population of field options based on current/initial values
412419
this.initialiseFieldOptions();
413420

414421
// Setup observer for watching segments list and event handlers on
415-
this.observeSegmentBlocks(prefix);
416-
this.setupEvents();
417-
418-
return block;
422+
this.observeSegmentBlocks(prefix, rootNode);
423+
this.setupEvents(rootNode);
419424
}
420425

421426
}

0 commit comments

Comments
 (0)