formik#getIn JavaScript Examples

The following examples show how to use formik#getIn. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: utils.js    From frontend-app-discussions with GNU Affero General Public License v3.0 7 votes vote down vote up
/**
 * Return true if a field has been modified and is no longer valid
 * @param {string} field Name of field
 * @param {{}} errors formik error object
 * @param {{}} touched formik touched object
 * @returns {boolean}
 */
export function isFormikFieldInvalid(field, {
  errors,
  touched,
}) {
  return Boolean(getIn(touched, field) && getIn(errors, field));
}
Example #2
Source File: DocumentRequestForm.js    From react-invenio-app-ils with MIT License 6 votes vote down vote up
constructor(props) {
    super(props);
    this.state = {
      data: {
        title: getIn(props, 'location.state.queryString', ''),
        medium: getIn(props, 'location.state.formData.medium', ''),
        ...props.location.state?.formData,
      },
    };
  }
Example #3
Source File: FormikControl.jsx    From frontend-app-course-authoring with GNU Affero General Public License v3.0 6 votes vote down vote up
function FormikControl({
  name,
  label,
  help,
  className,
  ...params
}) {
  const {
    touched, errors, handleChange, handleBlur, setFieldError,
  } = useFormikContext();
  const fieldTouched = getIn(touched, name);
  const fieldError = getIn(errors, name);
  const handleFocus = (e) => setFieldError(e.target.name, undefined);

  return (
    <Form.Group className={className}>
      {label}
      <Form.Control
        {...params}
        name={name}
        className="pb-2"
        onChange={handleChange}
        onBlur={handleBlur}
        onFocus={handleFocus}
        isInvalid={fieldTouched && fieldError}
      />
      <FormikErrorFeedback name={name}>
        <Form.Text>{help}</Form.Text>
      </FormikErrorFeedback>
    </Form.Group>
  );
}
Example #4
Source File: FormikErrorFeedback.jsx    From frontend-app-course-authoring with GNU Affero General Public License v3.0 6 votes vote down vote up
function FormikErrorFeedback({ name, children }) {
  const { touched, errors } = useFormikContext();
  const fieldTouched = getIn(touched, name);
  const fieldError = getIn(errors, name);

  return (
    <TransitionReplace>
      {fieldTouched && fieldError
        ? (
          <Form.Control.Feedback type="invalid" hasIcon={false} key={`${name}-error-feedback`}>
            {fieldError}
          </Form.Control.Feedback>
        )
        : (
          <React.Fragment key={`${name}-no-error-feedback`}>
            {children}
          </React.Fragment>
        )}
    </TransitionReplace>
  );
}
Example #5
Source File: utils.js    From frontend-app-course-authoring with GNU Affero General Public License v3.0 6 votes vote down vote up
checkFieldErrors = (touched, errors, fieldPath, propertyName) => {
  const path = fieldPath ? `${fieldPath}.${propertyName}` : propertyName;
  return Boolean(getIn(errors, path) && getIn(touched, path));
}
Example #6
Source File: utils.js    From frontend-app-course-authoring with GNU Affero General Public License v3.0 6 votes vote down vote up
errorExists = (errors, fieldPath, propertyName) => getIn(errors, `${fieldPath}.${propertyName}`)
Example #7
Source File: FormikErrorFeedback.jsx    From frontend-app-discussions with GNU Affero General Public License v3.0 6 votes vote down vote up
function FormikErrorFeedback({ name }) {
  const {
    touched,
    errors,
  } = useFormikContext();
  const fieldTouched = getIn(touched, name);
  const fieldError = getIn(errors, name);

  return (
    <TransitionReplace>
      {fieldTouched && fieldError
        ? (
          <Form.Control.Feedback type="invalid" hasIcon={false} key={`${name}-error-feedback`}>
            {fieldError}
          </Form.Control.Feedback>
        )
        : (
          <React.Fragment key={`${name}-no-error-feedback`} />
        )}
    </TransitionReplace>
  );
}
Example #8
Source File: AffiliationsField.js    From react-invenio-deposit with MIT License 5 votes vote down vote up
render() {
    const { fieldPath, selectRef } = this.props;
    return (
      <Field name={this.props.fieldPath}>
        {({ form: { values } }) => {
          return (
            <RemoteSelectField
              fieldPath={fieldPath}
              suggestionAPIUrl="/api/affiliations"
              suggestionAPIHeaders={{
                Accept: 'application/json',
              }}
              initialSuggestions={getIn(values, fieldPath, [])}
              serializeSuggestions={this.serializeAffiliations}
              placeholder={i18next.t("Search or create affiliation'")}
              label={
                <FieldLabel
                  htmlFor={`${fieldPath}.name`}
                  label={i18next.t('Affiliations')}
                />
              }
              noQueryMessage={i18next.t('Search for affiliations..')}
              allowAdditions
              clearable
              multiple
              onValueChange={({ formikProps }, selectedSuggestions) => {
                formikProps.form.setFieldValue(
                  fieldPath,
                  // save the suggestion objects so we can extract information
                  // about which value added by the user
                  selectedSuggestions
                );
              }}
              value={getIn(values, fieldPath, []).map((val) => val.name)}
              ref={selectRef}
            />
          );
        }}
      </Field>
    );
  }
Example #9
Source File: PIDField.js    From react-invenio-deposit with MIT License 5 votes vote down vote up
getFieldErrors = (form, fieldPath) => {
  return (
    getIn(form.errors, fieldPath, null) ||
    getIn(form.initialErrors, fieldPath, null)
  );
}
Example #10
Source File: LicenseField.js    From react-invenio-deposit with MIT License 5 votes vote down vote up
render() {
    const {
      label,
      labelIcon,
      fieldPath,
      uiFieldPath,
      form: { values, errors },
      move: formikArrayMove,
      push: formikArrayPush,
      remove: formikArrayRemove,
      replace: formikArrayReplace,
      required,
    } = this.props;

    const uiRights = getIn(values, uiFieldPath, []);

    return (
      <DndProvider backend={HTML5Backend}>
        <Form.Field required={required}>
          <FieldLabel
            htmlFor={fieldPath}
            icon={labelIcon}
            label={label}
          />
          <List>
            {getIn(values, fieldPath, []).map((value, index) => {
              const license = new VisibleLicense(uiRights, value, index);
              return (
                <LicenseFieldItem
                  key={license.key}
                  license={license}
                  moveLicense={formikArrayMove}
                  replaceLicense={formikArrayReplace}
                  removeLicense={formikArrayRemove}
                  searchConfig={this.props.searchConfig}
                  serializeLicenses={this.props.serializeLicenses}
                />
              );
            })}
            <LicenseModal
              searchConfig={this.props.searchConfig}
              trigger={
                <Button type="button" key="standard" icon labelPosition="left">
                  <Icon name="add" />
                  {i18next.t('Add standard')}
                </Button>
              }
              onLicenseChange={(selectedLicense) => {
                formikArrayPush(selectedLicense);
              }}
              mode="standard"
              action="add"
              serializeLicenses={this.props.serializeLicenses}
            />
            <LicenseModal
              searchConfig={this.props.searchConfig}
              trigger={
                <Button type="button" key="custom" icon labelPosition="left">
                  <Icon name="add" />
                  {i18next.t('Add custom')}
                </Button>
              }
              onLicenseChange={(selectedLicense) => {
                formikArrayPush(selectedLicense);
              }}
              mode="custom"
              action="add"
            />
          </List>
        </Form.Field>
      </DndProvider>
    );
  }
Example #11
Source File: SubjectsField.js    From react-invenio-deposit with MIT License 5 votes vote down vote up
render() {
    const {
      fieldPath,
      label,
      labelIcon,
      required,
      multiple,
      placeholder,
      clearable,
      limitToOptions,
    } = this.props;
    return (
      <GroupField className="main-group-field">
        <Form.Field width={5} className="subjects-field">
          <FieldLabel htmlFor={fieldPath} icon={labelIcon} label={label} />
          <GroupField>
            <Form.Field
              width={8}
              style={{ marginBottom: 'auto', marginTop: 'auto' }}
              className="p-0"
            >
              {i18next.t('Suggest from')}
            </Form.Field>
            <Form.Dropdown
              className="p-0"
              defaultValue={limitToOptions[0].value}
              fluid
              onChange={(event, data) => this.setState({ limitTo: data.value })}
              options={limitToOptions}
              selection
              width={8}
            />
          </GroupField>
        </Form.Field>
        <Field name={this.props.fieldPath}>
          {({ form: { values } }) => {
            return (
              <RemoteSelectField
                clearable={clearable}
                fieldPath={fieldPath}
                initialSuggestions={getIn(values, fieldPath, [])}
                multiple={multiple}
                noQueryMessage={i18next.t('Search or create subjects...')}
                placeholder={placeholder}
                preSearchChange={this.prepareSuggest}
                required={required}
                serializeSuggestions={this.serializeSubjects}
                serializeAddedValue={(value) => ({
                  text: value,
                  value: value,
                  key: value,
                  subject: value,
                })}
                suggestionAPIUrl="/api/subjects"
                onValueChange={({ formikProps }, selectedSuggestions) => {
                  formikProps.form.setFieldValue(
                    fieldPath,
                    // save the suggestion objects so we can extract information
                    // about which value added by the user
                    selectedSuggestions
                  );
                }}
                value={getIn(values, fieldPath, []).map((val) => val.subject)}
                label={
                  <label className="mobile-hidden">&nbsp;</label>
                } /** For alignment purposes */
                allowAdditions
                width={11}
              />
            );
          }}
        </Field>
      </GroupField>
    );
  }
Example #12
Source File: BlackoutDatesInput.jsx    From frontend-app-course-authoring with GNU Affero General Public License v3.0 5 votes vote down vote up
BlackoutDatesInput = ({
  value,
  type,
  label,
  fieldName,
  helpText,
  fieldClasses,
  feedbackClasses,
  formGroupClasses,
  fieldNameCommonBase,
}) => {
  const {
    handleChange, handleBlur, errors, touched,
  } = useFormikContext();

  const [inFocus, setInFocus] = useState(false);
  const fieldError = getIn(errors, `${fieldNameCommonBase}.${fieldName}`);
  const fieldTouched = getIn(touched, `${fieldNameCommonBase}.${fieldName}`);
  const isInvalidInput = Boolean(!inFocus && fieldError && fieldTouched);

  const handleFocusOut = (event) => {
    handleBlur(event);
    setInFocus(false);
  };

  return (
    <Form.Group
      controlId={`${fieldNameCommonBase}.${fieldName}`}
      className={`col ${formGroupClasses}`}
      isInvalid={isInvalidInput}
    >
      <Form.Control
        name={`${fieldNameCommonBase}.${fieldName}`}
        value={value}
        type={type}
        onChange={handleChange}
        floatingLabel={label}
        className={fieldClasses}
        onBlur={(event) => handleFocusOut(event)}
        onFocus={() => setInFocus(true)}
      />
      <FieldFeedback
        feedbackCondition={inFocus}
        errorCondition={isInvalidInput}
        errorMessage={fieldError || ''}
        feedbackMessage={helpText}
        transitionClasses="mt-1"
        feedbackClasses={feedbackClasses}
      />
    </Form.Group>
  );
}
Example #13
Source File: CreatibutorsField.js    From react-invenio-deposit with MIT License 4 votes vote down vote up
render() {
    const {
      form: { values, errors, initialErrors, initialValues },
      remove: formikArrayRemove,
      replace: formikArrayReplace,
      move: formikArrayMove,
      name: fieldPath,
      label,
      labelIcon,
      roleOptions,
      schema,
      modal,
      autocompleteNames,
      addButtonLabel,
    } = this.props;

    const creatibutorsList = getIn(values, fieldPath, []);
    const formikInitialValues = getIn(initialValues, fieldPath, []);

    const error = getIn(errors, fieldPath, null);
    const initialError = getIn(initialErrors, fieldPath, null);
    const creatibutorsError =
      error || (creatibutorsList === formikInitialValues && initialError);

    return (
      <DndProvider backend={HTML5Backend}>
        <Form.Field
          required={schema === 'creators'}
          className={creatibutorsError ? 'error' : ''}
        >
          <FieldLabel htmlFor={fieldPath} icon={labelIcon} label={label} />
          <List>
            {creatibutorsList.map((value, index, array) => {
              const key = `${fieldPath}.${index}`;
              const identifiersError =
                creatibutorsError &&
                creatibutorsError[index]?.person_or_org?.identifiers;
              const displayName = creatibutorNameDisplay(value);

              return (
                <CreatibutorsFieldItem
                  key={key}
                  identifiersError={identifiersError}
                  {...{
                    displayName,
                    index,
                    roleOptions,
                    schema,
                    compKey: key,
                    initialCreatibutor: value,
                    removeCreatibutor: formikArrayRemove,
                    replaceCreatibutor: formikArrayReplace,
                    moveCreatibutor: formikArrayMove,
                    addLabel: modal.addLabel,
                    editLabel: modal.editLabel,
                    autocompleteNames: autocompleteNames,
                  }}
                />
              );
            })}
            <CreatibutorsModal
              onCreatibutorChange={this.handleOnContributorChange}
              action="add"
              addLabel={modal.addLabel}
              editLabel={modal.editLabel}
              roleOptions={sortOptions(roleOptions)}
              schema={schema}
              autocompleteNames={autocompleteNames}
              trigger={
                <Button type="button" icon labelPosition="left">
                  <Icon name="add" />
                  {addButtonLabel}
                </Button>
              }
            />
            {creatibutorsError && typeof creatibutorsError == 'string' && (
              <Label pointing="left" prompt>
                {creatibutorsError}
              </Label>
            )}
          </List>
        </Form.Field>
      </DndProvider>
    );
  }
Example #14
Source File: FundingField.js    From react-invenio-deposit with MIT License 4 votes vote down vote up
function FundingFieldForm(props) {
  const {
    label,
    labelIcon,
    fieldPath,
    form: { values },
    move: formikArrayMove,
    push: formikArrayPush,
    remove: formikArrayRemove,
    replace: formikArrayReplace,
    required,
  } = props;

  const deserializeAward = props.deserializeAward
    ? props.deserializeAward
    : (award) => ({
        title: award?.title_l10n,
        number: award.number,
        funder: award.funder ?? '',
        id: award.id,
        ...(award.identifiers && { identifiers: award.identifiers }),
        ...(award.acronym && { acronym: award.acronym }),
      });

  const deserializeFunder = props.deserializeFunder
    ? props.deserializeFunder
    : (funder) => ({
        id: funder.id,
        name: funder.name,
        ...(funder.pid && { pid: funder.pid }),
        ...(funder.country && { country: funder.country }),
        ...(funder.identifiers && { identifiers: funder.identifiers }),
      });

  const computeFundingContents = props.computeFundingContents
    ? props.computeFundingContents
    : (funding) => {
        let headerContent,
          descriptionContent = '';
        let awardOrFunder = 'award';
        if (funding.award) {
          headerContent = funding.award.title;
        }

        if (funding.funder) {
          const funderName =
            funding?.funder?.name ??
            funding.funder?.title ??
            funding?.funder?.id ??
            '';
          descriptionContent = funderName;
          if (!headerContent) {
            awardOrFunder = 'funder';
            headerContent = funderName;
            descriptionContent = '';
          }
        }

        return { headerContent, descriptionContent, awardOrFunder };
      };
  return (
    <DndProvider backend={HTML5Backend}>
      <Form.Field required={required}>
        <FieldLabel
          htmlFor={fieldPath}
          icon={labelIcon}
          label={label}
        ></FieldLabel>
        <List>
          {getIn(values, fieldPath, []).map((value, index, array) => {
            const arrayPath = fieldPath;
            const indexPath = index;
            const key = `${arrayPath}.${indexPath}`;
            // if award does not exist or has no id, it's a custom one
            const awardType = value?.award?.id ? 'standard' : 'custom';
            return (
              <FundingFieldItem
                key={key}
                {...{
                  index,
                  compKey: key,
                  fundingItem: value,
                  awardType,
                  moveFunding: formikArrayMove,
                  replaceFunding: formikArrayReplace,
                  removeFunding: formikArrayRemove,
                  searchConfig: props.searchConfig,
                  computeFundingContents: computeFundingContents,
                  deserializeAward: deserializeAward,
                  deserializeFunder: deserializeFunder,
                }}
              />
            );
          })}
          <FundingModal
            searchConfig={props.searchConfig}
            trigger={
              <Button type="button" key="custom" icon labelPosition="left" className="mb-5">
                <Icon name="add" />
                {i18next.t('Add award')}
              </Button>
            }
            onAwardChange={(selectedFunding) => {
              formikArrayPush(selectedFunding);
            }}
            mode="standard"
            action="add"
            deserializeAward={deserializeAward}
            deserializeFunder={deserializeFunder}
            computeFundingContents={computeFundingContents}
          />
          <FundingModal
            searchConfig={props.searchConfig}
            trigger={
              <Button type="button" key="custom" icon labelPosition="left">
                <Icon name="add" />
                {i18next.t('Add custom')}
              </Button>
            }
            onAwardChange={(selectedFunding) => {
              formikArrayPush(selectedFunding);
            }}
            mode="custom"
            action="add"
            deserializeAward={deserializeAward}
            deserializeFunder={deserializeFunder}
            computeFundingContents={computeFundingContents}
          />
        </List>
      </Form.Field>
    </DndProvider>
  );
}
Example #15
Source File: AddTelephone.js    From AED-Map with MIT License 4 votes vote down vote up
AddTelephone = ({
  className,
  formik: {
    values: { phone },
    errors,
    touched,
    handleBlur,
    setFieldValue
  }
}) => {
  const classes = useStyles();
  return (
    <div>
      <p className={classes.title}>Ваш номер телефону</p>

      <FieldArray
        name="phone"
        render={arrayHelpers => (
          <div className={classes.numbersGroup}>
            {phone &&
              phone.length > 0 &&
              phone.map((phone, index) => {
                const errorMessage = getIn(
                  errors,
                  `phone[${index}]`
                );
                const isTouched = getIn(
                  touched,
                  `phone[${index}]`
                );
                return (
                  // eslint-disable-next-line react/no-array-index-key
                  <div key={index}>
                    <MuiPhoneNumber
                      name={`phone[${index}]`}
                      className={className}
                      value={phone}
                      onChange={value =>
                        setFieldValue(
                          `phone[${index}]`,
                          value
                        )
                      }
                      onBlur={handleBlur}
                      defaultCountry="ua"
                      regions="europe"
                      helperText={
                        errorMessage &&
                        isTouched &&
                        errorMessage
                      }
                      error={errorMessage && isTouched}
                      InputProps={{
                        endAdornment: (
                          <InputAdornment
                            position="end"
                            onClick={() =>
                              arrayHelpers.remove(index)
                            }
                          >
                            <IconButton
                              color="secondary"
                              aria-label="delete phone"
                            >
                              <DeleteIcon fontSize="small" />
                            </IconButton>
                          </InputAdornment>
                        )
                      }}
                    />
                  </div>
                );
              })}
            <div className={classes.centered}>
              <IconButton
                color="primary"
                aria-label="add phone"
                onClick={() =>
                  arrayHelpers.insert(phone.length, '')
                }
              >
                <AddCircleIcon fontSize="large" />
              </IconButton>
            </div>
          </div>
        )}
      />
    </div>
  );
}