text: (window.webpackJsonp=window.webpackJsonp||[]).push([[12],{"f/mQ":function(e,n,t){"use strict";t.r(n),t.d(n,"_frontmatter",(function(){return p})),t.d(n,"default",(function(){return b}));t("5hJT"),t("W1QL"),t("K/PF"),t("t91x"),t("75LO"),t("PJhk"),t("mXGw");var o=t("/FXl"),a=t("TjRS"),i=t("oXiK"),d=t("ZFoC"),r=t("dvV4"),l=t("c5I9");t("aD51");function c(){return(c=Object.assign||function(e){for(var n=1;n<arguments.length;n++){var t=arguments[n];for(var o in t)Object.prototype.hasOwnProperty.call(t,o)&&(e[o]=t[o])}return e}).apply(this,arguments)}var p={};void 0!==p&&p&&p===Object(p)&&Object.isExtensible(p)&&!p.hasOwnProperty("__filemeta")&&Object.defineProperty(p,"__filemeta",{configurable:!0,value:{name:"_frontmatter",filename:"docz/170.dynamicFields2.mdx"}});var s={_frontmatter:p},m=a.a;function b(e){var n=e.components,t=function(e,n){if(null==e)return{};var t,o,a={},i=Object.keys(e);for(o=0;o<i.length;o++)t=i[o],n.indexOf(t)>=0||(a[t]=e[t]);return a}(e,["components"]);return Object(o.b)(m,c({},s,t,{components:n,mdxType:"MDXLayout"}),Object(o.b)("h1",{id:"dynamic-fields"},"Dynamic Fields"),Object(o.b)("p",null,"Sometimes you do not know how many fields your form should have, so you need a way to add dynamic fields on user events, e.g. on a button click if a user should decide if a new field is needed, or on a change of a field, e.g. when a field is filled a new field should appear."),Object(o.b)("h2",{id:"onclick"},"onClick"),Object(o.b)("p",null,"First off, import your components."),Object(o.b)("pre",null,Object(o.b)("code",c({parentName:"pre"},{className:"language-js"}),"import React from 'react';\nimport {\n  Form,\n  Field,\n  Button,\n} from 'react-form-package';\n")),Object(o.b)("p",null,"The next step is to create a ",Object(o.b)("inlineCode",{parentName:"p"},"class")," that will render our form."),Object(o.b)("p",null,"The state is allways handled by ",Object(o.b)("inlineCode",{parentName:"p"},"react-form-package"),", the only thing that you need todo is to handle the appearence of the form, e.g. add or remove the input."),Object(o.b)("p",null,"We need create a ",Object(o.b)("inlineCode",{parentName:"p"},"addField"),", ",Object(o.b)("inlineCode",{parentName:"p"},"removeField"),", and optionally a ",Object(o.b)("inlineCode",{parentName:"p"},"calculateAvailableId")," function. The ",Object(o.b)("inlineCode",{parentName:"p"},"calculateAvailableId")," is only nessacary if you work on non unique index-based ids so that you ensure you do not overide an existing id."),Object(o.b)("p",null,"The ",Object(o.b)("inlineCode",{parentName:"p"},"addField")," function is here to add a new Field when you click on a ",Object(o.b)("inlineCode",{parentName:"p"},"<Button />")," component."),Object(o.b)("p",null,"To update the state of the ",Object(o.b)("inlineCode",{parentName:"p"},"<Form />")," component, you need to add a ",Object(o.b)("inlineCode",{parentName:"p"},"rfpRole")," property and a ",Object(o.b)("inlineCode",{parentName:"p"},"field")," or a ",Object(o.b)("inlineCode",{parentName:"p"},"fieldId")," property to a ",Object(o.b)("inlineCode",{parentName:"p"},"<Button />")," component."),Object(o.b)("p",null,"The ",Object(o.b)("inlineCode",{parentName:"p"},"rfpRole")," takes a string which is either ",Object(o.b)("inlineCode",{parentName:"p"},"addField")," or ",Object(o.b)("inlineCode",{parentName:"p"},"removeField"),". "),Object(o.b)("p",null,"If you use the ",Object(o.b)("inlineCode",{parentName:"p"},"<Button />")," component to add a new field to the state of the form component you need to provide a ",Object(o.b)("inlineCode",{parentName:"p"},"field")," property which takes an object that represents your new ",Object(o.b)("inlineCode",{parentName:"p"},"<Field />")," component. This object has to have at least a ",Object(o.b)("inlineCode",{parentName:"p"},"id")," and a ",Object(o.b)("inlineCode",{parentName:"p"},"type"),", but you can extend this object with rules like: ",Object(o.b)("inlineCode",{parentName:"p"},"min"),", ",Object(o.b)("inlineCode",{parentName:"p"},"max"),", ",Object(o.b)("inlineCode",{parentName:"p"},"required"),", ",Object(o.b)("inlineCode",{parentName:"p"},"match"),", and ",Object(o.b)("inlineCode",{parentName:"p"},"sameAs"),"."),Object(o.b)("p",null,"If you use the ",Object(o.b)("inlineCode",{parentName:"p"},"<Button />")," component to add remove an existing field from the state of the form component you need to provide a ",Object(o.b)("inlineCode",{parentName:"p"},"fieldId")," property which takes a string: the ",Object(o.b)("inlineCode",{parentName:"p"},"id")," of the field you want to remove."),Object(o.b)("p",null,"In the state of the ",Object(o.b)("inlineCode",{parentName:"p"},"DynamicFields")," component you have to create an array where you add refrences to the fields of your dynamic ",Object(o.b)("inlineCode",{parentName:"p"},"<Field />")," components. To add new fields you need to add a new refrence, so that the part of the DOM rerenders with the new Field Component. To remove the Fields not only from the state of the ",Object(o.b)("inlineCode",{parentName:"p"},"<Form />")," component but also from the DOM, you need to remove the refrences in your state that the component rerenders that part of the DOM."),Object(o.b)("pre",null,Object(o.b)("code",c({parentName:"pre"},{className:"language-jsx"}),'class DynamicFields extends React.Component {\n  constructor(props) {\n    super(props);\n\n    this.state = {\n      // the field refrences that we use to render in our <Form /> component\n      companies: [\n        {\n          id: \'company-0\',\n        },\n      ],\n    };\n\n    this.addField = this.addField.bind(this);\n    this.removeField = this.removeField.bind(this);\n    this.calculateAvailableId = this.calculateAvailableId.bind(this);\n  }\n\n  calculateAvailableId() {\n    const {\n      companies,\n    } = this.state;\n\n    const arr = companies.map((item) => parseInt(item.id.split(\'-\')[1], 10));\n\n    let currentHighestId = Math.max(...arr);\n    currentHighestId = currentHighestId !== -Infinity ? currentHighestId : 0;\n\n    const highestAvailableId = currentHighestId + 1;\n\n    return highestAvailableId;\n  }\n\n  addField() {\n    const {\n      companies,\n    } = this.state;\n\n    const highestAvailableId = this.calculateAvailableId();\n\n    // add a new field refrence to the <Form /> component\n    this.setState({\n      companies: companies.concat({ id: `company-${highestAvailableId}` }),\n    });\n  }\n\n  removeField(idx) {\n    const {\n      companies,\n    } = this.state;\n\n    // remove a field refrence to the <Form /> component\n    this.setState({\n      companies: companies.filter((_, index) => idx !== index),\n    });\n  }\n\n  render() {\n    const {\n      companies,\n    } = this.state;\n\n    const highestAvailableId = this.calculateAvailableId();\n\n    return (\n      <Form\n        validate\n      >\n        {/* render the <Field /> components based on our field refrences */}\n        {companies.map((company, idx) => (\n          <div>\n            <Field\n              id={company.id}\n              placeholder={`Company ${company.id.split(\'-\')[1]}`}\n              type="text"\n              required\n            />\n            <Button\n              id="removeField"\n              // add the rfpRole property\n              rfpRole="removeField"\n              type="button"\n              // add the fieldId property to remove the field from the state of the <Form /> component\n              fieldId={company.id}\n              onClick={() => this.removeField(idx)}\n            >\n              Remove Company\n            </Button>\n          </div>\n        ))}\n        <div>\n          <Button\n            id="addField"\n            // add the rfpRole property\n            rfpRole="addField"\n            type="button"\n            // add the field property to add to the state state of the <Form /> component\n            field={{\n              id: `company-${highestAvailableId}`,\n              type: \'text\',\n              required: true,\n            }}\n            onClick={() => this.addField()}\n          >\n            Add Company\n          </Button>\n        </div>\n        <div>\n          <Button\n            id="submit"\n            type="submit"\n            onClick={(state) => {\n              alert(JSON.stringify(state, null, 2));\n              alert(\'open the console to see the whole state...\');\n              console.log(state);\n            }}\n          >\n            submit\n          </Button>\n        </div>\n      </Form>\n    );\n  }\n}\n\nexport { DynamicFields };\n')),Object(o.b)("p",null,"Now render this Component. Everytime you click on the button ",Object(o.b)("inlineCode",{parentName:"p"},"Add Company")," you get a new field, and everytime you click on the button ",Object(o.b)("inlineCode",{parentName:"p"},"Remove Company")," you remove the corresponding field."),Object(o.b)(d.c,{__position:0,__code:"<DynamicFieldsOnClick />",__scope:{props:t,DefaultLayout:a.a,Form:i.d,Button:i.a,Field:i.b,Select:i.f,RadioGroup:i.e,Playground:d.c,DynamicFieldsOnChange:r.a,DynamicFieldsOnClick:l.a},mdxType:"Playground"},Object(o.b)(l.a,{mdxType:"DynamicFieldsOnClick"})),Object(o.b)("h2",{id:"onchange"},"onChange"),Object(o.b)("p",null,"First off, import your components."),Object(o.b)("pre",null,Object(o.b)("code",c({parentName:"pre"},{className:"language-js"}),"import React from 'react';\nimport {\n  Form,\n  Field,\n  Button,\n} from 'react-form-package';\n")),Object(o.b)("p",null,"The next step is to create a ",Object(o.b)("inlineCode",{parentName:"p"},"class")," that will render our form. "),Object(o.b)("p",null,"Everything stays the same as in the example above, except:"),Object(o.b)("p",null,"That we now use a ",Object(o.b)("inlineCode",{parentName:"p"},"dynamic")," property and the ",Object(o.b)("inlineCode",{parentName:"p"},"field")," property on the ",Object(o.b)("inlineCode",{parentName:"p"},"<Field />")," component. the ",Object(o.b)("inlineCode",{parentName:"p"},"field")," property takes the same properties as in the ",Object(o.b)("inlineCode",{parentName:"p"},"<Button />")," component. The ",Object(o.b)("inlineCode",{parentName:"p"},"dynamic")," property indicates that this ",Object(o.b)("inlineCode",{parentName:"p"},"<Field />")," component is dynamic and adds a new field in the state of the ",Object(o.b)("inlineCode",{parentName:"p"},"<Form />")," component when this ",Object(o.b)("inlineCode",{parentName:"p"},"<Field />")," is filled."),Object(o.b)("pre",null,Object(o.b)("code",c({parentName:"pre"},{className:"language-jsx"}),"class DynamicFields extends React.Component {\n  constructor(props) {\n    super(props);\n\n    // the field refrences that we use to render in our <Form /> component\n    this.state = {\n      companies: [\n        {\n          id: 'company-0',\n        },\n      ],\n    };\n\n    this.addField = this.addField.bind(this);\n    this.removeField = this.removeField.bind(this);\n    this.calculateAvailableId = this.calculateAvailableId.bind(this);\n  }\n\n  calculateAvailableId() {\n    const {\n      companies,\n    } = this.state;\n\n    const arr = companies.map((item) => parseInt(item.id.split('-')[1], 10));\n\n    let currentHighestId = Math.max(...arr);\n    currentHighestId = currentHighestId !== -Infinity ? currentHighestId : 0;\n\n    const highestAvailableId = currentHighestId + 1;\n\n    return highestAvailableId;\n  }\n\n  addField(state, id) {\n    const {\n      companies,\n    } = this.state;\n\n    const highestAvailableId = this.calculateAvailableId();\n\n    // add a new field refrence to the <Form /> component\n    if (state.data[id] && parseInt(id.split('-')[1], 10) + 1 === highestAvailableId) {\n      this.setState({\n        companies: companies.concat({ id: `company-${highestAvailableId}` }),\n      });\n    }\n  }\n\n  removeField(idx) {\n    const {\n      companies,\n    } = this.state;\n\n    // remove a field refrence to the <Form /> component\n    this.setState({\n      companies: companies.filter((_, index) => idx !== index),\n    });\n  }\n\n  render() {\n    const {\n      companies,\n    } = this.state;\n\n    const highestAvailableId = this.calculateAvailableId();\n\n    return (\n      <Form>\n        {/* render the <Field /> components based on our field refrences */}\n        {companies.map((company, idx) => (\n          <div>\n            <Field\n              id={company.id}\n              placeholder={`Company ${company.id.split('-')[1]}`}\n              type=\"text\"\n              required\n              // add the dynamic property \n              dynamic\n              // add the field property to add to the state state of the <Form /> component\n              field={{\n                id: `company-${highestAvailableId}`,\n                type: 'text',\n                required: true,\n              }}\n              onChange={(state) => this.addField(state, company.id)}\n            />\n            {companies.length && (\n              <Button\n                id=\"removeField\"\n                // add the rfpRole property\n                rfpRole=\"removeField\"\n                type=\"button\"\n                // add the fieldId property to remove the field from the state of the <Form /> component\n                fieldId={company.id}\n                onClick={() => this.removeField(idx)}\n              >\n                Remove Company\n              </Button>\n            )}\n\n          </div>\n        ))}\n        <div>\n          <Button\n            id=\"submit\"\n            type=\"submit\"\n            onClick={(state) => {\n              alert(JSON.stringify(state, null, 2));\n              alert('open the console to see the whole state...');\n              console.log(state);\n            }}\n          >\n            submit\n          </Button>\n        </div>\n      </Form>\n    );\n  }\n}\n\nexport { DynamicFieldsOnChange };\n")),Object(o.b)("p",null,"Now render this Component. Everytime you fill out the ",Object(o.b)("inlineCode",{parentName:"p"},"<Field />")," component you will add a new ",Object(o.b)("inlineCode",{parentName:"p"},"<Field />"),", and everytime you click on the button ",Object(o.b)("inlineCode",{parentName:"p"},"Remove Company")," you remove the corresponding field."),Object(o.b)(d.c,{__position:1,__code:"<DynamicFieldsOnChange />",__scope:{props:t,DefaultLayout:a.a,Form:i.d,Button:i.a,Field:i.b,Select:i.f,RadioGroup:i.e,Playground:d.c,DynamicFieldsOnChange:r.a,DynamicFieldsOnClick:l.a},mdxType:"Playground"},Object(o.b)(r.a,{mdxType:"DynamicFieldsOnChange"})))}b&&b===Object(b)&&Object.isExtensible(b)&&!b.hasOwnProperty("__filemeta")&&Object.defineProperty(b,"__filemeta",{configurable:!0,value:{name:"MDXContent",filename:"docz/170.dynamicFields2.mdx"}}),b.isMDXComponent=!0}}]);
  //# sourceMappingURL=component---docz-170-dynamic-fields-2-mdx-49a4eb14ff46ba6301ae.js.map