Skip to content

Commit

Permalink
feat: Support configuration options for Atomic components
Browse files Browse the repository at this point in the history
feat: [Mulitselect] Make rendering of selected Tags configurable
feat: [Multiselect] Make maximum number of selections configurable
  • Loading branch information
meissadia committed Nov 1, 2023
1 parent 60e5645 commit 500be6f
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -100,12 +100,13 @@ function setInitFlag(element) {

/**
* @param {string} selector - Selector to search for in the document.
* @param {Object} config - Configuration will be provided to the Constructor's init()
* @param {Function} Constructor - A constructor function.
* @param {HTMLElement} [scope] - A dom node in which to query the selector.
* If not supplied, it defaults to the `document`.
* @returns {Array} List of instances that were instantiated.
*/
function instantiateAll(selector, Constructor, scope) {
function instantiateAll(selector, Constructor, scope, config = {}) {
const base = scope || document;
const elements = base.querySelectorAll(selector);
const insts = [];
Expand All @@ -115,7 +116,7 @@ function instantiateAll(selector, Constructor, scope) {
element = elements[i];
if (contains(element, INIT_FLAG) === false) {
inst = new Constructor(element);
inst.init();
inst.init(config);
insts.push(inst);
}
}
Expand Down
35 changes: 28 additions & 7 deletions packages/cfpb-forms/src/organisms/Multiselect.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ function Multiselect(element) {
let _placeholder;
let _model;
let _options;
let _config; // Configuration object

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

if (typeof _selectionsItemDom !== 'undefined') {
_selectionsDom.removeChild(_selectionsItemDom);
// If the <Tag> exists
if (typeof _selectionsItemDom !== 'undefined' && _selectionsItemDom) {
_selectionsDom?.removeChild(_selectionsItemDom);
}
} else {
}
// Else, if we are configured to display <Tag>s then render them
else if (_config.renderTags && _selectionsDom) {
_createSelectedItem(_selectionsDom, option);
}
_model.toggleOption(optionIndex);
Expand Down Expand Up @@ -512,7 +516,8 @@ function Multiselect(element) {

_optionItemDoms.push(optionsItemDom);

if (isChecked) {
// Create <Tag> if enabled
if (isChecked && _config.renderTags) {
_createSelectedItem(_selectionsDom, option);
}
}
Expand All @@ -527,9 +532,10 @@ function Multiselect(element) {

/**
* Set up and create the multiselect.
* @param _modelConfig Multiselect configuration options
* @returns {Multiselect} An instance.
*/
function init() {
function init(_modelConfig) {
if (!setInitFlag(_dom)) {
return this;
}
Expand All @@ -544,7 +550,9 @@ function Multiselect(element) {
_options = _dom.options || [];

if (_options.length > 0) {
_model = new MultiselectModel(_options, _name).init();
// Store underlying model so we can expose it externally
_model = new MultiselectModel(_options, _name, _modelConfig).init();
_config = _modelConfig;
const newDom = _populateMarkup();

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

/**
* Allow external access to the underlying model for integration/customization when used in other applications.
* @returns {object} Model
*/
function getModel() {
return _model;
}

// Attach public events.
this.init = init;
this.expand = expand;
Expand All @@ -571,11 +587,16 @@ function Multiselect(element) {
this.addEventListener = eventObserver.addEventListener;
this.removeEventListener = eventObserver.removeEventListener;
this.dispatchEvent = eventObserver.dispatchEvent;
this.getModel = getModel;
this.updateSelections = _updateSelections;
this.selectionClickHandler = _selectionClickHandler;
this.selectionKeyDownHandler = _selectionKeyDownHandler;

return this;
}

Multiselect.BASE_CLASS = BASE_CLASS;
Multiselect.init = () => instantiateAll(`.${BASE_CLASS}`, Multiselect);
Multiselect.init = (config) =>
instantiateAll(`.${BASE_CLASS}`, Multiselect, undefined, config);

export { Multiselect };
6 changes: 4 additions & 2 deletions packages/cfpb-forms/src/organisms/MultiselectModel.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,9 @@ function stringMatch(x, y) {
* @param {HTMLOptionsCollection} options -
* Set of options from a <select> element.
* @param {string} name - a unique name for this multiselect.
* @param {Object} config - Customization of Multiselect behavior
*/
function MultiselectModel(options, name) {
function MultiselectModel(options, name, config) {
const _options = options;
const _name = name;
let _optionsData = [];
Expand Down Expand Up @@ -59,7 +60,8 @@ function MultiselectModel(options, name) {
* True if the maximum number of options are checked, false otherwise.
*/
function isAtMaxSelections() {
return _selectedIndices.length === MAX_SELECTIONS;
const _max = config.maxSelections || MAX_SELECTIONS;
return _selectedIndices.length >= _max;
}

/**
Expand Down
2 changes: 1 addition & 1 deletion packages/cfpb-forms/src/organisms/multiselect.less
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ select.o-multiselect {
pointer-events: none;

&::after {
content: 'Reached maximum of five selections';
content: 'Reached maximum number of selections';
}
}

Expand Down

0 comments on commit 500be6f

Please sign in to comment.