diff --git a/src/js/form-builder.js b/src/js/form-builder.js index 1a03e425e..43575a211 100644 --- a/src/js/form-builder.js +++ b/src/js/form-builder.js @@ -33,7 +33,7 @@ import { safename, forceNumber, getContentType, - generateSelectorClassNames, + generateSelectorClassNames, firstNumberOrUndefined, } from './utils' import { attributeWillClobber, setElementContent, setSanitizerConfig } from './sanitizer' import fontConfig from '../fonts/config.json' @@ -682,8 +682,16 @@ function FormBuilder(opts, element, $) { if (attrValType !== 'undefined') { const orig = mi18n.get(attribute) const tUA = typeUserAttr[attribute] - const origValue = attrValType === 'boolean' ? tUA.value : (tUA.value || '') - tUA.value = values[attribute] || origValue + let origValue = tUA.value + if (attrValType === 'boolean') { + origValue = tUA.value + tUA[attribute] ??= tUA.value + } else if (attrValType === 'number') { + tUA[attribute] ??= firstNumberOrUndefined(values[attribute], origValue) + } else { + origValue ??= '' + tUA[attribute] ??= values[attribute] || origValue + } if (tUA.label) { i18n[attribute] = Array.isArray(tUA.label) ? mi18n.get(...tUA.label) || tUA.label[0] : tUA.label @@ -871,7 +879,7 @@ function FormBuilder(opts, element, $) { */ const numberAttribute = (attribute, values) => { const { class: classname, className, ...attrs } = values - const attrVal = (isNaN(attrs[attribute])) ? undefined : attrs[attribute] + const attrVal = (Number.isNaN(attrs[attribute])) ? undefined : attrs[attribute] const attrLabel = mi18n.get(attribute) || attribute const placeholder = mi18n.get(`placeholder.${attribute}`) diff --git a/src/js/utils.js b/src/js/utils.js index 20f19f31b..48ffa56cc 100644 --- a/src/js/utils.js +++ b/src/js/utils.js @@ -702,6 +702,10 @@ export function titleCase(str) { ) } +export function firstNumberOrUndefined(...options) { + return options.find(x => typeof x === 'number') +} + const utils = { addEventListeners, attrString, @@ -733,6 +737,7 @@ const utils = { unique, validAttr, titleCase, + firstNumberOrUndefined, } /** diff --git a/tests/form-builder.test.js b/tests/form-builder.test.js index af753bb83..a0addd853 100644 --- a/tests/form-builder.test.js +++ b/tests/form-builder.test.js @@ -199,6 +199,38 @@ describe('FormBuilder stage names translated', () => { }) }) +describe('FormBuilder attribute setup', () => { + test('number control number attributes do not inherit field value when not set', async() => { + const config = {} + const fbWrap = $('
') + const fb = await fbWrap.formBuilder(config).promise + fb.actions.addField({ + type: 'number', + value: '5.2', + }) + expect(fbWrap.find('.value-wrap input').val()).toBe('5.2') + expect(fbWrap.find('.min-wrap input').val()).toBe('') + expect(fbWrap.find('.max-wrap input').val()).toBe('') + expect(fbWrap.find('.step-wrap input').val()).toBe('') + }) + test('number control number attributes do not inherit field value when set', async() => { + const config = {} + const fbWrap = $('
') + const fb = await fbWrap.formBuilder(config).promise + fb.actions.addField({ + type: 'number', + value: '5.2', + min: 2, + max: 10, + step: 1.0, + }) + expect(fbWrap.find('.value-wrap input').val()).toBe('5.2') + expect(fbWrap.find('.min-wrap input').val()).toBe('2') + expect(fbWrap.find('.max-wrap input').val()).toBe('10') + expect(fbWrap.find('.step-wrap input').val()).toBe('1') + }) + +}) describe('FormBuilder typeUserAttrs detection', () => { test('renders text/string user attribute', async () => { const config = { @@ -238,6 +270,27 @@ describe('FormBuilder typeUserAttrs detection', () => { expect(input.is(':checked')).toBeFalsy() }) test('renders number user attribute when value is number', async () => { + const config = { + typeUserAttrs: { + text: { + testAttribute: { + label: 'test', + value: 10, + }, + }, + }, + } + const fbWrap = $('
') + const fb = await fbWrap.formBuilder(config).promise + fb.actions.addField({ + type: 'text', + value: '1', + }) + const input = fbWrap.find('.testAttribute-wrap input') + expect(input.attr('type')).toBe('number') + expect(input.val()).toBe('10') + }) + test('renders number user attribute when value is zero', async () => { const config = { typeUserAttrs: { text: { @@ -250,9 +303,13 @@ describe('FormBuilder typeUserAttrs detection', () => { } const fbWrap = $('
') const fb = await fbWrap.formBuilder(config).promise - fb.actions.addField({ type: 'text'}) + fb.actions.addField({ + type: 'text', + value: '1', + }) const input = fbWrap.find('.testAttribute-wrap input') expect(input.attr('type')).toBe('number') + expect(input.val()).toBe('0') }) test('renders select user attribute when options given', async () => { const config = { diff --git a/tests/utils.test.js b/tests/utils.test.js index a89b2708c..b1fcdf6d5 100644 --- a/tests/utils.test.js +++ b/tests/utils.test.js @@ -1,7 +1,7 @@ const utils = require('./../src/js/utils.js') const { safeAttr, flattenArray, safeAttrName, hyphenCase, camelCase, bindEvents, attrString, nameAttr, markup, parsedHtml, escapeAttrs, getScripts, capitalize, addEventListeners, unique, escapeAttr, escapeHtml, - getAllGridRelatedClasses, subtract, safename, xmlParseAttrs, parseXML + getAllGridRelatedClasses, subtract, safename, xmlParseAttrs, parseXML, firstNumberOrUndefined } = require('../src/js/utils') describe('Test Util functions', () => { @@ -143,6 +143,12 @@ describe('Test Util functions', () => { expect(subtract([2],[1,2,3])).toEqual([1,3]) expect(subtract(['remove-me'],['classA','classB','remove-me','classC'])).toEqual(['classA','classB','classC']) }) + + test('firstNumberOrUndefined', () => { + expect(firstNumberOrUndefined(1)).toEqual(1) + expect(firstNumberOrUndefined(1,2,3)).toEqual(1) + expect(firstNumberOrUndefined(undefined,'',2,1)).toEqual(2) + }) }) describe('Test XML functions', () => {