Esempio n. 1
0
function getFieldFromState(state, model) {
  const form = getForm(state, toPath(model)[0]);

  if (!form) return null;

  return getField(form, toPath(model).slice(1));
}
Esempio n. 2
0
          persistKeys.forEach((persistKey) => {
            const newPersistKeyPath = toPath(persistKey);
            const currentIndex = newPersistKeyPath[localPath.length];
            const mappedIndex = persistKeysIndexMapping[currentIndex];

            if (typeof mappedIndex !== 'undefined') {
              newPersistKeyPath[localPath.length] = mappedIndex;
            } else {
              newPersistKeyPath[localPath.length] =
                persistKeysIndexMapping[currentIndex] =
                ++nextIndex;
            }

            const persistField = getField(state, persistKey);

            // Remove old key
            setFieldDirtyState = icepick.updateIn(
              setFieldDirtyState,
              ['fields'],
              (field) => icepick.dissoc(field, persistKey));

            // Update field to new key
            setFieldDirtyState = setInField(
              setFieldDirtyState,
              newPersistKeyPath,
              persistField);
          });
Esempio n. 3
0
export default function combinePath(...paths) {
    const combinedPath = [];
    for (const path of paths) {
        const pathArray = isArrayLike(path) && typeof path !== 'string'
            ? toArray(path)
            : toPath(path);
        combinedPath.push(...pathArray)
    }
    return combinedPath;
}
Esempio n. 4
0
  return function _createModelReducer(model, initialState = initialModelState) {
    const modelPath = toPath(model);

    return (state = initialState, action) => {
      if (!action.model) {
        return state;
      }

      const path = toPath(action.model);

      if (!isEqual(path.slice(0, modelPath.length), modelPath)) {
        return state;
      }

      const localPath = path.slice(modelPath.length);

      switch (action.type) {
        case actionTypes.CHANGE:
          if (!localPath.length) {
            return action.value;
          }

          if (isEqual(getter(state, localPath), action.value)) {
            return state;
          }

          return setter(state, localPath, action.value);

        case actionTypes.RESET:
          if (!localPath.length) {
            return initialState;
          }

          if (isEqual(getter(state, localPath), getter(initialState, localPath))) {
            return state;
          }

          return setter(
            state,
            localPath,
            getter(initialState, localPath)
          );

        default:
          return state;
      }
    };
  };
function getField(state, path) {
  if (!isPlainObject(state) || !state.fields) {
    throw new Error(`Error when trying to retrieve field '${path}' from an invalid/empty form state. Must pass in a valid form state as the first argument.`);
  }

  const localPath = toPath(path);

  if (!localPath.length) {
    return state;
  }

  return get(
    state,
    ['fields', localPath.join('.')],
    initialFieldState);
}
Esempio n. 6
0
          persistKeys.forEach((persistKey, index) => {
            const newPersistKeyPath = toPath(persistKey);
            newPersistKeyPath[localPath.length] = index;

            const persistField = getField(state, persistKey);

            // Remove old key
            setFieldDirtyState = icepick.updateIn(
              setFieldDirtyState,
              ['fields'],
              (field) => icepick.dissoc(field, persistKey));

            // Update field to new key
            setFieldDirtyState = setInField(
              setFieldDirtyState,
              newPersistKeyPath,
              persistField);
          });
Esempio n. 7
0
export const setProperty = (state, action) => {
    if (action.type === SET_PROPERTY) {
        return setIn(state, toPath(action.path), action.value);
    }
    return state;
};
  return (state = createInitialFormState(model), action) => {
    if (!action.model) return state;

    const path = toPath(action.model);

    if (!isEqual(path.slice(0, modelPath.length), modelPath)) {
      return state;
    }

    const localPath = path.slice(modelPath.length);

    switch (action.type) {
      case actionTypes.FOCUS:
        return setField(state, localPath, {
          focus: true,
          blur: false
        });

      case actionTypes.CHANGE:
      case actionTypes.SET_DIRTY:
        state = icepick.merge(state, {
          dirty: true,
          pristine: false,
        });

        return setField(state, localPath, {
          dirty: true,
          pristine: false
        });

      case actionTypes.BLUR:
      case actionTypes.SET_TOUCHED:
        return setField(state, localPath, {
          touched: true,
          untouched: false,
          focus: false,
          blur: true
        });

      case actionTypes.SET_PENDING:
        return setField(state, localPath, {
          pending: action.pending,
          submitted: false
        });

      case actionTypes.SET_VALIDITY:
        const errors = isPlainObject(action.validity)
          ? {
              ...getField(state, localPath).errors,
              ...mapValues(action.validity, (valid) => !valid)
            }
          : !action.validity;

        state = setField(state, localPath, {
          errors,
          valid: isBoolean(errors)
            ? errors
            : every(errors, (error) => !error)
        });

        return icepick.merge(state, {
          valid: every(mapValues(state.fields, (field) => field.valid))
            && every(state.errors, (error) => !error)
        });

      case actionTypes.SET_PRISTINE:
        state = setField(state, localPath, {
          dirty: false,
          pristine: true
        });

        const formIsPristine = every(mapValues(state.fields, (field) => field.pristine));

        return icepick.merge(state, {
          pristine: formIsPristine,
          dirty: !formIsPristine
        });

      case actionTypes.SET_UNTOUCHED:
        return setField(state, localPath, {
          touched: false,
          untouched: true
        });

      case actionTypes.SET_SUBMITTED:
        return setField(state, localPath, {
          pending: false,
          submitted: !!action.submitted
        });

      case actionTypes.SET_INITIAL:
      case actionTypes.RESET:
        return resetField(state, localPath);

      case actionTypes.SET_VIEW_VALUE:
        return setField(state, localPath, {
          viewValue: action.value
        });

      default:
        return state;
    }
  };
Esempio n. 9
0
  const formReducer = (state = localInitialFormState, action) => {
    if (!action.model) {
      return state;
    }

    const path = toPath(action.model);

    if (!isEqual(path.slice(0, modelPath.length), modelPath)) {
      return state;
    }

    const localPath = path.slice(modelPath.length);
    let errors;
    let validity;

    switch (action.type) {
      case actionTypes.BATCH:
        return action.actions.reduce(formReducer, state);

      case actionTypes.FOCUS:
        return setField(state, localPath, {
          blur: false, // will be deprecated
          focus: true,
          array: Array.isArray(action.value),
        });

      case actionTypes.CHANGE: {
        if (action.silent) return state;

        let setFieldDirtyState = setField(state, localPath, {
          dirty: true, // will be deprecated
          pristine: false,
          value: action.value,
        });

        if (action.removeKeys) {
          const persistKeys = [];

          const removeKeys = Object.keys(state.fields).filter((fieldKey) => {
            const localStringPath = localPath.join('.');

            for (const removeKey of action.removeKeys) {
              const removeKeyPath = `${localStringPath}.${removeKey}`;
              if (startsWith(fieldKey, removeKeyPath)) return true;
            }

            if (startsWith(fieldKey, `${localStringPath}.`)) {
              persistKeys.push(fieldKey);
            }

            return false;
          });

          removeKeys.forEach((removeKey) => {
            setFieldDirtyState = icepick.updateIn(
              setFieldDirtyState,
              ['fields'],
              (field) => icepick.dissoc(field, removeKey));
          });

          persistKeys.forEach((persistKey, index) => {
            const newPersistKeyPath = toPath(persistKey);
            newPersistKeyPath[localPath.length] = index;

            const persistField = getField(state, persistKey);

            // Remove old key
            setFieldDirtyState = icepick.updateIn(
              setFieldDirtyState,
              ['fields'],
              (field) => icepick.dissoc(field, persistKey));

            // Update field to new key
            setFieldDirtyState = setInField(
              setFieldDirtyState,
              newPersistKeyPath,
              persistField);
          });
        }

        return icepick.merge(setFieldDirtyState, {
          dirty: true, // will be deprecated
          pristine: false,
          valid: formIsValid(setFieldDirtyState),
        });
      }

      case actionTypes.SET_DIRTY: {
        const setDirtyState = icepick.merge(state, {
          dirty: true, // will be deprecated
          pristine: false,
        });

        return setField(setDirtyState, localPath, {
          dirty: true, // will be deprecated
          pristine: false,
        });
      }

      case actionTypes.BLUR:
      case actionTypes.SET_TOUCHED: {
        const fieldState = setField(state, localPath, {
          focus: false,
          touched: true,
          retouched: state.submitted || state.submitFailed,
          blur: true, // will be deprecated
          untouched: false, // will be deprecated
        });

        return icepick.merge(fieldState, {
          touched: true,
          retouched: state.submitted || state.submitFailed,
          untouched: false, // will be deprecated
        });
      }

      case actionTypes.SET_PENDING:
        return setField(state, localPath, {
          pending: action.pending,
          submitted: false,
          submitFailed: false,
          retouched: false,
        });

      case actionTypes.SET_VALIDITY: {
        if (isPlainObject(action.validity)) {
          errors = mapValues(action.validity, valid => !valid);
        } else {
          errors = !action.validity;
        }

        const formIsValidState = setInField(state, localPath, {
          errors,
          validity: action.validity,
          valid: isBoolean(errors) ? !errors : every(errors, error => !error),
        });

        return icepick.merge(formIsValidState, {
          valid: formIsValid(formIsValidState),
        });
      }

      case actionTypes.SET_FIELDS_VALIDITY:
        return map(action.fieldsValidity, (fieldValidity, field) =>
          actions.setValidity(`${model}.${field}`, fieldValidity, action.options)
        ).reduce(formReducer, state);

      case actionTypes.SET_ERRORS: {
        if (isPlainObject(action.errors)) {
          validity = mapValues(action.errors, error => !error);
        } else {
          validity = !action.errors;
        }

        const setErrorsState = setInField(state, localPath, {
          errors: action.errors,
          validity,
          valid: isValid(validity),
        });

        return icepick.merge(setErrorsState, {
          valid: formIsValid(setErrorsState),
        });
      }

      case actionTypes.RESET_VALIDITY: {
        let resetValidityState;
        if (!localPath.length) {
          resetValidityState = icepick.setIn(
            state,
            ['valid'],
            true);

          resetValidityState = icepick.setIn(
            resetValidityState,
            ['validity'],
            initialFieldState.validity);

          resetValidityState = icepick.setIn(
            resetValidityState,
            ['errors'],
            initialFieldState.errors);

          Object.keys(resetValidityState.fields).forEach((field) => {
            resetValidityState = icepick.setIn(
              resetValidityState,
              ['fields', field, 'valid'],
              true);

            resetValidityState = icepick.setIn(
              resetValidityState,
              ['fields', field, 'validity'],
              initialFieldState.validity);

            resetValidityState = icepick.setIn(
              resetValidityState,
              ['fields', field, 'errors'],
              initialFieldState.errors);
          });
        } else {
          resetValidityState = icepick.setIn(
            state,
            ['fields', localPath.join('.'), 'valid'],
            true
          );

          resetValidityState = icepick.setIn(
            resetValidityState,
            ['fields', localPath.join('.'), 'validity'],
            initialFieldState.validity
          );

          resetValidityState = icepick.setIn(
            resetValidityState,
            ['fields', localPath.join('.'), 'errors'],
            initialFieldState.errors
          );
        }

        return icepick.merge(resetValidityState, {
          valid: formIsValid(resetValidityState),
        });
      }

      case actionTypes.SET_PRISTINE: {
        let formIsPristine;
        let setPristineState;

        if (!localPath.length) {
          formIsPristine = true;

          setPristineState = icepick.merge(state, {
            fields: mapValues(state.fields, field => ({
              ...field,
              dirty: false, // will be deprecated
              pristine: true,
            })),
          });
        } else {
          setPristineState = setField(state, localPath, {
            dirty: false, // will be deprecated
            pristine: true,
          });

          formIsPristine = every(mapValues(setPristineState.fields, field => field.pristine));
        }

        return icepick.merge(setPristineState, {
          dirty: !formIsPristine, // will be deprecated
          pristine: formIsPristine,
        });
      }

      case actionTypes.SET_UNTOUCHED:
        return setField(state, localPath, {
          touched: false,
          untouched: true, // will be deprecated
        });

      case actionTypes.SET_SUBMITTED:
        return setField(state, localPath, {
          pending: false,
          submitted: !!action.submitted,
          submitFailed: false,
          touched: true,
          untouched: false, // will be deprecated
        });

      case actionTypes.SET_SUBMIT_FAILED:
        return setField(state, localPath, {
          pending: false,
          submitted: false,
          submitFailed: true,
          touched: true,
          untouched: false, // will be deprecated
        });

      case actionTypes.SET_INITIAL:
      case actionTypes.RESET:
        if (!localPath.length) {
          return localInitialFormState;
        }

        return resetField(state, localPath);

      case actionTypes.SET_VIEW_VALUE:
        return setField(state, localPath, {
          viewValue: action.value,
        });

      default:
        return state;
    }
  };