Skip to content

Commit 36d3cfe

Browse files
committed
feat: Support configuration options for Atomic components
feat: [Mulitselect] Make rendering of selected Tags configurable feat: [Multiselect] Make maximum number of selections configurable
1 parent 3a97b8b commit 36d3cfe

4 files changed

Lines changed: 36 additions & 12 deletions

File tree

packages/cfpb-atomic-component/src/utilities/atomic-helpers.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,12 +100,13 @@ function setInitFlag(element) {
100100

101101
/**
102102
* @param {string} selector - Selector to search for in the document.
103+
* @param {Object} config - Configuration will be provided to the Constructor's init()
103104
* @param {Function} Constructor - A constructor function.
104105
* @param {HTMLElement} [scope] - A dom node in which to query the selector.
105106
* If not supplied, it defaults to the `document`.
106107
* @returns {Array} List of instances that were instantiated.
107108
*/
108-
function instantiateAll(selector, Constructor, scope) {
109+
function instantiateAll(selector, Constructor, scope, config = {}) {
109110
const base = scope || document;
110111
const elements = base.querySelectorAll(selector);
111112
const insts = [];
@@ -115,7 +116,7 @@ function instantiateAll(selector, Constructor, scope) {
115116
element = elements[i];
116117
if (contains(element, INIT_FLAG) === false) {
117118
inst = new Constructor(element);
118-
inst.init();
119+
inst.init(config);
119120
insts.push(inst);
120121
}
121122
}

packages/cfpb-forms/src/organisms/Multiselect.js

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ function Multiselect(element) {
4949
let _placeholder;
5050
let _model;
5151
let _options;
52+
let _config; // Configuration object
5253

5354
// Markup elems, convert this to templating engine in the future.
5455
let _containerDom;
@@ -285,10 +286,13 @@ function Multiselect(element) {
285286
const dataOptionSel = '[data-option="' + option.value + '"]';
286287
const _selectionsItemDom = _selectionsDom.querySelector(dataOptionSel);
287288

288-
if (typeof _selectionsItemDom !== 'undefined') {
289-
_selectionsDom.removeChild(_selectionsItemDom);
289+
// If the <Tag> exists
290+
if (typeof _selectionsItemDom !== 'undefined' && _selectionsItemDom) {
291+
_selectionsDom?.removeChild(_selectionsItemDom);
290292
}
291-
} else {
293+
}
294+
// Else, if we are configured to display <Tag>s then render them
295+
else if (_config?.renderTags && _selectionsDom) {
292296
_createSelectedItem(_selectionsDom, option);
293297
}
294298
_model.toggleOption(optionIndex);
@@ -512,7 +516,8 @@ function Multiselect(element) {
512516

513517
_optionItemDoms.push(optionsItemDom);
514518

515-
if (isChecked) {
519+
// Create <Tag> if enabled
520+
if (isChecked && _config?.renderTags) {
516521
_createSelectedItem(_selectionsDom, option);
517522
}
518523
}
@@ -527,9 +532,10 @@ function Multiselect(element) {
527532

528533
/**
529534
* Set up and create the multiselect.
535+
* @param _modelConfig Multiselect configuration options
530536
* @returns {Multiselect} An instance.
531537
*/
532-
function init() {
538+
function init(_modelConfig) {
533539
if (!setInitFlag(_dom)) {
534540
return this;
535541
}
@@ -544,7 +550,9 @@ function Multiselect(element) {
544550
_options = _dom.options || [];
545551

546552
if (_options.length > 0) {
547-
_model = new MultiselectModel(_options, _name).init();
553+
// Store underlying model so we can expose it externally
554+
_model = new MultiselectModel(_options, _name, _modelConfig).init();
555+
_config = _modelConfig;
548556
const newDom = _populateMarkup();
549557

550558
/* Removes <select> element,
@@ -562,6 +570,14 @@ function Multiselect(element) {
562570
return this;
563571
}
564572

573+
/**
574+
* Allow external access to the underlying model for integration/customization when used in other applications.
575+
* @returns {object} Model
576+
*/
577+
function getModel() {
578+
return _model;
579+
}
580+
565581
// Attach public events.
566582
this.init = init;
567583
this.expand = expand;
@@ -571,11 +587,16 @@ function Multiselect(element) {
571587
this.addEventListener = eventObserver.addEventListener;
572588
this.removeEventListener = eventObserver.removeEventListener;
573589
this.dispatchEvent = eventObserver.dispatchEvent;
590+
this.getModel = getModel;
591+
this.updateSelections = _updateSelections;
592+
this.selectionClickHandler = _selectionClickHandler;
593+
this.selectionKeyDownHandler = _selectionKeyDownHandler;
574594

575595
return this;
576596
}
577597

578598
Multiselect.BASE_CLASS = BASE_CLASS;
579-
Multiselect.init = () => instantiateAll(`.${BASE_CLASS}`, Multiselect);
599+
Multiselect.init = (config) =>
600+
instantiateAll(`.${BASE_CLASS}`, Multiselect, undefined, config);
580601

581602
export { Multiselect };

packages/cfpb-forms/src/organisms/MultiselectModel.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,9 @@ function stringMatch(x, y) {
2929
* @param {HTMLOptionsCollection} options -
3030
* Set of options from a <select> element.
3131
* @param {string} name - a unique name for this multiselect.
32+
* @param {Object} config - Customization of Multiselect behavior
3233
*/
33-
function MultiselectModel(options, name) {
34+
function MultiselectModel(options, name, config) {
3435
const _options = options;
3536
const _name = name;
3637
let _optionsData = [];
@@ -59,7 +60,8 @@ function MultiselectModel(options, name) {
5960
* True if the maximum number of options are checked, false otherwise.
6061
*/
6162
function isAtMaxSelections() {
62-
return _selectedIndices.length === MAX_SELECTIONS;
63+
const _max = config?.maxSelections || MAX_SELECTIONS;
64+
return _selectedIndices.length >= _max;
6365
}
6466

6567
/**

packages/cfpb-forms/src/organisms/multiselect.less

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ select.o-multiselect {
132132
pointer-events: none;
133133

134134
&::after {
135-
content: 'Reached maximum of five selections';
135+
content: 'Reached maximum number of selections';
136136
}
137137
}
138138

0 commit comments

Comments
 (0)