diff --git a/docs/formBuilder/options/typeUserAttrs.md b/docs/formBuilder/options/typeUserAttrs.md index 83200699f..427ed25df 100644 --- a/docs/formBuilder/options/typeUserAttrs.md +++ b/docs/formBuilder/options/typeUserAttrs.md @@ -64,5 +64,17 @@ const typeUserAttrs = { }; ``` +## Example Input for all types +```javascript +const typeUserAttrs = { + '*': { + title: { + label: 'Title', + value: 'Field Title', + } + } +}; +``` + ### Usage

diff --git a/docs/formBuilder/options/typeUserEvents.md b/docs/formBuilder/options/typeUserEvents.md index 896fe46dc..2a72a8463 100644 --- a/docs/formBuilder/options/typeUserEvents.md +++ b/docs/formBuilder/options/typeUserEvents.md @@ -1,6 +1,10 @@ # typeUserEvents Add functionality to existing and custom attributes using `onclone` and `onadd` events. Events return JavaScript DOM elements. +For all types the wildcard type **_*_** exists. + +`onremove` event exists for removal events + ## Usage ```javascript var options = { @@ -14,6 +18,11 @@ var options = { } }, typeUserEvents: { + '*': { + onclone: (fld) => { + console.log('field cloned'); + } + }, text: { onadd: function(fld) { var $patternField = $('.fld-pattern', fld); diff --git a/package.json b/package.json index 98982195d..6277fa74a 100644 --- a/package.json +++ b/package.json @@ -179,6 +179,7 @@ "jest": { "collectCoverage": true, "coverageDirectory": ".jest/coverage", + "coveragePathIgnorePatterns": [ "tests/" ], "testEnvironment": "jsdom", "setupFiles": [ "./tests/setup-jest.js" diff --git a/src/js/form-builder.js b/src/js/form-builder.js index faa691d63..c94a45113 100644 --- a/src/js/form-builder.js +++ b/src/js/form-builder.js @@ -608,6 +608,8 @@ function FormBuilder(opts, element, $) { const noDisable = ['name', 'className'] + const typeUserAttrs = Object.assign({}, opts.typeUserAttrs['*'], opts.typeUserAttrs[type]) + Object.keys(fieldAttrs).forEach(index => { const attr = fieldAttrs[index] const useDefaultAttr = [true] @@ -623,8 +625,8 @@ function FormBuilder(opts, element, $) { useDefaultAttr.push(!userAttrs.includes(attr)) } - if (opts.typeUserAttrs[type]) { - const userAttrs = Object.keys(opts.typeUserAttrs[type]) + if (typeUserAttrs) { + const userAttrs = Object.keys(typeUserAttrs) useDefaultAttr.push(!userAttrs.includes(attr)) } @@ -644,8 +646,8 @@ function FormBuilder(opts, element, $) { } // Append custom attributes as defined in typeUserAttrs option - if (opts.typeUserAttrs[type]) { - const customAttr = processTypeUserAttrs(opts.typeUserAttrs[type], values) + if (typeUserAttrs) { + const customAttr = processTypeUserAttrs(typeUserAttrs, values) advFields.push(customAttr) } @@ -1224,6 +1226,8 @@ function FormBuilder(opts, element, $) { if (opts.typeUserEvents[type] && opts.typeUserEvents[type].onadd) { opts.typeUserEvents[type].onadd(field) + } else if (opts.typeUserEvents['*'] && opts.typeUserEvents['*'].onadd) { + opts.typeUserEvents['*'].onadd(field) } if (isNew) { @@ -1610,6 +1614,8 @@ function FormBuilder(opts, element, $) { if (opts.typeUserEvents[type] && opts.typeUserEvents[type].onclone) { opts.typeUserEvents[type].onclone($clone[0]) + } else if (opts.typeUserEvents['*'] && opts.typeUserEvents['*'].onclone) { + opts.typeUserEvents['*'].onclone($clone[0]) } return $clone diff --git a/src/js/form-render.js b/src/js/form-render.js index 7483468f8..77851ed3c 100644 --- a/src/js/form-render.js +++ b/src/js/form-render.js @@ -50,13 +50,13 @@ class FormRender { }, templates: {}, // custom inline defined templates notify: { - error: error => { + error: /* istanbul ignore next */ error => { console.log(error) }, - success: success => { + success: /* istanbul ignore next */ success => { console.log(success) }, - warning: warning => { + warning: /* istanbul ignore next */ warning => { console.warn(warning) }, }, diff --git a/src/js/helpers.js b/src/js/helpers.js index 9bc63fd24..bf905c75f 100644 --- a/src/js/helpers.js +++ b/src/js/helpers.js @@ -1057,7 +1057,7 @@ export default class Helpers { } }) - const userEvents = config.opts.typeUserEvents[field.type] + const userEvents = Object.assign({}, config.opts.typeUserEvents['*'], config.opts.typeUserEvents[field.type]) if (userEvents && userEvents.onremove) { userEvents.onremove(field) diff --git a/tests/form-builder.test.js b/tests/form-builder.test.js index d3120f804..b50ab5a71 100644 --- a/tests/form-builder.test.js +++ b/tests/form-builder.test.js @@ -54,6 +54,74 @@ describe('FormBuilder Add/Remove from Stage', () => { fb.actions.clearFields() //Test no error on empty stage expect($('.frmb.stage-wrap li', fbWrap).length).toBe(0) }) + + test('typeUserEvents onadd called for wildcard', async () => { + const fbWrap = $('
') + const cb = jest.fn() + const fb = await $(fbWrap).formBuilder({ + typeUserEvents: { + '*': { + onadd: cb, + }, + }, + }).promise + const field = { + type: 'text', + class: 'form-control', + name: 'on-add-test' + } + fb.actions.addField(field) + expect(cb.mock.calls).toHaveLength(1) + expect(cb.mock.calls[0]).toHaveLength(1) + expect(typeof cb.mock.calls[0][0]).toBe('object') + }) + + test('typeUserEvents onadd called for type', async () => { + const fbWrap = $('
') + const cb = jest.fn() + const fb = await $(fbWrap).formBuilder({ + typeUserEvents: { + 'text': { + onadd: cb, + }, + }, + }).promise + const field = { + type: 'text', + class: 'form-control', + name: 'on-add-test' + } + fb.actions.addField(field) + expect(cb.mock.calls).toHaveLength(1) + expect(cb.mock.calls[0]).toHaveLength(1) + expect(typeof cb.mock.calls[0][0]).toBe('object') + }) + + test('typeUserEvents onadd called for type when wildcard and type keys exist', async () => { + const fbWrap = $('
') + const cbType = jest.fn() + const cbWildcard = jest.fn() + const fb = await $(fbWrap).formBuilder({ + typeUserEvents: { + '*': { + onadd: cbWildcard, + }, + 'text': { + onadd: cbType, + }, + }, + }).promise + const field = { + type: 'text', + class: 'form-control', + name: 'on-add-test' + } + fb.actions.addField(field) + expect(cbType.mock.calls).toHaveLength(1) + expect(cbType.mock.calls[0]).toHaveLength(1) + expect(typeof cbType.mock.calls[0][0]).toBe('object') + expect(cbWildcard.mock.calls).toHaveLength(0) + }) }) describe('FormBuilder can add all default fields via clicking on control panel', () => { @@ -131,7 +199,7 @@ describe('FormBuilder stage names translated', () => { }) }) -describe('FormBuilder userAttrType detection', () => { +describe('FormBuilder typeUserAttrs detection', () => { test('renders text/string user attribute', async () => { const config = { typeUserAttrs: { @@ -207,6 +275,64 @@ describe('FormBuilder userAttrType detection', () => { expect(input.length).toBe(1) expect(input[0].options.length).toBe(2) }) + test('renders text/string user attribute when set by wildcard', async () => { + const config = { + typeUserAttrs: { + '*': { + testAttribute: { + label: 'test', + value: '', + }, + }, + }, + } + const fbWrap = $('
') + const fb = await fbWrap.formBuilder(config).promise + fb.actions.addField({ type: 'text'}) + let input = fbWrap.find('.text-field .testAttribute-wrap input') + expect(input.attr('type')).toBe('text') + expect(input.val()).toBe('') + fb.actions.addField({ type: 'button'}) + input = fbWrap.find('.button-field .testAttribute-wrap input') + expect(input.attr('type')).toBe('text') + expect(input.val()).toBe('') + }) + test('user attribute definition by type takes precedence over wildcard definition', async () => { + const config = { + typeUserAttrs: { + '*': { + testAttribute: { + label: 'test', + value: '', + }, + }, + button: { + testAttribute: { + label: 'override', + value: 'buttonOverride', + }, + }, + }, + } + const fbWrap = $('
') + const fb = await fbWrap.formBuilder(config).promise + fb.actions.addField({ type: 'text'}) + let input = fbWrap.find('.text-field .testAttribute-wrap input') + expect(input.attr('type')).toBe('text') + expect(input.val()).toBe('') + + input = fbWrap.find('.text-field .testAttribute-wrap label') + expect(input.text()).toBe('test') + + fb.actions.addField({ type: 'button'}) + input = fbWrap.find('.button-field .testAttribute-wrap input') + console.log(input) + expect(input.attr('type')).toBe('text') + expect(input.val()).toBe('buttonOverride') + + input = fbWrap.find('.button-field .testAttribute-wrap label') + expect(input.text()).toBe('override') + }) }) describe('FormBuilder can return formData', () => {