-
Notifications
You must be signed in to change notification settings - Fork 0
Keep track if a field is pristine or not. #6
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,44 +1,71 @@ | ||
| export interface FieldState { | ||
| value: any; | ||
| validationError?: string; | ||
| pristine: boolean; | ||
| } | ||
|
|
||
| export class Form { | ||
|
|
||
| private values: { [key: string]: any } = {}; | ||
| private fieldStates: { [key: string]: FieldState } = {}; | ||
| private fieldListeners: { [fieldName: string]: Array<(value: any) => void> } = {}; | ||
|
|
||
| private validationErrors: { [fieldName: string]: any } = {}; | ||
| public getFieldState(fieldName: string): FieldState | undefined { | ||
| return this.fieldStates[fieldName]; | ||
| } | ||
|
|
||
| private fieldListeners: { [fieldName: string]: Array<(value: any) => void> } = {}; | ||
| public initialiseFieldValues(values: { [fieldName: string]: any }) { | ||
| const fieldNames = Object.keys(values); | ||
| fieldNames.forEach((fieldName) => { | ||
| this.updateFieldValue(fieldName, values[fieldName], true); | ||
| }); | ||
|
|
||
| public getFieldValue(fieldName: string): any { | ||
| return this.values[fieldName] || ''; | ||
| this.triggerMultipleFieldListeners(fieldNames); | ||
| } | ||
|
|
||
| public setFieldValues(values: { [fieldName: string]: any }) { | ||
| const fieldNames = Object.keys(values); | ||
| fieldNames.forEach((fieldName) => { | ||
| this.values[fieldName] = values[fieldName]; | ||
| delete this.validationErrors[fieldName]; | ||
| this.updateFieldValue(fieldName, values[fieldName], false); | ||
| }); | ||
|
|
||
| this.triggerMultipleFieldListeners(fieldNames); | ||
| } | ||
|
|
||
| public initialiseFieldValue(fieldName: string, value: any) { | ||
| this.updateFieldValue(fieldName, value, true); | ||
|
|
||
| this.triggerFieldListeners(fieldName); | ||
| } | ||
|
|
||
| public setFieldValue(fieldName: string, value: any) { | ||
| this.values[fieldName] = value; | ||
| delete this.validationErrors[fieldName]; | ||
| this.updateFieldValue(fieldName, value, false); | ||
|
|
||
| this.triggerFieldListeners(fieldName); | ||
| } | ||
|
|
||
| private updateFieldValue(fieldName: string, value: any, pristineValue: boolean) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm expecting the value to be named
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. agree |
||
| this.fieldStates[fieldName] = { | ||
| ...this.fieldStates[fieldName], | ||
| value, | ||
| validationError: undefined, | ||
| pristine: pristineValue | ||
| }; | ||
| } | ||
|
|
||
| public setValidationErrors(errors: { [fieldName: string]: string }) { | ||
| this.validationErrors = errors; | ||
| const fieldNames = Object.keys(errors); | ||
|
|
||
| const fieldNames = Object.keys(this.validationErrors); | ||
| this.triggerMultipleFieldListeners(fieldNames); | ||
| } | ||
| fieldNames.forEach((fieldName) => { | ||
| this.fieldStates[fieldName] = { | ||
| ...this.fieldStates[fieldName], | ||
| validationError: errors[fieldName] | ||
| }; | ||
| }); | ||
|
|
||
| public getValidationError(fieldName: string): string | undefined { | ||
| return this.validationErrors[fieldName]; | ||
| this.triggerMultipleFieldListeners(fieldNames); | ||
| } | ||
|
|
||
| public listenForFieldChange(fieldName: string, callback: (value: any) => void) { | ||
| public listenForFieldChange(fieldName: string, callback: (value: FieldState) => void) { | ||
| if (typeof this.fieldListeners[fieldName] === 'undefined') { | ||
| this.fieldListeners[fieldName] = []; | ||
| } | ||
|
|
@@ -53,7 +80,7 @@ export class Form { | |
|
|
||
| private triggerFieldListeners(fieldName: string) { | ||
| if (typeof this.fieldListeners[fieldName] !== 'undefined') { | ||
| this.fieldListeners[fieldName].forEach((callback) => callback(this.getFieldValue(fieldName))); | ||
| this.fieldListeners[fieldName].forEach((callback) => callback(this.getFieldState(fieldName))); | ||
| } | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,6 @@ | ||
| import * as React from 'react'; | ||
| import {FormProps} from './bonn'; | ||
| import {FieldState} from '../business/form'; | ||
| export interface FieldProps { | ||
| value: any; | ||
| validationError: string | undefined; | ||
|
|
@@ -20,7 +21,9 @@ export function Field<Props>(WrappedComponent: IncomingField<Props>, | |
| return class extends React.Component<Props & OwnProps & FormProps, { value: any }> { | ||
|
|
||
| public state: { value: any } = { | ||
| value: this.props.form.getFieldValue(this.getFieldName()) | ||
| value: (typeof this.props.form.getFieldState(this.getFieldName()) !== 'undefined') | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Might be better to put this in a seperate method, unreadable like this, if you do that you can extract the |
||
| ? (this.props.form.getFieldState(this.getFieldName()) as FieldState).value | ||
| : '' | ||
| }; | ||
|
|
||
| public getFieldName(): string { | ||
|
|
@@ -36,13 +39,13 @@ export function Field<Props>(WrappedComponent: IncomingField<Props>, | |
|
|
||
| public componentWillMount() { | ||
| if (typeof this.props.value !== 'undefined') { | ||
| this.props.form.setFieldValue(this.getFieldName(), this.props.value); | ||
| this.props.form.initialiseFieldValue(this.getFieldName(), this.props.value); | ||
| } | ||
| } | ||
|
|
||
| public componentWillUpdate(nextProps: Props & OwnProps & FormProps) { | ||
| if (typeof nextProps.value !== 'undefined' && this.props.value !== nextProps.value) { | ||
| this.props.form.setFieldValue(this.getFieldName(), nextProps.value); | ||
| this.props.form.initialiseFieldValue(this.getFieldName(), nextProps.value); | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -59,10 +62,11 @@ export function Field<Props>(WrappedComponent: IncomingField<Props>, | |
| } | ||
|
|
||
| public render() { | ||
| const fieldState = this.props.form.getFieldState(this.getFieldName()); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why are we storing a copy of the value if we're still going to call
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good question. This is following the initial design we had and maybe should change. The
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This might be the textbook use-case for
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So we would push the local state to the bonn form, so instead of setting the local state in the
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ehm, this is already what we're doing.. I just say we remove the |
||
| return <WrappedComponent | ||
| {...this.props} | ||
| value={this.state.value} | ||
| validationError={this.props.form.getValidationError(this.getFieldName())} | ||
| validationError={(typeof fieldState !== 'undefined') ? fieldState.validationError : undefined} | ||
| onChange={this.handleChange.bind(this)} | ||
| />; | ||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
initialize?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
uk vs us? which do we choose?
initializeis US definition with a s is UKThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah true, I think we should opt for US, I'm not so much of a tea drinker
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh ya bloody imbecile