diff --git a/docs/formRender/actions/clear.md b/docs/formRender/actions/clear.md index c3d4dca4f..70e072cc3 100644 --- a/docs/formRender/actions/clear.md +++ b/docs/formRender/actions/clear.md @@ -3,15 +3,18 @@ Clears all user data from the form, even tinyMCE. ## Usage -
const formRenderOptions = {
+```javascript
+const formRenderOptions = {
formData: '[{"type":"text","label":"Text Field","name":"text-1526099104236","subtype":"text"}]';
}
-const formRenderInstance = $('#render-container').formRender(formRenderOptions);
-const html = formRenderInstance('html'); // HTML DOM nodes
+const renderContainer = $('#render-container')
+const formRenderInstance = renderContainer.formRender(formRenderOptions);
+const html = renderContainer.formRender('html'); // HTML DOM nodes
const htmlString = html.outerHTML;
-
+```
// User enters data
-formRenderInstance.clear();
-// or
-$('#render-container').formRender('clear')
+
+```javascript
+$('#render-container').formRender('clear')
+```
// User entered data is cleared
diff --git a/docs/formRender/actions/html.md b/docs/formRender/actions/html.md
index 74c0d52eb..e646d54d6 100644
--- a/docs/formRender/actions/html.md
+++ b/docs/formRender/actions/html.md
@@ -3,9 +3,9 @@
To grab the rendered form's HTML complete with user entered data
## Usage
-
+```javascript
const html = $('#render-container').formRender('html'); // HTML string
-
+```
### In Action
diff --git a/docs/formRender/actions/render.md b/docs/formRender/actions/render.md
index 5acc27637..2c334cc33 100644
--- a/docs/formRender/actions/render.md
+++ b/docs/formRender/actions/render.md
@@ -1,6 +1,6 @@
# `render` action
-Programmtically render or re-render a formRender instance with new data
+Programmatically render or re-render a formRender instance with new data
Arguments
| Arg | Type | Value(s) | Default |
@@ -9,9 +9,9 @@ Arguments
| options | {Object} | override options for new render | {} |
## Usage
-const wrap = $('.render-wrap');
+```javascript
+const wrap = $('.render-wrap');
const formRender = wrap.formRender();
// then
wrap.formRender('render', formData);
-// or
-formRender.actions.render(formData)
+```
\ No newline at end of file
diff --git a/docs/formRender/actions/setData.md b/docs/formRender/actions/setData.md
index ae3d0b5a9..de2a587b8 100644
--- a/docs/formRender/actions/setData.md
+++ b/docs/formRender/actions/setData.md
@@ -3,11 +3,12 @@
Set formData *without* rendering or re-initializing formRender.
## Usage
-const wrap = $('.render-wrap');
+```javascript
+const wrap = $('.render-wrap');
const formRender = wrap.formRender();
// then
wrap.formRender('setData', formData);
-
+```
## Demo
See the Pen
diff --git a/docs/formRender/actions/userData.md b/docs/formRender/actions/userData.md index dd57335a7..7dd0182c9 100644 --- a/docs/formRender/actions/userData.md +++ b/docs/formRender/actions/userData.md @@ -4,46 +4,46 @@ The UserData option aims to enable formRender to both capture the form data befo ## Usage 1. Setup formRender with base definition as normal -var formRenderOptions = {
+```javascript
+var formRenderOptions = {
formData: '[{"type":"text","label":"Text Field","name":"text-1526099104236","subtype":"text"}]';
}
var formRenderInstance = $('#render-container').formRender(formRenderOptions);
-
+```
1. After the user has entered data into the rendered form, their data is accessible from `formRenderInstance.userData` or `$('#render-container').formRender('userData')`
-console.log(formRenderInstance.userData);
+```javascript
+console.log(formRenderInstance.userData);
// "[{"type":"text","label":"Full Name","name":"text-1526099104236","subtype":"text","userData":["John Smith"]}]"
-
+```
UserData works for autocomplete, select, checkbox-group, radio-group, text, email, color, tel, number, hidden, date, textarea, textarea-tinymce.
For fields that have an "other" option, a value that is not in the pre-defined values is assumed to be the "other" value.
-var formData = '[{"type":"checkbox-group","label":"Checkbox Group","name":"checkbox-group-1526095813035","other":true,"values":[{"label":"Option 1","value":"option-1"},{"label":"2","value":"2"}],"userData":["option-1","Bilbo \\\"baggins\\\""]}]';
+```javascript
+var formData = '[{"type":"checkbox-group","label":"Checkbox Group","name":"checkbox-group-1526095813035","other":true,"values":[{"label":"Option 1","value":"option-1"},{"label":"2","value":"2"}],"userData":["option-1","Bilbo \\\"baggins\\\""]}]';
var formRenderOptions = {formData};
-var frInstance = $('#renderMe').formRender(formRenderOptions);
+var frInstance = $('#renderMe').formRender(formRenderOptions);
+```
A common use case for userData would be to create a form, save the input data from the form into a database, and then refresh the page with the saved data. Simply stringify userData when posting.
1. Capture form data
-
-
- $.ajax({
+```javascript
+$.ajax({
type: "POST",
url: url,
data: JSON.stringify(frInstance.userData)
- });
-
-
+});
+```
2. Send the saved JSON data back into formRender to display data
-
-
- var fbOptions.formData = {SavedJsonFromDatabase};
- var frInstance = $('#renderMe').formRender(fbOptions);
-
-
+```javascript
+var fbOptions.formData = {SavedJsonFromDatabase};
+var frInstance = $('#renderMe').formRender(fbOptions);
+```
## Demo
See the Pen
diff --git a/src/js/form-render.js b/src/js/form-render.js index 86eb528b1..a83d06166 100644 --- a/src/js/form-render.js +++ b/src/js/form-render.js @@ -28,7 +28,7 @@ class FormRender { container: false, // string selector or Node element dataType: 'json', disableHTMLLabels: false, - formData: false, + formData: [], i18n: Object.assign({}, defaultI18n), messages: { formRendered: 'Form Rendered', @@ -72,12 +72,12 @@ class FormRender { } // parse any passed formData - if (!this.options.formData) { - return false + if (this.options.formData) { + this.options.formData = this.parseFormData(this.options.formData) + } else { + this.options.formData = [] } - this.options.formData = this.parseFormData(this.options.formData) - // ability for controls to have their own configuration / options of the format control identifier (type, or type.subtype): {options} control.controlConfig = options.controlConfig || {} @@ -142,7 +142,7 @@ class FormRender { /** * Clean up passed object configuration to prepare for use with the markup function * @param {Object} field - object of field configuration - * @param {number} instanceIndex - instance index + * @param {number} [instanceIndex] - instance index * @return {Object} sanitized field object */ sanitizeField(field, instanceIndex) { @@ -196,10 +196,9 @@ class FormRender { // Begin the core plugin const rendered = [] - // generate field markup if we have fields - if (opts.formData) { - // instantiate the layout class & loop through the field configuration - const engine = new opts.layout(opts.layoutTemplates, false, opts.disableHTMLLabels) + // instantiate the layout class & loop through the field configuration + const engine = new opts.layout(opts.layoutTemplates, false, opts.disableHTMLLabels) + if (opts.formData.length) { for (let i = 0; i < opts.formData.length; i++) { const fieldData = opts.formData[i] const sanitizedField = this.sanitizeField(fieldData, instanceIndex) @@ -210,33 +209,29 @@ class FormRender { rendered.push(field) } + } else { + opts.notify.warning(opts.messages.noFormData) + } - if (element) { - this.instanceContainers[instanceIndex] = element - } + if (element) { + this.instanceContainers[instanceIndex] = element + } - // if rendering, inject the fields into the specified wrapper container/element - if (opts.render && element) { - element.emptyContainer() - element.appendFormFields(rendered) - - runCallbacks() - opts.notify.success(opts.messages.formRendered) - } else { - /** - * Retrieve the html markup for a passed array of DomElements - * @param {Array} fields - array of dom elements - * @return {string} fields html - */ - const exportMarkup = fields => fields.map(elem => elem.innerHTML).join('') - formRender.markup = exportMarkup(rendered) - } + // if rendering, inject the fields into the specified wrapper container/element + if (opts.render && element) { + element.emptyContainer() + element.appendFormFields(rendered) + + runCallbacks() + opts.notify.success(opts.messages.formRendered) } else { - const noData = utils.markup('div', opts.messages.noFormData, { - className: 'no-form-data', - }) - rendered.push(noData) - opts.notify.error(opts.messages.noFormData) + /** + * Retrieve the html markup for a passed array of DomElements + * @param {Array} fields - array of dom elements + * @return {string} fields html + */ + const exportMarkup = fields => fields.map(elem => elem.innerHTML).join('') + formRender.markup = exportMarkup(rendered) } if (opts.disableInjectedStyle === true) { diff --git a/src/js/layout.js b/src/js/layout.js index bc37077aa..a1d72eae2 100644 --- a/src/js/layout.js +++ b/src/js/layout.js @@ -12,22 +12,23 @@ const processClassName = (data, field) => { if (classes && classes.length > 0) { className += ` ${classes.join(' ')}` - } - - // Now that the row- & col- types were lifted, remove from the actual input field and any child elements - if (field.classList) { - field.classList.remove(...classes) - } - //field may be a single element, dom fragment, or an array of elements - if (!Array.isArray(field)) { - field = [field] - } - field.forEach(item => item.querySelectorAll('[class*=row-],[class*=col-]').forEach(element => { - if (element.classList) { - element.classList.remove(...classes) + // Now that the row- & col- types were lifted, remove from the actual input field and any child elements + //field may be a single element, dom fragment, or an array of elements + if (!Array.isArray(field)) { + field = [field] } - })) + field.forEach(item => { + if (item.classList) { + item.classList.remove(...classes) + } + item.querySelectorAll('[class*=row-],[class*=col-]').forEach(element => { + if (element.classList) { + element.classList.remove(...classes) + } + }) + }) + } } return className diff --git a/tests/form-builder.test.js b/tests/form-builder.test.js index b9785271b..0738286f1 100644 --- a/tests/form-builder.test.js +++ b/tests/form-builder.test.js @@ -332,6 +332,23 @@ describe('FormBuilder typeUserAttrs detection', () => { input = fbWrap.find('.button-field .testAttribute-wrap label') expect(input.text()).toBe('override') }) + test('lifts bootstrap classes from field', async () => { + const fbWrap = $('