Giter Club home page Giter Club logo

Comments (9)

bmv437 avatar bmv437 commented on September 27, 2024

Hey @adberard!

Thanks for your questions and interest. I took a look at your codesandbox and the questions in your comments, and compiled a list of answers below.

Here a an updated version of your codesandbox to follow along:
https://codesandbox.io/s/4qy8v0ony9


QUESTION:
I had to comment injectGenProps in order to use my own validate function,
but then the required key in the field objects became useless,
how can I still use the required key instead of writing which components
are required in my validate.js:3

It looks like the reason that you wanted to use a custom validate function was because you wanted to use a regex to validate the email, right? If that is the case, there is good news, because redux-form-gen supports custom validation by using our conditional operators. I just noticed that I forgot to add the conditionalValid field property to the docs, but I've taken a note to add it. We have a regex operator that will compare the value against the regex during validation. It would look something like this:

{
  type: "text",
  formType: "email",
  questionId: "email",
  label: "Email",
  required: true,
  conditionalValid: {
    regex: "^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}$"
  }
}

Within the customFieldTypes.js for the password field type, you asked:

// QUESTION is there other components that I should nullify ?

Here is a link to the source for genericFieldProps()

It essentially boils down to:

export const genericFieldProps = ({field}) => ({
  _genFieldComponent: Field,
  _genLabelComponent: GenericRequiredLabel,
  name: field.questionId
});

Because the TextField for material-ui has the input, label, and required indicator built in, you wouldn't need the _genLabelComponent. There shouldn't be anything else you need to nullify.


QUESTION:
How would I wrap childFields in a FormSection from react redux ?

You can extend the section field type to render a <FieldSection /> component from redux-form, but after trying to implement an example for you I think it may be a little more detailed that I originally thought. Let me whip something up for that and answer it in issue #23.


Thanks you so much for your questions, and let me know if you have any feedback as well. I have lots of ideas for features and improvements to the field type API, and look forward to hearing any suggestions you may have.

from redux-form-gen.

adelin-b avatar adelin-b commented on September 27, 2024

Im the one thanking you so much for your really quick and detailed answers !
But If you like questions I may still have some that rised up.

How can I set my own custom message for precise errors in field ? I need this because im planning on doing some multi-languages.

How can I put my own function into validate (which would my global state for coherent dates for examples)

I really look forward #23, I tryed to play around but Im not getting everything about how childrens are generated with _gencomponent !

from redux-form-gen.

adelin-b avatar adelin-b commented on September 27, 2024

I played a bit the SectionField that you started to write and it seem that validation with nested component like this isnt going to work. Even when using my own validate.js its not very simple, ive read that redux form v8 will enhance validation

from redux-form-gen.

bmv437 avatar bmv437 commented on September 27, 2024

How can I set my own custom message for precise errors in field ? I need this because im planning on doing some multi-languages.

You can use the requiredMessage and invalidMessage to overwrite the message used for that field. here's an example:

{
  type: 'text',
  questionId: 'Name',
  conditionalValid: {
    minLength: 2
  },
  invalidMessage: 'Must be at least two characters'
}

If you're planning on using a multi-language framework, such as react-intl, you could make your invalidMessage the message id for your defined messages in react-intl instead of an actual error message. Then you would expect the meta.error that comes down from redux-form to be a message id and would run formatMessage(formMessages[error]).

something like this:

// the field
{
  type: 'text',
  questionId: 'Name',
  conditionalValid: {
    minLength: 2
  },
  invalidMessage: 'minTwoChars' // the message id from defineMessages
}

// messages
import {defineMessages} from 'react-intl';
const formMessages = defineMessages({
  minTwoChars: {
    id: 'formMessages.minTwoChars',
    description: 'Form error message for min two characters',
    defaultMessage: 'Must be at least two characters'
  }
});


// field component
import {injectIntl} from 'react-intl';
const TextField = injectIntl(({intl: {formatMessage}, meta, ...props}) => (
  <Input
    {...props.input}
    error={meta.touched && meta.invalid && formatMessage(formMessages[meta.error])}
  />
));

How can I put my own function into validate (which would my global state for coherent dates for examples)

Not sure what you mean exactly. If you want to provide a custom validate function in addition to having injectGenProps do validation, you can pass it like this:

const MyForm = injectGenProps(
  reduxForm({
    form: 'exampleForm',
    onSubmit
    // don't pass validate here, since it will get overridden by injectGenProps. you need to pass it above injectGenProps
  })(MyFields)
);

const customValidate = (formValues) => {
  // do some custom validation here, and return an errors object
};

const App = () => (
  <Provider store={store}>
    {/* pass a custom validate function here: */}
    <MyForm fields={fields} customFieldTypes={customFieldTypes} validate={customValidate} />
  </Provider>
);

This is more of a last resort if you can't build the logic you need with a conditional object. There is also the option to provide your own customOperators for use in conditional object. You can find examples of conditionalOperators here:
https://github.com/isobar-us/redux-form-gen/blob/master/src/conditionalUtils.js#L39


I really look forward #23, I tryed to play around but Im not getting everything about how childrens are generated with _gencomponent !

Let me see if I can explain:

The <FormGenerator /> runs through the list of fields and recursively renders <GenField /> components for each field. GenField handles the rendering of childFields internally so that each field component implementation doesn't have to be concerned about it. Also of note, childFields are not actually rendered as children react nodes, but as siblings to the field. The parent/child relationship was more referring to the visibly/hidden relationship that parents and children have. If a parent field is hidden, so are it's children.

If you do want to render the childFields inside of your _genComponent (as is the case for a FormSection, There is an override to have GenField skip rendering of childFields by passing _genSkipChildren: true in the field type definition. Then in your _genComponent you can read the field.childFields from props, and map over them to render <GenField field={field} /> for each field.


I played a bit the SectionField that you started to write and it seem that validation with nested component like this isnt going to work. Even when using my own validate.js its not very simple, ive read that redux form v8 will enhance validation

After digging around a bit, I realized that the issues we're seeing around the FormSection and validation stem from bugs in the way the pathPrefix is handled in the validation of conditional objects. There's a larger discussion to be had in how to fix this, and I have some ideas I've been working on.

In the meantime, I realized you can work around it by prefixing your questionId's individually, instead of using a FormSection + questionId at the section level.

{
  type: 'section',
  label: 'Step 1',
  childFields: [
    {
      type: 'text',
      inputType: 'email',
      // questionId's have been prefixed with "parent."
      questionId: 'parent.email',
      label: 'Email',
      required: true,
      conditionalValid: {
        regex: '^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}$'
      }
    },
    {
      type: 'text',
      inputType: 'text',
      questionId: 'parent.firstName',
      label: 'First Name',
      required: true
    },
    {
      type: 'text',
      inputType: 'text',
      questionId: 'parent.secondName',
      label: 'Second Name'
    },
    {
      type: 'password',
      questionId: 'parent.password',
      inputType: 'password',
      label: 'Password',
      required: true
    }
  ]
}

from redux-form-gen.

adelin-b avatar adelin-b commented on September 27, 2024

Thank you again for your super detailled explanations !
I didnt saw customValidation examples so I didnt knew how to use it. I was more thinking about putting the function in the field object directly.

   {
      type: 'password',
      questionId: 'parent.password',
      inputType: 'password',
      label: 'Password',
      required: true,
      validate: (value) => {
                             ...  
       }
    }

I figured out how to use the childrenFields finally and I kept on adding components
https://codesandbox.io/s/j4n568lo5
I created a stepper field. But im now stuck at creating checkboxes as you can test the input value isnt the correct one and I fail to understand why. (CheckboxField.js)

from redux-form-gen.

bmv437 avatar bmv437 commented on September 27, 2024

Wow, that stepper field type is impressive! Really creative way to implement a stepped wizard.


I didnt saw customValidation examples so I didnt knew how to use it. I was more thinking about putting the function in the field object directly.

Ah, I see what you mean. We've stuck to a JSON-compatible field structure in order to make sure the field structure could be requested from a back-end, since you can't describe a function in JSON. That's also the reasoning behind the conditional object API, for things like conditionalVisible, conditionalValid, conditionalDisabled, and conditionalRequired, as well as the customOperators API so you can define your own operators for custom logic like date comparisons for example.

From what I can tell, all the logic that you have in your validate function can be described as a conditionalValid property, with custom messages like I described above. For example:
requiredMessage: 'Champs requis'
invalidMessage: 'Addresse Email invalide'


But im now stuck at creating checkboxes as you can test the input value isnt the correct one and I fail to understand why. (CheckboxField.js)

Are you trying to create a single checkbox field? or more like a checkbox list, where you can select multiple options?

Checkbox Lists can work like a list. the value of the checkboxList can be an array, where all the values of the selected options will appear in the array. you can use a custom onClick on the rendered checkbox input to add/remove values from the array. Since you always want the value to be an array, you can use _genDefaultValue: [], so the generator will populate it be default.

const checkboxListType = ({ field, ...options }) => ({
  ...genericFieldProps({ field, ...options }),
  _genDefaultValue: [],
  component: CheckboxListField,
  options: field.options
});

Single Checkboxes can be tricky in forms. Since it can only have two states, true or false. If it comes in as null/undefined/"" and gets checked (set to true), and then unchecked (set to false), it breaks the dirty/pristine state of redux-form. For this case, we have a concept of _genDefaultValue which will ensure that default values are filled when the form first boots up. For a checkbox, the default value can be set to false, and we provide a custom _genIsFilled to tell the generator that this field is filled out when the value === true. Try this out:

const checkboxType = ({ field, ...options }) => ({
  ...genericFieldProps({ field, ...options }),
  _genDefaultValue: false,
  _genIsFilled: ({ data, field }) => _.get(data, field.questionId) === true,
  component: CheckboxField
});

As a note, if you don't use injectGenProps, you won't get default values from _genDefaultValue since that happens inside there and is passed to the form as initialValues.

from redux-form-gen.

adelin-b avatar adelin-b commented on September 27, 2024

Thanx again for explanation, but still ended up pulling my hair off on the checkbox list.

So I tryed to use _genDefaultValue, but once inside the component I cant find how to bind the list of checkbox to the value of the form. I need to use objects instead of array (because their key->value never change when you remove or insert an element).

Can you help me making a basic working checkbox list component ?
something like

{
        type: "checkbox",
        questionId: "DevModel",
        options: [
          { label: "Up", value: "1" },
          { label: "Down", value: "2" },
          { label: "Middle", value: "3" }
        ]
},

Would submit a value like :

 DevModel: {
          up: true,
          down: false,
          middle: true
        }

Also with an onclick event that only modify values I dont think that box would appear checked when I will need to inject initialvalue in reduxForm(MyForm) in the futur.... I really need to get how you change the input. Im looking at the radio component (https://github.com/isobar-us/redux-form-gen/blob/master/src/defaultFieldTypes/components/RadioField.js) too see how you implemented having bunch of inputs in one 1 group but didnt managed to get something working.

Here is my latest attempt
https://codesandbox.io/s/j4n568lo5?module=%2Fsrc%2FCheckboxField.js

from redux-form-gen.

bmv437 avatar bmv437 commented on September 27, 2024

Here's a working example with the CheckboxField.
https://codesandbox.io/s/wy23z9lv9w?module=%2Fsrc%2FCheckboxField.js

A quick list of some changes:

  • CheckboxField.js
    • modified props to <Checkbox /> to include checked
    • updated logic in custom this.onChange handler
  • customFieldTypes.js
    • modified the _genDefaultValue for the checkbox type to build the value object you were looking for instead of an array
  • index.js
    • wrapped reduxForm in injectGenProps HOC
    • moved the custom validate function to be a prop of <MyForm />.
    • added customFieldTypes as a prop of <MyForm />. injectGenProps needs this in order to pickup your _genDefaultValue and inject the proper initialValues into redux form.

from redux-form-gen.

adelin-b avatar adelin-b commented on September 27, 2024

Your help is precious, I was far to get the logic of it. I will keep on adding materials components :)

from redux-form-gen.

Related Issues (13)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.