This repository has been archived by the owner on Nov 29, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[frontend-typescript] simple working example of forms
- Loading branch information
Showing
11 changed files
with
311 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,9 @@ | ||
import { combineReducers } from 'redux'; | ||
import {combineReducers, Reducer} from 'redux'; | ||
import {reducer as formReducer} from "redux-form"; | ||
|
||
export default function createReducer(asyncReducers: any) { // TODO: fix any | ||
export default function createReducer(asyncReducers: Reducer<any>) { | ||
return combineReducers({ | ||
form: formReducer, | ||
...asyncReducers | ||
}); | ||
} |
45 changes: 45 additions & 0 deletions
45
idontknow.web.ts/src/routes/DemoForm/DemoForm.component.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
import * as React from "react"; | ||
import {reduxForm, Field, InjectedFormProps} from "redux-form"; | ||
import {Button} from "antd"; | ||
// import {initialize} from "redux-form"; | ||
|
||
interface SimpleDemoFormProps { | ||
foo: string; | ||
test: string; | ||
} | ||
|
||
const SimpleDemoFormName: string = 'simpleDemoForm'; | ||
class SimpleDemoForm extends React.Component<InjectedFormProps<SimpleDemoFormProps>> { | ||
resetForm = () => { | ||
this.props.initialize({test: "test123"}); | ||
// initialize(SimpleDemoFormName, {test: "test123"}); // this is alternative way | ||
}; | ||
|
||
render() { | ||
const {} = this.props; | ||
|
||
return ( | ||
<div> | ||
Simple demo form | ||
|
||
<Button onClick={this.resetForm}> | ||
Reset form | ||
</Button> | ||
|
||
<Field | ||
name='foo' | ||
component='input' | ||
placeholder='Foo bar' | ||
/> | ||
<Field | ||
name='test' | ||
component='input' | ||
placeholder='Foo bar' | ||
/> | ||
|
||
</div> | ||
) | ||
} | ||
} | ||
|
||
export default reduxForm({form: SimpleDemoFormName })(SimpleDemoForm); |
13 changes: 13 additions & 0 deletions
13
idontknow.web.ts/src/routes/DemoForm/DemoForm.container.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import {connect} from 'react-redux'; | ||
import DemoFormComponent from './DemoForm.component'; | ||
|
||
const mapDispatchToProps = { | ||
onIncrement: () => (dispatch: any) => dispatch({ type: 'INCREMENT' }), | ||
onDecrement: () => (dispatch: any) => dispatch({ type: 'DECREMENT' }), | ||
}; | ||
|
||
const mapStateToProps = (state: any) => ({ | ||
|
||
}); | ||
|
||
export default connect(mapStateToProps, mapDispatchToProps)(DemoFormComponent) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
interface DemoFormReducerAction { | ||
type: string; | ||
} | ||
|
||
export default (state = {}, action: DemoFormReducerAction) => { | ||
switch (action.type) { | ||
default: | ||
return state; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,188 @@ | ||
import * as React from 'react'; | ||
import {Component, MouseEventHandler} from 'react'; | ||
// import { Action } from 'redux'; | ||
import { | ||
Field, GenericField, reduxForm, | ||
// WrappedFieldProps, | ||
BaseFieldProps, FormProps, FormAction, actionTypes, reducer, | ||
// ConfigProps, | ||
InjectedFormProps | ||
} from "redux-form"; | ||
import { input } from 'react-dom-factories'; | ||
|
||
// TODO: tests fail in TypeScript@next when strictFunctionTypes=true | ||
|
||
interface CustomComponentProps { | ||
customProp: string; | ||
meta: { touched: boolean } | ||
} | ||
|
||
class CustomComponent extends Component<BaseFieldProps & CustomComponentProps> { | ||
render() { | ||
const { | ||
// input, | ||
meta : { touched }, | ||
customProp | ||
} = this.props; | ||
|
||
return ( | ||
<div> | ||
<span>{customProp}</span> | ||
<p>Field: {touched ? 'touched' : 'pristine'}</p> | ||
<input {...input} /> | ||
</div> | ||
); | ||
} | ||
} | ||
|
||
class CustomField extends Component<BaseFieldProps & CustomComponentProps> { | ||
render() { | ||
const { customProp, name, meta } = this.props; | ||
const F = Field as new () => GenericField<CustomComponentProps>; | ||
return <F | ||
component={CustomComponent} | ||
customProp={customProp} | ||
name={name} | ||
meta={meta} | ||
/>; | ||
} | ||
} | ||
|
||
export interface FormData { | ||
foo: string; | ||
custom: string; | ||
} | ||
|
||
// const config1: ConfigProps<FormData, {}> = { | ||
// form: 'myForm' | ||
// }; | ||
// @reduxForm<FormData, {}>(config1) | ||
class MyForm extends Component<InjectedFormProps<any, any>> { | ||
render() { | ||
return ( | ||
<div> | ||
<Field | ||
name='foo' | ||
component='input' | ||
placeholder='Foo bar' | ||
/> | ||
<CustomField | ||
name='custom' | ||
customProp='Hello' | ||
meta={{touched: false}} | ||
/> | ||
</div> | ||
); | ||
} | ||
} | ||
export const MyFormWrapped = reduxForm({form: "myForm"})(MyForm); | ||
|
||
const MyStatelessFunctionalComponent: React.SFC<any> = () => <div/>; | ||
|
||
reduxForm({ | ||
form: 'mySFCForm' | ||
})(MyStatelessFunctionalComponent); | ||
|
||
class MyReusableForm extends Component<InjectedFormProps<{}, {}>> { | ||
render() { | ||
return ( | ||
<div> | ||
<Field | ||
name='foo' | ||
component='input' | ||
placeholder='Foo bar' | ||
/> | ||
</div> | ||
); | ||
} | ||
} | ||
export const MyReusableFormWrapper = reduxForm({form: "myForm"})(MyReusableForm); | ||
|
||
reduxForm({ | ||
form: 'forceUnregisterOnMountForm', | ||
forceUnregisterOnUnmount: true | ||
}); | ||
|
||
// adapted from: http://redux-form.com/6.0.0-alpha.4/examples/initializeFromState/ | ||
|
||
|
||
export interface DataShape { | ||
firstName: string; | ||
} | ||
|
||
// interface Props extends FormProps<DataShape, {}, {}> {} | ||
|
||
interface TestProps { | ||
reset: MouseEventHandler<HTMLButtonElement>; | ||
submitting: boolean; | ||
handleSubmit: MouseEventHandler<HTMLFormElement>; | ||
pristine: boolean; | ||
} | ||
export let InitializeFromStateFormFunction = (props: FormProps & TestProps) => { | ||
const { handleSubmit, pristine, reset, submitting } = props; | ||
return ( | ||
<form onSubmit={handleSubmit}> | ||
<div> | ||
<label>First Name</label> | ||
<div> | ||
<Field name="firstName" component={input} type="text" placeholder="First Name"/> | ||
</div> | ||
</div> | ||
<div> | ||
<button type="submit" disabled={pristine || submitting}>Submit</button> | ||
<button type="button" disabled={pristine || submitting} onClick={reset}>Undo Changes</button> | ||
</div> | ||
</form> | ||
); | ||
}; | ||
|
||
// // Decorate with reduxForm(). It will read the initialValues prop provided by connect() | ||
// const DecoratedInitializeFromStateFormFunction = reduxForm({ | ||
// form: 'initializeFromState' // a unique identifier for this form | ||
// })(InitializeFromStateFormFunction); | ||
|
||
// // You have to connect() to any reducers that you wish to connect to yourself | ||
// const ConnectedDecoratedInitializeFromStateFormFunction = connect( | ||
// state => ({ | ||
// initialValues: state.account.data // pull initial values from account reducer | ||
// }), | ||
// )(DecoratedInitializeFromStateFormFunction); | ||
// | ||
// // React ComponentClass instead of StatelessComponent | ||
// | ||
// class InitializeFromStateFormClass extends React.Component<FormProps & TestProps & DispatchProp<any>> { | ||
// render() { | ||
// return InitializeFromStateFormFunction(this.props); | ||
// } | ||
// } | ||
// | ||
// // Decorate with reduxForm(). It will read the initialValues prop provided by connect() | ||
// const DecoratedInitializeFromStateFormClass = reduxForm<DataShape, {}>({ | ||
// form: 'initializeFromState' // a unique identifier for this form | ||
// })(InitializeFromStateFormClass); | ||
// | ||
// // You have to connect() to any reducers that you wish to connect to yourself | ||
// const mapStateToProps = (state: any) => ({ | ||
// initialValues: { firstName: state.account.data.firstName } // pull initial values from account reducer | ||
// } as {initialValues?: Partial<DataShape>}); | ||
// const ConnectedDecoratedInitializeFromStateFormClass = connect(mapStateToProps)(DecoratedInitializeFromStateFormClass); | ||
|
||
reducer({}, { | ||
type: 'ACTION' | ||
}); | ||
|
||
reducer.plugin({ | ||
myform: (state: any, action: FormAction) => { | ||
if (action.type === actionTypes.CHANGE && action.meta.form === 'securitySettings') { | ||
return { | ||
...state, | ||
values: { | ||
...state.values, | ||
downloadLinkAutoPassword: true, | ||
}, | ||
}; | ||
} else { | ||
return state; | ||
} | ||
} | ||
}); |
Empty file.
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import {injectAsyncReducer} from '../../config/store'; | ||
import CounterReducer from './DemoForm.reducer'; | ||
|
||
export default (store: any): any => import('./DemoForm.container').then((component) => { | ||
injectAsyncReducer(store, 'counter', CounterReducer); | ||
return component; | ||
}); |
Oops, something went wrong.