Redux Form v6 (#13214)

* [Redux Form] Rename current definitions to 4.0

* Added start of redux-form v6 definition

* Defined arrayMove parameter types

* Unexported action creators that are not exported

* Form props/methods don't need to be optional

* Updated decorator to infer the component generic type

* Fix reducer definition. State should always be the FormStateMap type not a generic. Returned is the state AND object with plugin method (not or).

* Removed namespace. I think this will make it easier to extend functionality....just follow redux's lead really.

* Split meta, input, and custom props from RC4 change. Renamed MyFieldProps to FieldCustomProps to match documented wording.

* Fix onDragStart, onDrop, onFocus

* Update SubmitHandler doc to give more info and reference SubmissionError

* Added Selectors

* Replace Form's fieldList with registeredFields

* Split FieldArray's meta props out from rc4 change

* Add submitSucceeded prop and setSubmitSucceeded action (#1428)

* Added parse() and format() to Field

* Removed value type from onBlur and onChange parameter (40c0d7e)

* Revert handleSubmit change so TS sees both definitions as methods.

* Nothing to see here...

* Added props parameter to config's validate

* Added array functions to FormProps

* Removed unexported action creators

* Overloaded reduxForm() to make generics optional.

* Refactor Generic* interfaces from Field and FieldArray. These will have the generics, and the classes will have those generics set to any :(

* Added some tests for definition.

* Added pure option to config

* Split definition into multiple files

* [tsconfig] no implicit returns or this. enabled strict null checks and decorators.

* Fix event handlers needing a element generic with any for now.

* Added Fields

* Updated definition for all changes up to v6.1.1.

* Missed errors prop on SubmissionError

* Updated definition for all changes up to v6.2.1.

* Added header

* Added validate and warn props https://github.com/erikras/redux-form/pull/2245

* Added clearAsyncError https://github.com/erikras/redux-form/pull/2213

* Added FieldArray get & getAll https://github.com/erikras/redux-form/pull/2247

* Updated version to 6.3.1

* Added react reference dependency

* Fix initialize action. Thanks @csillag

* Changed Normalizer, Formatter, Parser, Validator to types and exported them

* Added original author of v4 definitions
This commit is contained in:
Carson Full
2016-12-27 17:12:06 -06:00
committed by Andy
parent 1a87b929f0
commit c3eef69e2e
13 changed files with 2343 additions and 776 deletions

486
redux-form/index.d.ts vendored
View File

@@ -1,476 +1,38 @@
// Type definitions for redux-form v4.0.3
// Type definitions for redux-form v6.3.1
// Project: https://github.com/erikras/redux-form
// Definitions by: Daniel Lytkin <https://github.com/aikoven>
// Definitions by: Carson Full <https://github.com/carsonf>, Daniel Lytkin <https://github.com/aikoven>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
import * as React from 'react';
import { Component, SyntheticEvent, FormEventHandler } from 'react';
import { Dispatch, ActionCreator, Reducer } from 'redux';
///<reference types="react" />
export const actionTypes: {[actionName:string]: string};
import {
ComponentClass,
StatelessComponent,
} from 'react';
export type FieldValue = any;
export type FormData = { [fieldName: string]: FieldValue };
export type FieldType = 'Field' | 'FieldArray';
export interface FieldProp<T> {
/**
* true if this field currently has focus. It will only work if you are
* passing onFocus to your input element.
*/
active: boolean;
export type DataShape = {[fieldName:string]: FieldValue};
/**
* An alias for value only when value is a boolean. Provided for
* convenience of destructuring the whole field object into the props of a
* form element.
*/
checked?: boolean;
export type FormErrors<FormData extends DataShape> = FormData & { _error?: string };
/**
* true if the field value has changed from its initialized value.
* Opposite of pristine.
*/
dirty: boolean;
/**
* The error for this field if its value is not passing validation. Both
* synchronous and asynchronous validation errors will be reported here.
*/
error?: any;
/**
* The value for this field as supplied in initialValues to the form.
*/
initialValue: FieldValue;
/**
* true if the field value fails validation (has a validation error).
* Opposite of valid.
*/
invalid: boolean;
/**
* The name of the field. It will be the same as the key in the fields
* Object, but useful if bundling up a field to send down to a specialized
* input component.
*/
name: string;
/**
* A function to call when the form field loses focus. It expects to
* either receive the React SyntheticEvent or the current value of the
* field.
*/
onBlur(eventOrValue: SyntheticEvent<T> | FieldValue): void;
/**
* A function to call when the form field is changed. It expects to either
* receive the React SyntheticEvent or the new value of the field.
* @param eventOrValue
*/
onChange(eventOrValue: SyntheticEvent<T> | FieldValue): void;
/**
* A function to call when the form field receives a 'dragStart' event.
* Saves the field value in the event for giving the field it is dropped
* into.
*/
onDragStart(): void;
/**
* A function to call when the form field receives a drop event.
*/
onDrop(): void;
/**
* A function to call when the form field receives focus.
*/
onFocus(): void;
/**
* An alias for onChange. Provided for convenience of destructuring the
* whole field object into the props of a form element. Added to provide
* out-of-the-box support for Belle components' onUpdate API.
*/
onUpdate(): void;
/**
* true if the field value is the same as its initialized value. Opposite
* of dirty.
*/
pristine: boolean;
/**
* true if the field has been touched. By default this will be set when
* the field is blurred.
*/
touched: boolean;
/**
* true if the field value passes validation (has no validation errors).
* Opposite of invalid.
*/
valid: boolean;
/**
* The value of this form field. It will be a boolean for checkboxes, and
* a string for all other input types.
*/
value: FieldValue;
/**
* true if this field has ever had focus. It will only work if you are
* passing onFocus to your input element.
*/
visited: boolean;
}
export interface ReduxFormProps<T> {
/**
* The name of the currently active (with focus) field.
*/
active?: string;
/**
* A function that may be called to initiate asynchronous validation if
* asynchronous validation is enabled.
*/
asyncValidate?: Function;
/**
* true if the asynchronous validation function has been called but has not
* yet returned.
*/
asyncValidating?: boolean;
/**
* Destroys the form state in the Redux store. By default, this will be
* called for you in componentWillUnmount().
*/
destroyForm?(): void;
/**
* true if the form data has changed from its initialized values. Opposite
* of pristine.
*/
dirty?: boolean;
/**
* A generic error for the entire form given by the _error key in the
* result from the synchronous validation function, the asynchronous
* validation, or the rejected promise from onSubmit.
*/
error?: any;
/**
* The form data, in the form { field1: <Object>, field2: <Object> }. The
* field objects are meant to be destructured into your input component as
* props, e.g. <input type="text" {...field.name}/>. Each field Object has
* the following properties:
*/
fields?: { [field: string]: FieldProp<T> };
/**
* A function meant to be passed to <form onSubmit={handleSubmit}> or to
* <button onClick={handleSubmit}>. It will run validation, both sync and
* async, and, if the form is valid, it will call
* this.props.onSubmit(data) with the contents of the form data.
* Optionally, you may also pass your onSubmit function to handleSubmit
* which will take the place of the onSubmit prop. For example: <form
* onSubmit={handleSubmit(this.save.bind(this))}> If your onSubmit
* function returns a promise, the submitting property will be set to true
* until the promise has been resolved or rejected. If it is rejected with
* an object matching { field1: 'error', field2: 'error' } then the
* submission errors will be added to each field (to the error prop) just
* like async validation errors are. If there is an error that is not
* specific to any field, but applicable to the entire form, you may pass
* that as if it were the error for a field called _error, and it will be
* given as the error prop.
*/
handleSubmit?(event: SyntheticEvent<T>): void;
handleSubmit?(event: React.MouseEvent<HTMLButtonElement>): void;
handleSubmit?(submit: (data: FormData, dispatch?: Dispatch<any>) => Promise<any> | void): FormEventHandler<T>;
/**
* Initializes the form data to the given values. All dirty and pristine
* state will be determined by comparing the current data with these
* initialized values.
* @param data
*/
initializeForm?(data: FormData): void;
/**
* true if the form has validation errors. Opposite of valid.
*/
invalid?: boolean;
/**
* true if the form data is the same as its initialized values. Opposite
* of dirty.
*/
pristine?: boolean;
/**
* Resets all the values in the form to the initialized state, making it
* pristine again.
*/
resetForm?(): void;
/**
* The same formKey prop that was passed in. See Editing Multiple Records.
*/
formKey?: string;
/**
* Whether or not your form is currently submitting. This prop will only
* work if you have passed an onSubmit function that returns a promise. It
* will be true until the promise is resolved or rejected.
*/
submitting?: boolean;
/**
* Starts as false. If onSubmit is called, and fails to submit for any
* reason, submitFailed will be set to true. A subsequent successful
* submit will set it back to false.
*/
submitFailed?: boolean;
/**
* Marks the given fields as "touched" to show errors.
* @param field
*/
touch?(...field: string[]): void;
/**
* Marks all fields as "touched" to show errors. This will automatically
* happen on form submission.
*/
touchAll?(): void;
/**
* Clears the "touched" flag for the given fields
* @param field
*/
untouch?(...field: string[]): void;
/**
* Clears the "touched" flag for the all fields
*/
untouchAll?(): void;
/**
* true if the form passes validation (has no validation errors). Opposite
* of invalid.
*/
valid?: boolean;
/**
* All of your values in the form { field1: <string>, field2: <string> }.
*/
values?: FormData;
}
declare class ElementClass extends Component<any, any> {
}
interface ClassDecorator {
<T extends (typeof ElementClass)>(component: T): T;
}
interface MapStateToProps {
(state: any, ownProps?: any): any;
}
interface MapDispatchToPropsFunction {
(dispatch: Dispatch<any>, ownProps?: any): any;
}
interface MapDispatchToPropsObject {
[name: string]: ActionCreator<any>;
}
export declare function reduxForm(config: ReduxFormConfig,
mapStateToProps?: MapStateToProps,
mapDispatchToProps?: MapDispatchToPropsFunction | MapDispatchToPropsObject): ClassDecorator;
export interface ReduxFormConfig {
/**
* a list of all your fields in your form. You may change these dynamically
* at runtime.
*/
fields: string[];
/**
* the name of your form and the key to where your form's state will be
* mounted under the redux-form reducer
*/
form: string;
/**
* By default, async blur validation is only triggered if synchronous
* validation passes, and the form is dirty or was never initialized (or if
* submitting). Sometimes it may be desirable to trigger asynchronous
* validation even in these cases, for example if all validation is performed
* asynchronously and you want to display validation messages if a user does
* not change a field, but does touch and blur it. Setting
* alwaysAsyncValidate to true will always run asynchronous validation on
* blur, even if the form is pristine or sync validation fails.
*/
alwaysAsyncValidate?: boolean;
/**
* field names for which onBlur should trigger a call to the asyncValidate
* function. Defaults to [].
*
* See Asynchronous Blur Validation Example for more details.
*/
asyncBlurFields?: string[];
/**
* a function that takes all the form values, the dispatch function, and
* the props given to your component, and returns a Promise that will
* resolve if the validation is passed, or will reject with an object of
* validation errors in the form { field1: <String>, field2: <String> }.
*
* See Asynchronous Blur Validation Example for more details.
*/
asyncValidate?(values: FormData, dispatch: Dispatch<any>, props: Object): Promise<any>;
/**
* Whether or not to automatically destroy your form's state in the Redux
* store when your component is unmounted. Defaults to true.
*/
destroyOnUnmount?: boolean;
/**
* The key for your sub-form.
*
* See Multirecord Example for more details.
*/
formKey?: string;
/**
* A function that takes the entire Redux state and the reduxMountPoint
* (which defaults to "form"). It defaults to:
* (state, reduxMountPoint) => state[reduxMountPoint].
* The only reason you should provide this is if you are keeping your Redux
* state as something other than plain javascript objects, e.g. an
* Immutable.Map.
*/
getFormState?(state: any, reduxMountPoint: string): any;
/**
* The values with which to initialize your form in componentWillMount().
* Particularly useful when Editing Multiple Records, but can also be used
* with single-record forms. The values should be in the form
* { field1: 'value1', field2: 'value2' }.
*/
initialValues?: { [field: string]: FieldValue };
/**
* The function to call with the form data when the handleSubmit() is fired
* from within the form component. If you do not specify it as a prop here,
* you must pass it as a parameter to handleSubmit() inside your form
* component.
*/
onSubmit?(values: FormData, dispatch?: Dispatch<any>): any;
/**
* If true, the form values will be overwritten whenever the initialValues
* prop changes. If false, the values will not be overwritten if the form has
* previously been initialized. Defaults to true.
*/
overwriteOnInitialValuesChange?: boolean;
/**
* If specified, all the props normally passed into your decorated
* component directly will be passed under the key specified. Useful if
* using other decorator libraries on the same component to avoid prop
* namespace collisions.
*/
propNamespace?: string;
/**
* if true, the decorated component will not be passed any of the onX
* functions as props that will allow it to mutate the state. Useful for
* decorating another component that is not your form, but that needs to
* know about the state of your form.
*/
readonly?: boolean;
/**
* The use of this property is highly discouraged, but if you absolutely
* need to mount your redux-form reducer at somewhere other than form in
* your Redux state, you will need to specify the key you mounted it under
* with this property. Defaults to 'form'.
*
* See Alternate Mount Point Example for more details.
*/
reduxMountPoint?: string;
/**
* If set to true, a failed submit will return a rejected promise. Defaults
* to false. Only use this if you need to detect submit failures and run
* some code when a submit fails.
*/
returnRejectedSubmitPromise?: boolean;
/**
* marks fields as touched when the blur action is fired. Defaults to true.
*/
touchOnBlur?: boolean;
/**
* marks fields as touched when the change action is fired. Defaults to
* false.
*/
touchOnChange?: boolean;
/**
* a synchronous validation function that takes the form values and props
* passed into your component. If validation passes, it should return {}.
* If validation fails, it should return the validation errors in the form
* { field1: <String>, field2: <String> }.
* Defaults to (values, props) => ({}).
*/
validate?(values: FormData, props: { [fieldName: string]: FieldProp<any> }): Object;
}
export type FormWarnings<FormData extends DataShape> = FormData & { _warning?: string };
/**
* @param value The current value of the field.
* @param previousValue The previous value of the field before the current
* action was dispatched.
* @param allValues All the values of the current form.
* @param previousAllValues All the values of the form before the current
* change. Useful to change one field based on a change in another.
* A component class or stateless function component.
* Workaround for: ComponentClass<P> | SFC<P> which does
* not resolve due to a bug in TypeScript.
* https://github.com/Microsoft/TypeScript/pull/8674
*/
export type Normalizer =
(value: FieldValue, previousValue: FieldValue,
allValues: FormData, previousAllValues: FormData) => any;
export declare const reducer: {
(state: any, action: any): any;
/**
* Returns a form reducer that will also pass each form value through the
* normalizing functions provided. The parameter is an object mapping from
* formName to an object mapping from fieldName to a normalizer function.
* The normalizer function is given four parameters and expected to return
* the normalized value of the field.
*/
normalize(normalizers: {
[formName: string]: {
[fieldName: string]: Normalizer
}
}): Reducer<any>;
/**
* Returns a form reducer that will also pass each action through
* additional reducers specified. The parameter should be an object mapping
* from formName to a (state, action) => nextState reducer. The state
* passed to each reducer will only be the slice that pertains to that
* form.
*/
plugin(reducers: { [formName: string]: Reducer<any> }): Reducer<any>;
}
export type ComponentConstructor = ComponentClass<any> | StatelessComponent<any>;
export * from "./lib/reduxForm";
export * from "./lib/Field";
export * from "./lib/Fields";
export * from "./lib/FieldArray";
export * from "./lib/FormSection";
export * from "./lib/actions";
export * from "./lib/reducer";
export * from "./lib/selectors";

313
redux-form/lib/Field.d.ts vendored Normal file
View File

@@ -0,0 +1,313 @@
import {
Component,
ReactElement,
DragEventHandler,
FocusEventHandler,
FormEventHandler,
} from "react";
import { Dispatch } from "redux";
import { ComponentConstructor, DataShape, FieldValue } from "../index";
/**
* These are the props to give to `Field`.
* Any others will be passed through to your component.
*/
interface BaseFieldProps {
/**
* A string path, in dot-and-bracket notation, corresponding to a value
* in the form values. It may be as simple as 'firstName' or as complicated
* as contact.billing.address[2].phones[1].areaCode.
*
* Required but made optional so interface can be used on decorated components.
*/
name?: string;
/**
* A Component, stateless function, or string corresponding to a default
* JSX element.
*
* Required but made optional so interface can be used on decorated components.
*/
component?: ComponentConstructor | "input" | "select" | "textarea",
// component?: ComponentClass<P> | SFC<P> | "input" | "select" | "textarea",
/**
* If true, the rendered component will be available with the
* getRenderedComponent() method. Defaults to false. Cannot be used if your
* component is a stateless function component.
*/
withRef?: boolean;
/**
* Formats the value from the Redux store to be displayed in the field input.
* Common use cases are to format Numbers into currencies or Dates into a
* localized date format.
*/
format?: Formatter | null;
/**
* A function to convert whatever value the user has entered into the value that you
* want stored in the Redux store for the field.
*
* For instance, if you want the value to be in all uppercase, you would pass
* value => value.toUpperCase()
*/
normalize?: Normalizer;
/**
* Don't use.
*/
props?: Object;
/**
* Parses the value given from the field input component to the type that you want
* stored in the Redux store. Common use cases are to parse currencies into Numbers into
* currencies or localized date formats into Dates.
*/
parse?: Parser;
/**
* Allows you to to provide a field-level validation rule. The function will be given the
* current value of the field and all the other form values. If the field is valid, it
* should return `undefined`, if the field is invalid, it should return an error
* (usually, but not necessarily, a `String`).
*/
validate?: Validator|Validator[];
/**
* Allows you to to provide a field-level warning rule. The function will be given the
* current value of the field and all the other form values. If the field needs a warning,
* it should return the warning (usually, but not necessarily, a `String`). If the field
* does not need a warning, it should return `undefined`.
*/
warn?: Validator|Validator[];
}
/**
* @param value The value entered by the user.
* @param previousValue The previous value for the field.
* @param allValues All the values in the entire form with the new value.
* This will be an Immutable Map if you are using Immutable JS.
* @param previousAllValues All the values in the entire form before the current change.
* This will be an Immutable Map if you are using Immutable JS.
*/
export type Normalizer = (value: FieldValue, previousValue?: FieldValue, allValues?: Object, previousAllValues?: Object) => FieldValue;
export type Formatter = (value: FieldValue, name: string) => FieldValue;
export type Parser = (value: FieldValue, name: string) => FieldValue;
export type Validator = (value: FieldValue, allValues?: Object) => undefined | string;
/**
* Declare Field as this interface to specify the generic.
*/
export interface GenericField<FieldCustomProps, S> extends Component<BaseFieldProps & FieldCustomProps, {}> {
/**
* true if the current value is different from the initialized value,
* false otherwise.
*/
dirty: boolean;
/**
* The name prop that you passed in.
*/
name: string;
/**
* true if the current value is the same as the initialized value,
* false otherwise.
*/
pristine: boolean;
/**
* The current value of the field.
*/
value: FieldValue;
/**
* Returns the instance of the rendered component. For this to work, you must
* provide a withRef prop, and your component must not be a stateless function
* component.
*/
getRenderedComponent(): Component<WrappedFieldProps<S> & FieldCustomProps, any>;
}
/**
* The Field Instance API.
*/
export class Field extends Component<any, {}> implements GenericField<any, any> {
/**
* true if the current value is different from the initialized value,
* false otherwise.
*/
dirty: boolean;
/**
* The name prop that you passed in.
*/
name: string;
/**
* true if the current value is the same as the initialized value,
* false otherwise.
*/
pristine: boolean;
/**
* The current value of the field.
*/
value: FieldValue;
/**
* Returns the instance of the rendered component. For this to work, you must
* provide a withRef prop, and your component must not be a stateless function
* component.
*/
getRenderedComponent(): Component<any, any>;
}
/**
* These are props that `Field` will pass to your wrapped component (not including custom props).
*/
interface WrappedFieldProps<S> {
/**
* An object containing all the props that you will normally want to pass to
* your input component.
*/
input: WrappedFieldInputProps;
/**
* An object containing all the metadata props.
*/
meta: WrappedFieldMetaProps<S>;
}
/**
* These props are meant to be destructured into your <input/> component.
*/
interface WrappedFieldInputProps {
/**
* An alias for value only when value is a boolean. Provided for
* convenience of destructuring the whole field object into the props of a
* form element.
*/
checked?: boolean;
/**
* The name prop passed in.
*/
name: string;
/**
* A function to call when the form field loses focus.
*/
onBlur: FocusEventHandler<any>;
/**
* A function to call when the form field is changed.
*/
onChange: FormEventHandler<any>;
/**
* A function to call when the form field receives a 'dragStart' event.
* Saves the field value in the event for giving the field it is dropped
* into.
*/
onDragStart: DragEventHandler<any>;
/**
* A function to call when the form field receives a drop event.
*/
onDrop: DragEventHandler<any>;
/**
* A function to call when the form field receives focus.
*/
onFocus: FocusEventHandler<any>;
/**
* The value of this form field. It will be a boolean for checkboxes, and
* a string for all other input types. If there is no value in the Redux
* state for this field, it will default to ''. This is to
* ensure that the input is controlled.
*/
value: FieldValue;
}
/**
* These props are metadata about the state of this field that redux-form is tracking for you.
*/
interface WrappedFieldMetaProps<S> {
/**
* true if this field currently has focus. It will only work if you are
* passing onFocus to your input element.
*/
active?: boolean;
/**
* true if this field has been set with the AUTOFILL action and has not since been changed
* with a CHANGE action. This is useful to render the field in a way that the user can tell
* that the value was autofilled for them.
*/
autofilled: boolean;
/**
* true if the form is currently running asynchronous validation because this
* field was blurred.
*/
asyncValidating: boolean;
/**
* true if the field value has changed from its initialized value.
* Opposite of pristine.
*/
dirty: boolean;
/**
* The Redux dispatch function.
*/
dispatch: Dispatch<S>;
/**
* The error for this field if its value is not passing validation. Both
* synchronous, asynchronous, and submit validation errors will be reported here.
*/
error?: string;
/**
* true if the field value fails validation (has a validation error).
* Opposite of valid.
*/
invalid: boolean;
/**
* true if the field value is the same as its initialized value. Opposite
* of dirty.
*/
pristine: boolean;
/**
* true if the field has been touched. By default this will be set when
* the field is blurred.
*/
touched: boolean;
/**
* true if the field value passes validation (has no validation errors).
* Opposite of invalid.
*/
valid: boolean;
/**
* true if this field has ever had focus. It will only work if you are
* passing onFocus to your input element.
*/
visited?: boolean;
/**
* The warning for this field if its value is not passing warning validation.
*/
warning?: string;
}

214
redux-form/lib/FieldArray.d.ts vendored Normal file
View File

@@ -0,0 +1,214 @@
import { Component } from "react";
import { ComponentConstructor, Validator } from "../index";
/**
* These are the props to give to `FieldArray`.
* Any others will be passed through to your component.
*/
interface BaseFieldArrayProps {
/**
* A string path, in dot-and-bracket notation, corresponding to a value
* in the form values. It may be as simple as 'firstName' or as complicated
* as contact.billing.address[2].phones[1].areaCode.
*
* Required but made optional so interface can be used on decorated components.
*/
name?: string;
/**
* A Component or stateless function to render the field array.
*
* Required but made optional so interface can be used on decorated components.
*/
component?: ComponentConstructor,
// component?: Component<P, any> | StatelessComponent<P>,
/**
* Allows you to to provide a field-level validation rule. The function will be given the
* current value of the field and all the other form values. If the field is valid, it
* should return `undefined`, if the field is invalid, it should return an error
* (usually, but not necessarily, a `String`).
*/
validate?: Validator|Validator[];
/**
* Allows you to to provide a field-level warning rule. The function will be given the
* current value of the field and all the other form values. If the field needs a warning,
* it should return the warning (usually, but not necessarily, a `String`). If the field
* does not need a warning, it should return `undefined`.
*/
warn?: Validator|Validator[];
/**
* If true, the rendered component will be available with the
* getRenderedComponent() method. Defaults to false. Cannot be used if your
* component is a stateless function component.
*/
withRef?: boolean;
props?: Object;
}
/**
* Declare FieldArray as this interface to specify the generics.
*/
export interface GenericFieldArray<T, FieldCustomProps> extends Component<BaseFieldArrayProps & FieldCustomProps, {}> {
/**
* The name prop that you passed in.
*/
name: string;
/**
* true if this field passes validation, false otherwise.
*/
valid: boolean;
/**
* Returns the instance of the rendered component. For this to work, you must
* provide a withRef prop, and your component must not be a stateless function
* component.
*/
getRenderedComponent(): Component<WrappedFieldArrayProps<T> & FieldCustomProps, any>;
}
/**
* The FieldArray Instance API.
*/
export class FieldArray extends Component<any, {}> implements GenericFieldArray<any, any> {
/**
* The name prop that you passed in.
*/
name: string;
/**
* true if this field passes validation, false otherwise.
*/
valid: boolean;
/**
* Returns the instance of the rendered component. For this to work, you must
* provide a withRef prop, and your component must not be a stateless function
* component.
*/
getRenderedComponent(): Component<any, any>;
}
/**
* These are props that `FieldArray` will pass to your wrapped component.
*/
interface WrappedFieldArrayProps<T> {
fields: FieldsProps<T>;
meta: FieldArrayMetaProps;
}
interface FieldsProps<T> {
/**
* A method to iterate over each value of the array.
*/
forEach(callback: (name: string, index: number, fields: FieldsProps<T>) => void): void;
/**
* A method to get a single value from the array value.
*/
get(index: number): T;
/**
* A method to get all the values in the array.
*/
getAll(): T[];
/**
* A function to insert a new value into the array at any arbitrary index.
*/
insert(index: number, value: T): void;
/**
* The current length of the array.
*/
length: number;
/**
* A method to iterate over each value of the array. Returns an array of the
* results of each call to the callback.
*/
map(callback: (name: string, index: number, fields: FieldsProps<T>) => any): any;
/**
* Removes an item from the end of the array. Returns the item removed.
*/
pop(): T;
/**
* Adds a value to the end of the array.
*/
push(value: T): void;
/**
* Removes an item from the array at an arbitrary index.
*/
remove(index: number): void;
/**
* Removes an item from beginning of the array. Returns the item removed.
*/
shift(): T;
/**
* Swaps two items in the array at the given indexes.
*/
swap(indexA: number, indexB: number): void;
/**
* Adds an item to the beginning of the array.
*/
unshift(value: T): void;
}
interface FieldArrayMetaProps {
/**
* true if the any of the fields in the field array have changed from their
* initialized value. Opposite of pristine.
*/
dirty: boolean;
/**
* The error for this field array if its value is not passing validation. Both
* synchronous, asynchronous, and submit validation errors will be reported here.
* Array-specific errors should be returned from the validation function as an
* _error key on the array.
*/
error?: string;
/**
* true if the field array value fails validation (has a validation error).
* Opposite of valid.
*/
invalid: boolean;
/**
* true if the all of the fields in the field array are the same as their
* initialized value. Opposite of dirty.
*/
pristine: boolean;
/**
* true if any of the fields have been touched.
*/
touched: boolean;
/**
* true if the field value passes validation (has no validation errors).
* Opposite of invalid.
*/
valid: boolean;
/**
* The warning for this field array if its values are not passing warning validation.
* Array-specific errors should be returned from the validation function as an
* `_warning` key on the array.
*/
warning?: string;
}

112
redux-form/lib/Fields.d.ts vendored Normal file
View File

@@ -0,0 +1,112 @@
import { Component } from "react";
import { ComponentConstructor, Formatter, Parser, FieldValue } from "../index";
/**
* These are the props to give to `Field`.
* Any others will be passed through to your component.
*/
interface BaseFieldsProps {
/**
* An array of strings (or the pseudo-array fields provided by FieldArray),
* in dot-and-bracket notation, corresponding to form values.
* They may be as simple as 'firstName' or as complicated as
* 'contact.billing.address[2].phones[1].areaCode'.
*/
names: string[];
/**
* A Component or stateless function that will be given all the props necessary
* to render the field inputs.
*/
component?: ComponentConstructor | 'input' | 'select' | 'textarea';
/**
* Formats the value from the Redux store to be displayed in the field input.
* Common use cases are to format Numbers into currencies or Dates into a localized date format.
*
* format is called with the field value and name as arguments and should return the new formatted
* value to be displayed in the field input.
*
* To respect React 15 input behavior there is defaultFormat = value => value == null ? '' : value
* internally used. To disable that you can pass null as format prop.
*/
format?: Formatter | null;
/**
* Don't use.
*/
props?: Object;
/**
* Parses the value given from the field input component to the type that you want stored in the Redux store.
* Common use cases are to parse currencies into Numbers into currencies or localized date formats into Dates.
*
* parse is called with the field value and name as arguments and should return the new parsed value to be
* stored in the Redux store.
*/
parse?: Parser;
/**
* If true, the rendered component will be available with the getRenderedComponent() method.
* Defaults to false. Cannot be used if your component is a stateless function component.
*/
withRef?: boolean;
}
/**
* Declare Fields as this interface to specify the generics.
*/
export interface GenericFields<T, FieldsCustomProps> extends Component<BaseFieldsProps & FieldsCustomProps, {}> {
/**
* true if the current value of any of the fields is different from the initialized value, false otherwise.
*/
dirty: boolean;
/**
* The names prop that you passed in.
*/
names: string[];
/**
* true if the all of the current values are the same as the initialized values, false otherwise.
*/
pristine: boolean;
/**
* The current values of the fields. If they are nested, the values will duplicate the structure.
* For example, if your names are [ 'name.first', 'name.last', 'email' ], the values will be
* { name: { first: 'John', last: 'Smith' }, email: 'john@email.com' }
*/
values: {[name: string]: FieldValue};
getRenderedComponent(): Component<BaseFieldsProps & FieldsCustomProps, any>;
}
/**
* The Fields Instance API.
*/
export class Fields extends Component<any, {}> implements GenericFields<any, any> {
/**
* true if the current value of any of the fields is different from the initialized value, false otherwise.
*/
dirty: boolean;
/**
* The names prop that you passed in.
*/
names: string[];
/**
* true if the all of the current values are the same as the initialized values, false otherwise.
*/
pristine: boolean;
/**
* The current values of the fields. If they are nested, the values will duplicate the structure.
* For example, if your names are [ 'name.first', 'name.last', 'email' ], the values will be
* { name: { first: 'John', last: 'Smith' }, email: 'john@email.com' }
*/
values: {[name: string]: FieldValue};
getRenderedComponent(): Component<any, any>;
}

17
redux-form/lib/FormSection.d.ts vendored Normal file
View File

@@ -0,0 +1,17 @@
import { Component } from "react";
interface FormSectionProps {
/**
* The name all child fields should be prefixed with.
*/
name: string;
}
/**
* The FormSection component makes it easy to split forms into smaller components that are resuable across
* multiple forms. It does this by prefixing the name of Field, Fields and FieldArray children, at any depth,
* with the value specified in the name prop.
*/
export class FormSection extends Component<FormSectionProps, any> {
}

144
redux-form/lib/actions.d.ts vendored Normal file
View File

@@ -0,0 +1,144 @@
import { Action } from "redux";
import { FormErrors, FormWarnings, FieldType } from "../index";
/**
* Inserts an item into a field array at the specified index
*/
export function arrayInsert(form: string, field: string, index: number, value: any): Action;
/**
* Moves an item from one index in the array to another. In effect, it performs a remove and an
* insert, so the item already at the `to` position will be bumped to a higher index, not overwritten.
*/
export function arrayMove(form: string, field: string, from: number, to: number): Action;
/**
* Removes an item from the end of a field array
*/
export function arrayPop(form: string, field: string): Action;
/**
* Appends an item to the end of a field array
*/
export function arrayPush(form: string, field: string, value: any): Action;
/**
* Removes an item at the specified index from a field array
*/
export function arrayRemove(form: string, field: string, index: number): Action;
/**
* Removes all items from a field array
*/
export function arrayRemoveAll(form: string, field: string): Action;
/**
* Removes an item from the beginning of a field array
*/
export function arrayShift(form: string, field: string): Action;
/**
* ADVANCED USAGE - Inserts and/or removes items from a field array. Works similarly to Array.splice.
*/
export function arraySplice(form: string, field: string, index: number, removeNum: number, value: any): Action;
/**
* Swaps two items at the specified indexes in a field array
*/
export function arraySwap(form: string, field: string, indexA: number, indexB: number): Action;
/**
* Inserts an item at the beginning of a field array
*/
export function arrayUnshift(form: string, field: string, value: any): Action;
/**
* Saves the value to the field and sets its `autofilled` property to `true`.
*/
export function autofill(form: string, field: string, value: any): Action;
/**
* Saves the value to the field
*/
export function blur(form: string, field: string, value: any): Action;
/**
* Saves the value to the field
*/
export function change(form: string, field: string, value: any): Action;
/**
* Destroys the form, removing all it's state
*/
export function destroy(form: string): Action;
/**
* Marks the given field as active and visited
*/
export function focus(form: string, field: string): Action;
/**
* Sets the initial values in the form with which future data values will be compared to calculate dirty and pristine.
* The data parameter may contain deep nested array and object values that match the shape of your form fields.
* If the keepDirty parameter is true, the values of the currently dirty fields will be retained to avoid overwriting
* user edits.
*/
export function initialize(form: string, data: Object, keepDirty: boolean): Action;
/**
* Registers a field with the form.
*/
export function registerField(form: string, name: string, type: FieldType): Action;
/**
* Resets the values in the form back to the values past in with the most recent initialize action.
*/
export function reset(form: string): Action;
/**
* Flips the asyncValidating flag true
*/
export function startAsyncValidation(form: string): Action;
/**
* Flips the submitting flag true.
*/
export function startSubmit(form: string): Action;
/**
* Flips the submitting flag false and populates submitError for each field.
*/
export function stopSubmit(form: string, errors?: Object): Action;
/**
* Flips the asyncValidating flag false and populates asyncError for each field.
*/
export function stopAsyncValidation(form: string, errors?: Object): Action;
export function setSubmitFailed(form: string, ...fields: string[]): Action;
export function setSubmitSucceeded(form: string, ...fields: string[]): Action;
/**
* Triggers a submission of the specified form.
*/
export function submit(form: string): Action;
/**
* Marks all the fields passed in as touched.
*/
export function touch(form: string, ...fields: string[]): Action;
/**
* Unregisters a field with the form.
*/
export function unregisterField(form: string, name: string): Action;
/**
* Resets the 'touched' flag for all the fields passed in.
*/
export function untouch(form: string, ...fields: string[]): Action;
export function updateSyncErrors(from: string, syncErrors: FormErrors<FormData>, error: any): Action;
export function updateSyncWarnings(form: string, syncWarnings: FormWarnings<FormData>, warning: any): Action;

49
redux-form/lib/reducer.d.ts vendored Normal file
View File

@@ -0,0 +1,49 @@
import { Action, Reducer } from "redux";
import { FieldType } from "../index";
export function reducer(state: FormStateMap, action: Action): FormStateMap & FormReducer;
export interface FormReducer {
/**
* Returns a form reducer that will also pass each action through
* additional reducers specified. The parameter should be an object mapping
* from formName to a (state, action) => nextState reducer. The state
* passed to each reducer will only be the slice that pertains to that
* form.
*/
plugin(reducers: FormReducerMapObject): Reducer<any>;
}
export interface FormReducerMapObject {
[formName: string]: Reducer<any>;
}
/**
* Store state
*/
export interface FormStateMap {
[formName: string]: FormState;
}
export interface FormState {
registeredFields: RegisteredFieldState[];
fields?: {[name: string]: FieldState};
values?: { [fieldName: string]: string };
active?: string;
anyTouched?: boolean;
submitting?: boolean;
submitErrors?: { [fieldName: string]: string };
submitFailed?: boolean;
}
export interface RegisteredFieldState {
name: string;
type: FieldType;
}
export interface FieldState {
active?: boolean;
touched?: boolean;
visited?: boolean;
}

551
redux-form/lib/reduxForm.d.ts vendored Normal file
View File

@@ -0,0 +1,551 @@
import {
Component,
ReactElement,
SyntheticEvent,
ReactEventHandler,
} from "react";
import { Dispatch } from "redux";
import { DataShape, FieldValue, FormErrors, FormWarnings, RegisteredFieldState } from "../index";
export function reduxForm<FormData extends DataShape, P, S>(
config: Config<FormData, P, S>
): FormDecorator<FormData, P, S>;
export function reduxForm<FormData extends DataShape, P>(
config: Config<FormData, P, any>
): FormDecorator<FormData, P, any>;
export function reduxForm(
config: Config<any, any, any>
): FormDecorator<any, any, any>;
export interface FormDecorator<FormData extends DataShape, P, S> {
<T extends (typeof Component)>(component: T): T & Form<FormData, P, S>;
}
export interface Config<FormData extends DataShape, P, S> {
/**
* the name of your form and the key to where your form's state will be
* mounted under the redux-form reducer
*/
form: string;
/**
* An adapter function that will render a component based on a string component
* type and the props given to a Field. Remember that all you really need to hook
* up to your custom component's value and onChange. Defaults to [].
*
* See Asynchronous Blur Validation Example for more details.
*/
adapter?: (component: string, props: Object) => ReactElement<any>;
/**
* field names for which onBlur should trigger a call to the asyncValidate
* function. Defaults to [].
*
* See Asynchronous Blur Validation Example for more details.
*/
asyncBlurFields?: string[];
/**
* a function that takes all the form values, the dispatch function, and
* the props given to your component, and returns a Promise that will
* resolve if the validation is passed, or will reject with an object of
* validation errors in the form { field1: <String>, field2: <String> }.
*
* See Asynchronous Blur Validation Example for more details.
*/
asyncValidate?(values: FormData, dispatch: Dispatch<S>, props: P): Promise<any>;
/**
* Whether or not to automatically destroy your form's state in the Redux
* store when your component is unmounted. Defaults to true.
*/
destroyOnUnmount?: boolean;
/**
* A function that takes the entire Redux state and returns the state slice
* which corresponds to where the redux-form reducer was mounted. This
* functionality is rarely needed, and defaults to assuming that the reducer
* is mounted under the "form" key.
*/
getFormState?(state: S): any;
/**
* When set to true and enableReinitialize is also set, the form will retain the value of dirty fields when
* reinitializing. When this option is not set (the default), reinitializing the form replaces all field values.
* This option is useful in situations where the form has live updates or continues to be editable after
* form submission; it prevents reinitialization from overwriting user changes. Defaults to false.
*/
keepDirtyOnReinitialize?: boolean;
/**
* If true, implements `shouldComponentUpdate` and shallowly compares _only_
* the Redux-connected props that are needed to manage the form state. This
* prevents unnecessary updates, but assumes the component is a "pure"
* component and does not rely on any input or state other than its props and
* the selected Redux store's state. Defaults to true.
*/
pure?: boolean;
/**
* The values with which to initialize your form in componentWillMount().
* Particularly useful when Editing Multiple Records, but can also be used
* with single-record forms. The values should be in the form
* { field1: 'value1', field2: 'value2' }.
*/
initialValues?: FormData;
/**
* Reinitialize the form every time the initialValues prop changes.
* Defaults to false.
*/
enableReinitialize?: boolean;
/**
* The function to call with the form data when the handleSubmit() is fired
* from within the form component. If you do not specify it as a prop here,
* you must pass it as a parameter to handleSubmit() inside your form
* component.
*/
onSubmit?: SubmitHandler<FormData, P, S>;
/**
* A callback function that will be called when a submission fails for whatever reason.
*
* @param errors The errors that caused the submission to fail.
* @param dispatch The Redux `dispatch` function.
* @param submitError The error object that caused the submission to fail. If `errors` is set this will be most
* likely a `SubmissionError`, otherwise it can be any error or null.
*/
onSubmitFail?(errors: FormErrors<FormData>, dispatch: Dispatch<S>, submitError: any): void;
/**
* A callback function that will be called when a submission succeeds.
*/
onSubmitSuccess?(result: any, dispatch: Dispatch<S>): void;
/**
* Do not remove submit errors when the change action is fired. Defaults to false.
*/
persistentSubmitErrors?: boolean;
/**
* If specified, all the props normally passed into your decorated
* component directly will be passed under the key specified. Useful if
* using other decorator libraries on the same component to avoid prop
* namespace collisions.
*/
propNamespace?: string;
/**
* The use of this property is highly discouraged, but if you absolutely
* need to mount your redux-form reducer at somewhere other than form in
* your Redux state, you will need to specify the key you mounted it under
* with this property. Defaults to 'form'.
*
* See Alternate Mount Point Example for more details.
*/
reduxMountPoint?: string;
/**
* An optional function you may provide to have full control over when sync validation happens.
*/
shouldValidate?(params: ValidateCallback<FormData>): boolean;
/**
* An optional function you may provide to have full control over when async
* validation happens.
*/
shouldAsyncValidate?(params: AsyncValidateCallback<FormData>): boolean;
/**
* marks fields as touched when the blur action is fired. Defaults to true.
*/
touchOnBlur?: boolean;
/**
* marks fields as touched when the change action is fired. Defaults to
* false.
*/
touchOnChange?: boolean;
/**
* a synchronous validation function that takes the form values and props
* passed into your component. If validation passes, it should return {}.
* If validation fails, it should return the validation errors in the form
* { field1: <String>, field2: <String> }.
* Defaults to (values, props) => ({}).
*/
validate?(values: FormData, props: FormProps<FormData, P, S> & P): FormErrors<FormData>;
/**
* A synchronous warning function that takes the form values and props passed into your component.
* Warnings work the same as validations, but do not mark a form as invalid. If the warning check passes,
* it should return {}. If the check fails, it should return the warnings in the form
* { field1: <String>, field2: <String> }. Defaults to (values, props) => ({}).
*/
warn?(values: FormData, props: FormProps<FormData, P, S> & P): FormWarnings<FormData>;
}
/**
* If your onSubmit function returns a promise, the submitting property will be set to true
* until the promise has been resolved or rejected. If it is rejected with a redux-form
* SubmissionError containing errors in the form { field1: 'error', field2: 'error' } then
* the submission errors will be added to each field (to the error prop) just like async
* validation errors are. If there is an error that is not specific to any field, but applicable
* to the entire form, you may pass that as if it were the error for a field called _error,
* and it will be given as the error prop.
*/
export interface SubmitHandler<FormData extends DataShape, P, S> {
(values: FormData, dispatch: Dispatch<S>, props: FormProps<FormData, P, S> & P): void | FormErrors<FormData> | Promise<any>;
}
interface ValidateCallback<FormData extends DataShape> {
/**
* The values.
*/
values: FormData;
/**
* The next props.
*/
nextProps: Object;
/**
* The current props.
*/
props: Object;
/**
* true if the form is being initially rendered.
*/
initialRender: boolean;
/**
* The structure object being used internally for values. You may wish to use 'deepEqual' from the structure.
*/
structure: Object;
}
interface AsyncValidateCallback<FormData extends DataShape> {
/**
* Any existing asynchronous validation errors
*/
asyncErrors?: FormErrors<FormData>;
/**
* true if the form has ever been initialized with initial values
*/
initialized: boolean;
/**
* The reason to possibly run async validation. It will either be: 'blur' or
* 'submit', depending on whether an async blur field had triggered the async
* validation or if submitting the form has triggered it, respectively.
*/
trigger: 'blur' | 'submit';
/**
* The name of the field that has triggered the async validation. May be undefined.
*/
blurredField?: string;
/**
* true if the form is pristine, false if it is dirty
*/
pristine: boolean;
/**
* true if synchronous validation is passing, false if it is failing.
*/
syncValidationPasses: boolean;
}
/**
* A throwable error that is used to return submit validation errors from onSubmit.
* The purpose being to distinguish promise rejection because of validation errors
* from promise rejection because of AJAX I/O problems or other server errors.
*/
export class SubmissionError<FormData extends DataShape> extends Error {
errors: FormErrors<FormData>;
constructor(errors?: FormErrors<FormData>);
}
/**
* The following are methods or properties that you can access on an instance
* of your decorated form component (outermost component named "ReduxForm").
*/
export interface Form<FormData extends DataShape, P, S> extends Component<P, any> {
/**
* true if the form data has changed from its initialized values. Opposite
* of pristine.
*/
dirty: boolean;
/**
* true if the form has validation errors. Opposite of valid.
*/
invalid: boolean;
/**
* true if the form data is the same as its initialized values. Opposite
* of dirty.
*/
pristine: boolean;
/**
* An array of objects with fields `name` and `type` for each field
* representing all the fields in the form. Mainly useful for testing.
*/
registeredFields: RegisteredFieldState[];
/**
* Resets all the values in the form to the initialized state, making it
* pristine again.
*/
reset(): void;
/**
* Submits the form. Returns a promise that will be resolved when the form
* is submitted successfully, or rejected if the submission fails.
*/
submit(): Promise<any>;
/**
* true if the form passes validation (has no validation errors). Opposite
* of invalid.
*/
valid: boolean;
/**
* The current values of all the fields in the form.
*/
values: FormData;
/**
* A reference to the instance of the component you decorated with reduxForm().
* Mainly useful for testing.
*/
wrappedInstance: ReactElement<P & FormProps<FormData, P, S>>
}
/**
* These are the props that will be passed to your form component.
* Your form component's props can extend this interface.
*/
export interface FormProps<FormData extends DataShape, P, S> {
/**
* true if any of the fields have been marked as touched, false otherwise.
*/
anyTouched?: boolean;
/**
* A set of pre-bound action creators for you to operate on array fields in your form.
*/
array?: {
/**
* Inserts a value into the given array field in your form.
*/
insert(field: string, index: number, value: FieldValue): void;
/**
* Moves a value at the given from index to the given to index in
* the given array field in your form.
*/
move(field: string, from: number, to: number): void;
/**
* Pops a value off of the end of a given array field in your form.
*/
pop(field: string): void;
/**
* Pushes the given value onto the end of the given array field in your form.
*/
push(field: string, value: FieldValue): void;
/**
* Removes a value at the given index from the given array field in your form.
*/
remove(field: string, index: number): void;
/**
* Removes all the values from the given array field in your form.
*/
removeAll(field: string): void;
/**
* Shifts a value out of the beginning of the given array in your form.
*/
shift(field: string): void;
/**
* Performs an Array.splice operation on the given array in your form.
*/
splice(field: string, index: number, removeNum: number, value: FieldValue): void;
/**
* Swaps two values at the given indexes of the given array field in your form.
*/
swap(field: string, indexA: number, indexB: number): void;
/**
* Unshifts the given value into the beginning of the given array field in your form.
*/
unshift(field: string, value: FieldValue): void;
}
/**
* A function that may be called to initiate asynchronous validation if
* asynchronous validation is enabled.
*/
asyncValidate?: () => void;
/**
* This value will be either:
* - false - No asynchronous validation is currently happening
* - true - Asynchronous validation is currently running in preparation to submit a form
* - a string - The name of the field that just blurred to trigger asynchronous validation
*/
asyncValidating?: string | boolean;
/**
* Sets the value and marks the field as autofilled in the Redux Store. This is useful when a field
* needs to be set programmatically, but in a way that lets the user know (via a styling change using
* the autofilled prop in Field) that it has been autofilled for them programmatically.
*/
autofill?(field: string, value: FieldValue): void;
/**
* Marks a field as blurred in the Redux store.
*/
blur?(field: string, value: FieldValue): void;
/**
* Changes the value of a field in the Redux store.
*/
change?(field: string, value: FieldValue): void;
/**
* Clear async error of a field in the Redux store.
*/
clearAsyncError?(field: string): void;
/**
* Destroys the form state in the Redux store. By default, this will be
* called for you in componentWillUnmount().
*/
destroy?(): void;
/**
* true if the form data has changed from its initialized values. Opposite
* of pristine.
*/
dirty?: boolean;
/**
* A generic error for the entire form given by the _error key in the
* result from the synchronous validation function, the asynchronous
* validation, or the rejected promise from onSubmit.
*/
error?: string;
/**
* The form name that you gave to the reduxForm() decorator or the prop you
* passed in to your decorated form component.
*/
form?: string;
/**
* A function meant to be passed to <form onSubmit={handleSubmit}> or to
* <button onClick={handleSubmit}>. It will run validation, both sync and
* async, and, if the form is valid, it will call
* this.props.onSubmit(data) with the contents of the form data.
*
* Optionally, you may also pass your onSubmit function to handleSubmit
* which will take the place of the onSubmit prop. For example: <form
* onSubmit={handleSubmit(this.save.bind(this))}>
*
* If your onSubmit function returns a promise, the submitting property
* will be set to true until the promise has been resolved or rejected.
* If it is rejected with an object like
* new SubmissionError({ field1: 'error', field2: 'error' })
* then the submission errors will be added to each field (to the error
* prop) just like async validation errors are. If there is an error that
* is not specific to any field, but applicable to the entire form, you
* may pass that as if it were the error for a field called _error, and
* it will be given as the error prop.
*/
handleSubmit?(event: SyntheticEvent<any>): void; // same as ReactEventHandler
handleSubmit?(submit: SubmitHandler<FormData, P, S>): ReactEventHandler<any>;
/**
* Initializes the form data to the given values. All dirty and pristine
* state will be determined by comparing the current data with these
* initialized values.
*/
initialize?(data: FormData): void;
/**
* true if the form has validation errors. Opposite of valid.
*/
invalid?: boolean;
/**
* true if the form data is the same as its initialized values. Opposite
* of dirty.
*/
pristine?: boolean;
/**
* Resets all the values in the form to the initialized state, making it
* pristine again.
*/
reset?(): void;
/**
* Whether or not your form is currently submitting. This prop will only
* work if you have passed an onSubmit function that returns a promise. It
* will be true until the promise is resolved or rejected.
*/
submitting?: boolean;
/**
* Starts as false. If onSubmit is called, and fails to submit for any
* reason, submitFailed will be set to true. A subsequent successful
* submit will set it back to false.
*/
submitFailed?: boolean;
/**
* Starts as false. If onSubmit is called, and succeed to submit,
* submitSucceeded will be set to true. A subsequent unsuccessful
* submit will set it back to false.
*/
submitSucceeded?: boolean;
/**
* Marks the given fields as "touched" to show errors.
*/
touch?(...field: string[]): void;
/**
* Clears the "touched" flag for the given fields
*/
untouch?(...field: string[]): void;
/**
* true if the form passes validation (has no validation errors). Opposite
* of invalid.
*/
valid?: boolean;
/**
* A generic warning for the entire form given by the `_warning` key in the result from the
* synchronous warning function.
*/
warning?: string;
}

74
redux-form/lib/selectors.d.ts vendored Normal file
View File

@@ -0,0 +1,74 @@
import { DataShape, FormErrors } from "../index";
/**
* A "selector" API to make it easier to connect() to form values. Creates a selector
* function for your form that can be used with your field names.
*/
export function formValueSelector<State>(form: string, getFormState?: () => State): Selector<State>;
export interface Selector<State> {
(state: State, ...field: string[]): Object
}
/**
* Gets form data.
*/
export interface DataSelector {
<FormData extends DataShape, State>(formName: string): (state: State) => FormData;
<FormData extends DataShape>(formName: string): (state: any) => FormData;
}
/**
* Gets form errors.
*/
export interface ErrorSelector {
<FormData extends DataShape, State>(formName: string): (state: State) => FormErrors<FormData>;
<FormData extends DataShape>(formName: string): (state: any) => FormErrors<FormData>;
}
/**
* Gets boolean info from form.
*/
export interface BooleanSelector {
<State>(formName: string): (state: State) => boolean;
(formName: string): (state: any) => boolean;
}
/**
* Gets the form values. Shocking, right?
*/
export const getFormValues: DataSelector;
/**
* Returns the form synchronous validation errors.
*/
export const getFormSyncErrors: ErrorSelector;
/**
* Returns the form submit validation errors.
*/
export const getFormSubmitErrors: ErrorSelector;
/**
* Returns true if the form is dirty, i.e. the values have been altered
* from the original initialValues provided. The opposite of isPristine.
*/
export const isDirty: BooleanSelector;
/**
* Returns true if the form is pristine, i.e. the values have NOT been altered
* from the original initialValues provided. The opposite of isDirty.
*/
export const isPristine: BooleanSelector;
/**
* Returns true if the form is valid, i.e. has no sync, async, or submission
* errors. The opposite of isInvalid.
*/
export const isValid: BooleanSelector;
/**
* Returns true if the form is invalid, i.e. has sync, async, or submission
* errors. The opposite of isValid.
*/
export const isInvalid: BooleanSelector;

View File

@@ -0,0 +1,331 @@
import * as React from 'react';
import {Component, PropTypes} from 'react';
import {createStore, combineReducers} from 'redux';
import {reduxForm, reducer as reduxFormReducer, ReduxFormProps} from 'redux-form';
namespace SimpleForm {
export const fields = ['firstName', 'lastName', 'email', 'sex', 'favoriteColor', 'employed', 'notes'];
class SimpleForm extends Component<ReduxFormProps<SimpleForm & HTMLFormElement>, void> {
static propTypes = {
fields: PropTypes.object.isRequired,
handleSubmit: PropTypes.func.isRequired,
resetForm: PropTypes.func.isRequired,
submitting: PropTypes.bool.isRequired
};
render() {
const {
fields: {firstName, lastName, email, sex, favoriteColor, employed, notes},
handleSubmit,
resetForm,
submitting
} = this.props;
return (<form onSubmit={handleSubmit}>
<div>
<label>First Name</label>
<div>
<input type="text" placeholder="First Name" {...firstName}/>
</div>
</div>
<div>
<label>Last Name</label>
<div>
<input type="text" placeholder="Last Name" {...lastName}/>
</div>
</div>
<div>
<label>Email</label>
<div>
<input type="email" placeholder="Email" {...email}/>
</div>
</div>
<div>
<label>Sex</label>
<div>
<label>
<input type="radio" {...sex} value="male" checked={sex.value === 'male'}/> Male
</label>
<label>
<input type="radio" {...sex} value="female" checked={sex.value === 'female'}/> Female
</label>
</div>
</div>
<div>
<label>Favorite Color</label>
<div>
<select {...favoriteColor}>
<option></option>
<option value="ff0000">Red</option>
<option value="00ff00">Green</option>
<option value="0000ff">Blue</option>
</select>
</div>
</div>
<div>
<label>
<input type="checkbox" {...employed}/> Employed
</label>
</div>
<div>
<label>Notes</label>
<div>
<textarea
{...notes}
value={notes.value || ''}
/>
</div>
</div>
<div>
<button disabled={submitting} onClick={handleSubmit}>
{submitting ? <i/> : <i/>} Submit
</button>
<button disabled={submitting} onClick={resetForm}>
Clear Values
</button>
</div>
</form>
);
}
}
const Connected = reduxForm({
form: 'simple',
fields
})(SimpleForm);
}
namespace SynchronousValidation {
export const fields = ['username', 'email', 'age'];
const validate = (values:any) => {
const errors:any = {};
if (!values.username) {
errors.username = 'Required';
} else if (values.username.length > 15) {
errors.username = 'Must be 15 characters or less';
}
if (!values.email) {
errors.email = 'Required';
} else if (!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(values.email)) {
errors.email = 'Invalid email address';
}
if (!values.age) {
errors.age = 'Required';
} else if (isNaN(Number(values.age))) {
errors.age = 'Must be a number';
} else if (Number(values.age) < 18) {
errors.age = 'Sorry, you must be at least 18 years old';
}
return errors;
};
class SynchronousValidationForm extends Component<ReduxFormProps<SynchronousValidationForm & HTMLFormElement>, any> {
static propTypes = {
fields: PropTypes.object.isRequired,
handleSubmit: PropTypes.func.isRequired,
resetForm: PropTypes.func.isRequired,
submitting: PropTypes.bool.isRequired
};
render() {
const {fields: {username, email, age}, resetForm, handleSubmit, submitting} = this.props;
return (<form onSubmit={handleSubmit}>
<div>
<label>Username</label>
<div>
<input type="text" placeholder="Username" {...username}/>
</div>
{username.touched && username.error && <div>{username.error}</div>}
</div>
<div>
<label>Email</label>
<div>
<input type="text" placeholder="Email" {...email}/>
</div>
{email.touched && email.error && <div>{email.error}</div>}
</div>
<div>
<label>Age</label>
<div>
<input type="text" placeholder="Age" {...age}/>
</div>
{age.touched && age.error && <div>{age.error}</div>}
</div>
<div>
<button disabled={submitting} onClick={handleSubmit}>
{submitting ? <i/> : <i/>} Submit
</button>
<button disabled={submitting} onClick={resetForm}>
Clear Values
</button>
</div>
</form>
);
}
}
export const Connected = reduxForm({
form: 'synchronousValidation',
fields,
validate
})(SynchronousValidationForm);
}
namespace SumbitValidation {
export const fields = ['username', 'password'];
const submit = (values:any, dispatch:any) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (['john', 'paul', 'george', 'ringo'].indexOf(values.username) === -1) {
reject({username: 'User does not exist', _error: 'Login failed!'});
} else if (values.password !== 'redux-form') {
reject({password: 'Wrong password', _error: 'Login failed!'});
} else {
resolve();
}
}, 1000); // simulate server latency
});
};
class SubmitValidationForm extends Component<ReduxFormProps<SubmitValidationForm>, any> {
static propTypes = {
fields: PropTypes.object.isRequired,
handleSubmit: PropTypes.func.isRequired,
error: PropTypes.string,
resetForm: PropTypes.func.isRequired,
submitting: PropTypes.bool.isRequired
};
render() {
const {fields: {username, password}, error, resetForm, handleSubmit, submitting} = this.props;
return (<form onSubmit={submit => handleSubmit(submit as any)}>
<div>
<label>Username</label>
<div>
<input type="text" placeholder="Username" {...username}/>
</div>
{username.touched && username.error && <div>{username.error}</div>}
</div>
<div>
<label>Password</label>
<div>
<input type="password" placeholder="Password" {...password}/>
</div>
{password.touched && password.error && <div>{password.error}</div>}
</div>
{error && <div>{error}</div>}
<div>
<button disabled={submitting} onClick={handleSubmit}>
{submitting ? <i/> : <i/>} Log In
</button>
<button disabled={submitting} onClick={resetForm}>
Clear Values
</button>
</div>
</form>
);
}
}
export const Connected = reduxForm({
form: 'submitValidation',
fields
})(SubmitValidationForm);
}
namespace InitializingFromState {
const LOAD = 'redux-form-examples/account/LOAD';
const loadAccount = (data:any) => ({type: LOAD, data});
export const fields = ['firstName', 'lastName', 'age', 'bio'];
const data = { // used to populate "account" reducer when "Load" is clicked
firstName: 'John',
lastName: 'Doe',
age: '42',
bio: 'Born to write amazing Redux code.'
};
interface Props<T> extends ReduxFormProps<T> {
load: Function;
}
class InitializingFromStateForm extends Component<Props<InitializingFromStateForm & HTMLFormElement>, any> {
static propTypes = {
fields: PropTypes.object.isRequired,
handleSubmit: PropTypes.func.isRequired,
load: PropTypes.func.isRequired,
submitting: PropTypes.bool.isRequired
};
render() {
const {fields: {firstName, lastName, age, bio}, handleSubmit, load, submitting} = this.props;
return (
<div>
<div>
<button onClick={() => load(data)}>Load Account</button>
</div>
<form onSubmit={handleSubmit}>
<div>
<label>First Name</label>
<div>
<input type="text" placeholder="First Name" {...firstName}/>
</div>
</div>
<div>
<label>Last Name</label>
<div>
<input type="text" placeholder="Last Name" {...lastName}/>
</div>
</div>
<div>
<label>Age</label>
<div>
<input type="number" placeholder="Age" {...age}/>
</div>
</div>
<div>
<label>Occupation</label>
<div>
<textarea placeholder="Biography" {...bio}/>
</div>
</div>
<div>
<button disabled={submitting} onClick={handleSubmit}>
{submitting ? <i/> : <i/>} Submit
</button>
</div>
</form>
</div>
);
}
}
export const Connected = reduxForm({
form: 'initializing',
fields
},
(state:any) => ({ // mapStateToProps
initialValues: state.account.data // will pull state into form's initialValues
}),
{load: loadAccount} // mapDispatchToProps (will bind action creator to dispatch)
)(InitializingFromStateForm);
}
namespace NormalizingFormData {
const reducer = combineReducers({
// other reducers
form: reduxFormReducer.normalize({
normalizing: { // <--- name of the form
upper: value => value && value.toUpperCase(), // normalizer for 'upper' field
}
})
});
const store = createStore(reducer);
}

476
redux-form/redux-form-4.0.d.ts vendored Normal file
View File

@@ -0,0 +1,476 @@
// Type definitions for redux-form v4.0.3
// Project: https://github.com/erikras/redux-form
// Definitions by: Daniel Lytkin <https://github.com/aikoven>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
import * as React from 'react';
import { Component, SyntheticEvent, FormEventHandler } from 'react';
import { Dispatch, ActionCreator, Reducer } from 'redux';
export const actionTypes: {[actionName:string]: string};
export type FieldValue = any;
export type FormData = { [fieldName: string]: FieldValue };
export interface FieldProp<T> {
/**
* true if this field currently has focus. It will only work if you are
* passing onFocus to your input element.
*/
active: boolean;
/**
* An alias for value only when value is a boolean. Provided for
* convenience of destructuring the whole field object into the props of a
* form element.
*/
checked?: boolean;
/**
* true if the field value has changed from its initialized value.
* Opposite of pristine.
*/
dirty: boolean;
/**
* The error for this field if its value is not passing validation. Both
* synchronous and asynchronous validation errors will be reported here.
*/
error?: any;
/**
* The value for this field as supplied in initialValues to the form.
*/
initialValue: FieldValue;
/**
* true if the field value fails validation (has a validation error).
* Opposite of valid.
*/
invalid: boolean;
/**
* The name of the field. It will be the same as the key in the fields
* Object, but useful if bundling up a field to send down to a specialized
* input component.
*/
name: string;
/**
* A function to call when the form field loses focus. It expects to
* either receive the React SyntheticEvent or the current value of the
* field.
*/
onBlur(eventOrValue: SyntheticEvent<T> | FieldValue): void;
/**
* A function to call when the form field is changed. It expects to either
* receive the React SyntheticEvent or the new value of the field.
* @param eventOrValue
*/
onChange(eventOrValue: SyntheticEvent<T> | FieldValue): void;
/**
* A function to call when the form field receives a 'dragStart' event.
* Saves the field value in the event for giving the field it is dropped
* into.
*/
onDragStart(): void;
/**
* A function to call when the form field receives a drop event.
*/
onDrop(): void;
/**
* A function to call when the form field receives focus.
*/
onFocus(): void;
/**
* An alias for onChange. Provided for convenience of destructuring the
* whole field object into the props of a form element. Added to provide
* out-of-the-box support for Belle components' onUpdate API.
*/
onUpdate(): void;
/**
* true if the field value is the same as its initialized value. Opposite
* of dirty.
*/
pristine: boolean;
/**
* true if the field has been touched. By default this will be set when
* the field is blurred.
*/
touched: boolean;
/**
* true if the field value passes validation (has no validation errors).
* Opposite of invalid.
*/
valid: boolean;
/**
* The value of this form field. It will be a boolean for checkboxes, and
* a string for all other input types.
*/
value: FieldValue;
/**
* true if this field has ever had focus. It will only work if you are
* passing onFocus to your input element.
*/
visited: boolean;
}
export interface ReduxFormProps<T> {
/**
* The name of the currently active (with focus) field.
*/
active?: string;
/**
* A function that may be called to initiate asynchronous validation if
* asynchronous validation is enabled.
*/
asyncValidate?: Function;
/**
* true if the asynchronous validation function has been called but has not
* yet returned.
*/
asyncValidating?: boolean;
/**
* Destroys the form state in the Redux store. By default, this will be
* called for you in componentWillUnmount().
*/
destroyForm?(): void;
/**
* true if the form data has changed from its initialized values. Opposite
* of pristine.
*/
dirty?: boolean;
/**
* A generic error for the entire form given by the _error key in the
* result from the synchronous validation function, the asynchronous
* validation, or the rejected promise from onSubmit.
*/
error?: any;
/**
* The form data, in the form { field1: <Object>, field2: <Object> }. The
* field objects are meant to be destructured into your input component as
* props, e.g. <input type="text" {...field.name}/>. Each field Object has
* the following properties:
*/
fields?: { [field: string]: FieldProp<T> };
/**
* A function meant to be passed to <form onSubmit={handleSubmit}> or to
* <button onClick={handleSubmit}>. It will run validation, both sync and
* async, and, if the form is valid, it will call
* this.props.onSubmit(data) with the contents of the form data.
* Optionally, you may also pass your onSubmit function to handleSubmit
* which will take the place of the onSubmit prop. For example: <form
* onSubmit={handleSubmit(this.save.bind(this))}> If your onSubmit
* function returns a promise, the submitting property will be set to true
* until the promise has been resolved or rejected. If it is rejected with
* an object matching { field1: 'error', field2: 'error' } then the
* submission errors will be added to each field (to the error prop) just
* like async validation errors are. If there is an error that is not
* specific to any field, but applicable to the entire form, you may pass
* that as if it were the error for a field called _error, and it will be
* given as the error prop.
*/
handleSubmit?(event: SyntheticEvent<T>): void;
handleSubmit?(event: React.MouseEvent<HTMLButtonElement>): void;
handleSubmit?(submit: (data: FormData, dispatch?: Dispatch<any>) => Promise<any> | void): FormEventHandler<T>;
/**
* Initializes the form data to the given values. All dirty and pristine
* state will be determined by comparing the current data with these
* initialized values.
* @param data
*/
initializeForm?(data: FormData): void;
/**
* true if the form has validation errors. Opposite of valid.
*/
invalid?: boolean;
/**
* true if the form data is the same as its initialized values. Opposite
* of dirty.
*/
pristine?: boolean;
/**
* Resets all the values in the form to the initialized state, making it
* pristine again.
*/
resetForm?(): void;
/**
* The same formKey prop that was passed in. See Editing Multiple Records.
*/
formKey?: string;
/**
* Whether or not your form is currently submitting. This prop will only
* work if you have passed an onSubmit function that returns a promise. It
* will be true until the promise is resolved or rejected.
*/
submitting?: boolean;
/**
* Starts as false. If onSubmit is called, and fails to submit for any
* reason, submitFailed will be set to true. A subsequent successful
* submit will set it back to false.
*/
submitFailed?: boolean;
/**
* Marks the given fields as "touched" to show errors.
* @param field
*/
touch?(...field: string[]): void;
/**
* Marks all fields as "touched" to show errors. This will automatically
* happen on form submission.
*/
touchAll?(): void;
/**
* Clears the "touched" flag for the given fields
* @param field
*/
untouch?(...field: string[]): void;
/**
* Clears the "touched" flag for the all fields
*/
untouchAll?(): void;
/**
* true if the form passes validation (has no validation errors). Opposite
* of invalid.
*/
valid?: boolean;
/**
* All of your values in the form { field1: <string>, field2: <string> }.
*/
values?: FormData;
}
declare class ElementClass extends Component<any, any> {
}
interface ClassDecorator {
<T extends (typeof ElementClass)>(component: T): T;
}
interface MapStateToProps {
(state: any, ownProps?: any): any;
}
interface MapDispatchToPropsFunction {
(dispatch: Dispatch<any>, ownProps?: any): any;
}
interface MapDispatchToPropsObject {
[name: string]: ActionCreator<any>;
}
export declare function reduxForm(config: ReduxFormConfig,
mapStateToProps?: MapStateToProps,
mapDispatchToProps?: MapDispatchToPropsFunction | MapDispatchToPropsObject): ClassDecorator;
export interface ReduxFormConfig {
/**
* a list of all your fields in your form. You may change these dynamically
* at runtime.
*/
fields: string[];
/**
* the name of your form and the key to where your form's state will be
* mounted under the redux-form reducer
*/
form: string;
/**
* By default, async blur validation is only triggered if synchronous
* validation passes, and the form is dirty or was never initialized (or if
* submitting). Sometimes it may be desirable to trigger asynchronous
* validation even in these cases, for example if all validation is performed
* asynchronously and you want to display validation messages if a user does
* not change a field, but does touch and blur it. Setting
* alwaysAsyncValidate to true will always run asynchronous validation on
* blur, even if the form is pristine or sync validation fails.
*/
alwaysAsyncValidate?: boolean;
/**
* field names for which onBlur should trigger a call to the asyncValidate
* function. Defaults to [].
*
* See Asynchronous Blur Validation Example for more details.
*/
asyncBlurFields?: string[];
/**
* a function that takes all the form values, the dispatch function, and
* the props given to your component, and returns a Promise that will
* resolve if the validation is passed, or will reject with an object of
* validation errors in the form { field1: <String>, field2: <String> }.
*
* See Asynchronous Blur Validation Example for more details.
*/
asyncValidate?(values: FormData, dispatch: Dispatch<any>, props: Object): Promise<any>;
/**
* Whether or not to automatically destroy your form's state in the Redux
* store when your component is unmounted. Defaults to true.
*/
destroyOnUnmount?: boolean;
/**
* The key for your sub-form.
*
* See Multirecord Example for more details.
*/
formKey?: string;
/**
* A function that takes the entire Redux state and the reduxMountPoint
* (which defaults to "form"). It defaults to:
* (state, reduxMountPoint) => state[reduxMountPoint].
* The only reason you should provide this is if you are keeping your Redux
* state as something other than plain javascript objects, e.g. an
* Immutable.Map.
*/
getFormState?(state: any, reduxMountPoint: string): any;
/**
* The values with which to initialize your form in componentWillMount().
* Particularly useful when Editing Multiple Records, but can also be used
* with single-record forms. The values should be in the form
* { field1: 'value1', field2: 'value2' }.
*/
initialValues?: { [field: string]: FieldValue };
/**
* The function to call with the form data when the handleSubmit() is fired
* from within the form component. If you do not specify it as a prop here,
* you must pass it as a parameter to handleSubmit() inside your form
* component.
*/
onSubmit?(values: FormData, dispatch?: Dispatch<any>): any;
/**
* If true, the form values will be overwritten whenever the initialValues
* prop changes. If false, the values will not be overwritten if the form has
* previously been initialized. Defaults to true.
*/
overwriteOnInitialValuesChange?: boolean;
/**
* If specified, all the props normally passed into your decorated
* component directly will be passed under the key specified. Useful if
* using other decorator libraries on the same component to avoid prop
* namespace collisions.
*/
propNamespace?: string;
/**
* if true, the decorated component will not be passed any of the onX
* functions as props that will allow it to mutate the state. Useful for
* decorating another component that is not your form, but that needs to
* know about the state of your form.
*/
readonly?: boolean;
/**
* The use of this property is highly discouraged, but if you absolutely
* need to mount your redux-form reducer at somewhere other than form in
* your Redux state, you will need to specify the key you mounted it under
* with this property. Defaults to 'form'.
*
* See Alternate Mount Point Example for more details.
*/
reduxMountPoint?: string;
/**
* If set to true, a failed submit will return a rejected promise. Defaults
* to false. Only use this if you need to detect submit failures and run
* some code when a submit fails.
*/
returnRejectedSubmitPromise?: boolean;
/**
* marks fields as touched when the blur action is fired. Defaults to true.
*/
touchOnBlur?: boolean;
/**
* marks fields as touched when the change action is fired. Defaults to
* false.
*/
touchOnChange?: boolean;
/**
* a synchronous validation function that takes the form values and props
* passed into your component. If validation passes, it should return {}.
* If validation fails, it should return the validation errors in the form
* { field1: <String>, field2: <String> }.
* Defaults to (values, props) => ({}).
*/
validate?(values: FormData, props: { [fieldName: string]: FieldProp<any> }): Object;
}
/**
* @param value The current value of the field.
* @param previousValue The previous value of the field before the current
* action was dispatched.
* @param allValues All the values of the current form.
* @param previousAllValues All the values of the form before the current
* change. Useful to change one field based on a change in another.
*/
export type Normalizer =
(value: FieldValue, previousValue: FieldValue,
allValues: FormData, previousAllValues: FormData) => any;
export declare const reducer: {
(state: any, action: any): any;
/**
* Returns a form reducer that will also pass each form value through the
* normalizing functions provided. The parameter is an object mapping from
* formName to an object mapping from fieldName to a normalizer function.
* The normalizer function is given four parameters and expected to return
* the normalized value of the field.
*/
normalize(normalizers: {
[formName: string]: {
[fieldName: string]: Normalizer
}
}): Reducer<any>;
/**
* Returns a form reducer that will also pass each action through
* additional reducers specified. The parameter should be an object mapping
* from formName to a (state, action) => nextState reducer. The state
* passed to each reducer will only be the slice that pertains to that
* form.
*/
plugin(reducers: { [formName: string]: Reducer<any> }): Reducer<any>;
}

View File

@@ -1,331 +1,52 @@
import * as React from 'react';
import {Component, PropTypes} from 'react';
import {createStore, combineReducers} from 'redux';
import {reduxForm, reducer as reduxFormReducer, ReduxFormProps} from 'redux-form';
import { Component } from 'react';
import { Field, GenericField, reduxForm, WrappedFieldProps, BaseFieldProps } from "redux-form";
interface CustomComponentProps {
customProp: string;
}
namespace SimpleForm {
export const fields = ['firstName', 'lastName', 'email', 'sex', 'favoriteColor', 'employed', 'notes'];
class SimpleForm extends Component<ReduxFormProps<SimpleForm & HTMLFormElement>, void> {
static propTypes = {
fields: PropTypes.object.isRequired,
handleSubmit: PropTypes.func.isRequired,
resetForm: PropTypes.func.isRequired,
submitting: PropTypes.bool.isRequired
};
class CustomComponent extends Component<WrappedFieldProps<any> & CustomComponentProps, {}> {
render() {
const {
fields: {firstName, lastName, email, sex, favoriteColor, employed, notes},
handleSubmit,
resetForm,
submitting
} = this.props;
return (<form onSubmit={handleSubmit}>
<div>
<label>First Name</label>
return (
<div>
<input type="text" placeholder="First Name" {...firstName}/>
<span>{this.props.customProp}</span>
<p>Field: {this.props.meta.touched ? 'touched' : 'pristine'}</p>
<input {...this.props.input} />
</div>
</div>
<div>
<label>Last Name</label>
<div>
<input type="text" placeholder="Last Name" {...lastName}/>
</div>
</div>
<div>
<label>Email</label>
<div>
<input type="email" placeholder="Email" {...email}/>
</div>
</div>
<div>
<label>Sex</label>
<div>
<label>
<input type="radio" {...sex} value="male" checked={sex.value === 'male'}/> Male
</label>
<label>
<input type="radio" {...sex} value="female" checked={sex.value === 'female'}/> Female
</label>
</div>
</div>
<div>
<label>Favorite Color</label>
<div>
<select {...favoriteColor}>
<option></option>
<option value="ff0000">Red</option>
<option value="00ff00">Green</option>
<option value="0000ff">Blue</option>
</select>
</div>
</div>
<div>
<label>
<input type="checkbox" {...employed}/> Employed
</label>
</div>
<div>
<label>Notes</label>
<div>
<textarea
{...notes}
value={notes.value || ''}
/>
</div>
</div>
<div>
<button disabled={submitting} onClick={handleSubmit}>
{submitting ? <i/> : <i/>} Submit
</button>
<button disabled={submitting} onClick={resetForm}>
Clear Values
</button>
</div>
</form>
);
);
}
}
const Connected = reduxForm({
form: 'simple',
fields
})(SimpleForm);
}
namespace SynchronousValidation {
export const fields = ['username', 'email', 'age'];
const validate = (values:any) => {
const errors:any = {};
if (!values.username) {
errors.username = 'Required';
} else if (values.username.length > 15) {
errors.username = 'Must be 15 characters or less';
}
if (!values.email) {
errors.email = 'Required';
} else if (!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(values.email)) {
errors.email = 'Invalid email address';
}
if (!values.age) {
errors.age = 'Required';
} else if (isNaN(Number(values.age))) {
errors.age = 'Must be a number';
} else if (Number(values.age) < 18) {
errors.age = 'Sorry, you must be at least 18 years old';
}
return errors;
};
class SynchronousValidationForm extends Component<ReduxFormProps<SynchronousValidationForm & HTMLFormElement>, any> {
static propTypes = {
fields: PropTypes.object.isRequired,
handleSubmit: PropTypes.func.isRequired,
resetForm: PropTypes.func.isRequired,
submitting: PropTypes.bool.isRequired
};
class CustomField extends Component<BaseFieldProps & CustomComponentProps, {}> {
render() {
const {fields: {username, email, age}, resetForm, handleSubmit, submitting} = this.props;
return (<form onSubmit={handleSubmit}>
<div>
<label>Username</label>
<div>
<input type="text" placeholder="Username" {...username}/>
</div>
{username.touched && username.error && <div>{username.error}</div>}
</div>
<div>
<label>Email</label>
<div>
<input type="text" placeholder="Email" {...email}/>
</div>
{email.touched && email.error && <div>{email.error}</div>}
</div>
<div>
<label>Age</label>
<div>
<input type="text" placeholder="Age" {...age}/>
</div>
{age.touched && age.error && <div>{age.error}</div>}
</div>
<div>
<button disabled={submitting} onClick={handleSubmit}>
{submitting ? <i/> : <i/>} Submit
</button>
<button disabled={submitting} onClick={resetForm}>
Clear Values
</button>
</div>
</form>
);
const F = Field as new () => GenericField<CustomComponentProps, any>;
return <F component={CustomComponent} {...this.props} />;
}
}
export const Connected = reduxForm({
form: 'synchronousValidation',
fields,
validate
})(SynchronousValidationForm);
}
interface FormData {
foo: string;
custom: string;
}
namespace SumbitValidation {
export const fields = ['username', 'password'];
const submit = (values:any, dispatch:any) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (['john', 'paul', 'george', 'ringo'].indexOf(values.username) === -1) {
reject({username: 'User does not exist', _error: 'Login failed!'});
} else if (values.password !== 'redux-form') {
reject({password: 'Wrong password', _error: 'Login failed!'});
} else {
resolve();
}
}, 1000); // simulate server latency
});
};
class SubmitValidationForm extends Component<ReduxFormProps<SubmitValidationForm>, any> {
static propTypes = {
fields: PropTypes.object.isRequired,
handleSubmit: PropTypes.func.isRequired,
error: PropTypes.string,
resetForm: PropTypes.func.isRequired,
submitting: PropTypes.bool.isRequired
};
@reduxForm<FormData, any, any>({
form: 'myForm'
})
class MyForm extends Component<{}, {}> {
render() {
const {fields: {username, password}, error, resetForm, handleSubmit, submitting} = this.props;
return (<form onSubmit={submit => handleSubmit(submit as any)}>
<div>
<label>Username</label>
return (
<div>
<input type="text" placeholder="Username" {...username}/>
<Field
name='foo'
component='input'
placeholder='Foo bar'
/>
<CustomField
name='custom'
customProp='Hello'
/>
</div>
{username.touched && username.error && <div>{username.error}</div>}
</div>
<div>
<label>Password</label>
<div>
<input type="password" placeholder="Password" {...password}/>
</div>
{password.touched && password.error && <div>{password.error}</div>}
</div>
{error && <div>{error}</div>}
<div>
<button disabled={submitting} onClick={handleSubmit}>
{submitting ? <i/> : <i/>} Log In
</button>
<button disabled={submitting} onClick={resetForm}>
Clear Values
</button>
</div>
</form>
);
);
}
}
export const Connected = reduxForm({
form: 'submitValidation',
fields
})(SubmitValidationForm);
}
namespace InitializingFromState {
const LOAD = 'redux-form-examples/account/LOAD';
const loadAccount = (data:any) => ({type: LOAD, data});
export const fields = ['firstName', 'lastName', 'age', 'bio'];
const data = { // used to populate "account" reducer when "Load" is clicked
firstName: 'John',
lastName: 'Doe',
age: '42',
bio: 'Born to write amazing Redux code.'
};
interface Props<T> extends ReduxFormProps<T> {
load: Function;
}
class InitializingFromStateForm extends Component<Props<InitializingFromStateForm & HTMLFormElement>, any> {
static propTypes = {
fields: PropTypes.object.isRequired,
handleSubmit: PropTypes.func.isRequired,
load: PropTypes.func.isRequired,
submitting: PropTypes.bool.isRequired
};
render() {
const {fields: {firstName, lastName, age, bio}, handleSubmit, load, submitting} = this.props;
return (
<div>
<div>
<button onClick={() => load(data)}>Load Account</button>
</div>
<form onSubmit={handleSubmit}>
<div>
<label>First Name</label>
<div>
<input type="text" placeholder="First Name" {...firstName}/>
</div>
</div>
<div>
<label>Last Name</label>
<div>
<input type="text" placeholder="Last Name" {...lastName}/>
</div>
</div>
<div>
<label>Age</label>
<div>
<input type="number" placeholder="Age" {...age}/>
</div>
</div>
<div>
<label>Occupation</label>
<div>
<textarea placeholder="Biography" {...bio}/>
</div>
</div>
<div>
<button disabled={submitting} onClick={handleSubmit}>
{submitting ? <i/> : <i/>} Submit
</button>
</div>
</form>
</div>
);
}
}
export const Connected = reduxForm({
form: 'initializing',
fields
},
(state:any) => ({ // mapStateToProps
initialValues: state.account.data // will pull state into form's initialValues
}),
{load: loadAccount} // mapDispatchToProps (will bind action creator to dispatch)
)(InitializingFromStateForm);
}
namespace NormalizingFormData {
const reducer = combineReducers({
// other reducers
form: reduxFormReducer.normalize({
normalizing: { // <--- name of the form
upper: value => value && value.toUpperCase(), // normalizer for 'upper' field
}
})
});
const store = createStore(reducer);
}

View File

@@ -2,8 +2,11 @@
"compilerOptions": {
"module": "commonjs",
"target": "es6",
"experimentalDecorators": true,
"noImplicitAny": true,
"strictNullChecks": false,
"noImplicitReturns": true,
"noImplicitThis": true,
"strictNullChecks": true,
"baseUrl": "../",
"jsx": "react",
"typeRoots": [
@@ -17,4 +20,4 @@
"index.d.ts",
"redux-form-tests.tsx"
]
}
}