diff --git a/src/js/components/fields/__snapshots__/edit-panel-item.spec.js.snap b/src/js/components/fields/__snapshots__/edit-panel-item.spec.js.snap index 363e5e00..933cc650 100644 --- a/src/js/components/fields/__snapshots__/edit-panel-item.spec.js.snap +++ b/src/js/components/fields/__snapshots__/edit-panel-item.spec.js.snap @@ -14,8 +14,8 @@ EditPanelItem { > ({ click: ({ target: { checked } }) => { + if (field.data?.attrs?.type === 'radio') { + field.set('options', field.data.options.map(option => ({ ...option, selected: false }))) + } field.set(dataKey, checked) field.updatePreview() }, @@ -148,18 +151,19 @@ export default class EditPanelItem { * @param {String} field * @return {Object} field object */ - constructor(itemKey, itemData, field) { - this.itemValues = orderObjectsBy(Object.entries(itemData), INPUT_ORDER, '0') + constructor({ key, data, index, field }) { + this.itemValues = orderObjectsBy(Object.entries(data), INPUT_ORDER, '0') + const [panelName, item] = key.split('.') this.field = field - this.itemKey = itemKey - const [panelName, item] = itemKey.split('.') + this.itemKey = key + this.itemIndex = index this.panelName = panelName this.isDisabled = field.isDisabledProp(item, panelName) this.isHidden = this.isDisabled && field.config.panels[panelName].hideDisabled this.isLocked = field.isLockedProp(item, panelName) this.dom = dom.create({ tag: 'li', - className: [`field-${itemKey.replace(/\./g, '-')}`, 'prop-wrap', this.isHidden && 'hidden-property'], + className: [`field-${key.replace(/\./g, '-')}`, 'prop-wrap', this.isHidden && 'hidden-property'], children: { className: 'field-prop', children: [this.itemInputs, this.itemControls] }, }) } @@ -422,9 +426,9 @@ export default class EditPanelItem { .filter(isNaN) .join('.') - const id = [this.field.id, !['selected', 'checked'].includes(key) && this.itemKey.replace(/\./g, '-')] - .filter(Boolean) - .join('-') + const [id, name] = [[...this.itemKey.split('.'), key], [key]].map(attrVars => + [this.field.id, ...attrVars].filter(Boolean).join('-') + ) inputTypeConfig.config = Object.assign({}, inputTypeConfig.config, { label: this.panelName !== 'options' && labelHelper(labelKey), @@ -432,7 +436,7 @@ export default class EditPanelItem { }) inputTypeConfig.attrs = Object.assign({}, inputTypeConfig.attrs, { - name: inputTypeConfig.attrs.type === 'checkbox' ? `${id}[]` : id, + name: inputTypeConfig.attrs.type === 'checkbox' ? `${name}[]` : name, id, disabled: this.isDisabled, locked: this.isLocked, diff --git a/src/js/components/fields/edit-panel-item.spec.js b/src/js/components/fields/edit-panel-item.spec.js index d8e19ded..56ef6168 100644 --- a/src/js/components/fields/edit-panel-item.spec.js +++ b/src/js/components/fields/edit-panel-item.spec.js @@ -10,12 +10,12 @@ const mockField = { describe('EditPanelItem', () => { it('should match attribute item snapshot', () => { - const item = new EditPanelItem('attrs.type', { type: 'checkbox' }, mockField) + const item = new EditPanelItem({ key: 'attrs.type', data: { type: 'checkbox' }, field: mockField }) expect(item).toMatchSnapshot() }) it('should match option snapshot', () => { const itemData = { label: 'Checkbox 1', value: 'checkbox-1', checked: false } - const item = new EditPanelItem('options.0', itemData, mockField) + const item = new EditPanelItem({ key: 'options.0', data: itemData, index: 0, field: mockField }) expect(item).toMatchSnapshot() }) }) diff --git a/src/js/components/fields/edit-panel.js b/src/js/components/fields/edit-panel.js index 0307e77c..c3c5d5aa 100644 --- a/src/js/components/fields/edit-panel.js +++ b/src/js/components/fields/edit-panel.js @@ -48,7 +48,7 @@ export default class EditPanel { const itemKey = [this.name, isArray ? String(index) : data[0]].join('.') const itemData = isArray ? data : { [data[0]]: data[1] } - return new EditPanelItem(itemKey, itemData, this.field) + return new EditPanelItem({ key: itemKey, data: itemData, field: this.field }) }) const editGroupConfig = { tag: 'ul', @@ -138,7 +138,7 @@ export default class EditPanel { this.field.set(`attrs.${attr}`, val) const existingAttr = this.props.querySelector(`.field-attrs-${safeAttr}`) - const newAttr = new EditPanelItem(itemKey, { [safeAttr]: val }, this.field) + const newAttr = new EditPanelItem({ key: itemKey, data: { [safeAttr]: val }, field: this.field }) if (existingAttr) { this.props.replaceChild(newAttr.dom, existingAttr) @@ -161,7 +161,12 @@ export default class EditPanel { const optionTemplate = fieldOptionData.length ? cleanObj(fieldOptionData[fieldOptionData.length - 1]) : {} const itemData = Object.assign({}, optionTemplate, { label: newOptionLabel, value: hyphenCase(newOptionLabel) }) - const newOption = new EditPanelItem(itemKey, itemData, this.field) + const newOption = new EditPanelItem({ + key: itemKey, + data: itemData, + field: this.field, + index: this.props.children.length, + }) this.editPanelItems.push(newOption) this.props.appendChild(newOption.dom) @@ -173,7 +178,7 @@ export default class EditPanel { const currentConditions = this.field.get('conditions') const itemKey = `conditions.${currentConditions.length}` const existingCondition = this.props.querySelector(`.field-${itemKey.replace('.', '-')}`) - const newCondition = new EditPanelItem(itemKey, evt.template, this.field) + const newCondition = new EditPanelItem({ key: itemKey, data: evt.template, field: this.field }) if (existingCondition) { this.props.replaceChild(newCondition.dom, existingCondition) diff --git a/src/js/components/fields/field.js b/src/js/components/fields/field.js index f7e9efd0..9755dfab 100644 --- a/src/js/components/fields/field.js +++ b/src/js/components/fields/field.js @@ -3,7 +3,7 @@ import startCase from 'lodash/startCase' import throttle from 'lodash/throttle' import dom from '../../common/dom' import Panels from '../panels' -import { indexOfNode } from '../../common/helpers' +// import { indexOfNode } from '../../common/helpers' import { clone, unique } from '../../common/utils' import EditPanel from './edit-panel' import Component from '../component' @@ -269,12 +269,12 @@ export default class Field extends Component { const { checked, type } = target // @todo these kind of events should be added to control definitions if (['checkbox', 'radio'].includes(type)) { - const optionIndex = indexOfNode(target) - const options = this.get('options') + const optionIndex = +target.id.split('-').pop() // uncheck options if radio if (type === 'radio') { - options.forEach(({ selected }) => (selected = false)) + this.set('options', this.get('options').map(option => ({ ...option, selected: false }))) } + const checkType = type === 'checkbox' ? 'checked' : 'selected' this.set(`options.${optionIndex}.${checkType}`, checked) }