Skip to content

Commit 9647165

Browse files
CoreField abstracted from BaseField.
1 parent e43441b commit 9647165

File tree

12 files changed

+326
-304
lines changed

12 files changed

+326
-304
lines changed
Lines changed: 9 additions & 283 deletions
Original file line numberDiff line numberDiff line change
@@ -1,295 +1,21 @@
1-
import * as React from "react";
2-
import * as actionEmitter from "action-emitter";
3-
import * as PropTypes from "prop-types";
4-
51
import {
6-
FieldProps,
72
FieldValue,
8-
FieldValidationType,
9-
FieldFormatValueCallback,
10-
FieldNormalizeValueCallback,
11-
FieldParseValueCallback,
12-
FieldStateRecord
3+
FieldProps
134
} from "../contracts/field";
14-
import * as ValueHelpers from "../utils/value-helpers";
15-
import { FormContextPropsObject } from "../contracts/form";
16-
import { FormStore } from "../stores/form-store";
17-
import { FormStoreStateRecord } from "../contracts/form-store";
18-
import * as FormStoreActions from "../actions/form-store";
19-
// import { FieldsGroupContextProps } from "../contracts/fields-group";
20-
import { FSHContainer } from "../stores/form-stores-handler";
5+
import { CoreField, CoreFieldState } from "./core-field";
216

22-
export interface BaseFieldState {
23-
Field?: FieldStateRecord;
24-
Form?: FormStoreStateRecord;
25-
Value?: FieldValue;
26-
}
7+
export interface BaseFieldState extends CoreFieldState {
278

28-
export interface ParentContext {
29-
FormId: string;
30-
FormProps: FormContextPropsObject;
31-
FieldsGroupId: string;
32-
// FieldsGroupProps: FieldsGroupContextProps;
339
}
3410

35-
36-
export abstract class BaseField<TProps extends FieldProps, TState extends BaseFieldState>
37-
extends React.Component<TProps, TState> {
38-
public context: ParentContext;
39-
40-
static contextTypes: PropTypes.ValidationMap<ParentContext> = {
41-
FormId: PropTypes.string,
42-
FormProps: PropTypes.object,
43-
FieldsGroupId: PropTypes.string,
44-
// FieldsGroupProps: PropTypes.object
45-
};
46-
47-
static defaultProps: FieldProps = {
48-
// Empty string checked to have value in componentWillMount
49-
name: "",
50-
validationType: FieldValidationType.OnFieldRegistered |
51-
FieldValidationType.OnValueChange |
52-
FieldValidationType.OnPropsChange,
53-
// By default, fields data should be retained, even if the field is unmounted
54-
destroyOnUnmount: false
55-
};
56-
57-
protected get FormId(): string {
58-
return this.context.FormId;
59-
}
60-
61-
protected get FormStore(): FormStore {
62-
return FSHContainer.FormStoresHandler.GetStore(this.FormId);
63-
}
64-
65-
protected get FieldId(): string {
66-
return this.FormStore.GetFieldId(this.props.name, this.FieldsGroupId);
67-
}
68-
69-
protected get FieldsGroupId(): string {
70-
return this.context.FieldsGroupId;
71-
}
72-
73-
protected StoreEventSubscription: actionEmitter.EventSubscription;
74-
75-
componentWillMount() {
76-
// props.name MUST have a proper value
77-
if (this.props.name == null || this.props.name === "") {
78-
throw new Error("simplr-forms-core: A proper field name must be given (undefined and empty string are not valid).");
79-
}
80-
81-
if (this.FormId == null) {
82-
throw new Error("simplr-forms-core: Field must be used inside a Form component.");
83-
}
84-
this.StoreEventSubscription =
85-
this.FormStore.addListener<FormStoreActions.StateUpdated>(
86-
FormStoreActions.StateUpdated,
87-
this.OnStoreUpdated.bind(this));
88-
this.registerFieldInFormStore();
89-
}
90-
91-
componentWillReceiveProps(nextProps: FieldProps) {
92-
// Check if field name has not been changed
93-
if (this.props.name !== nextProps.name) {
94-
throw new Error(`simplr-forms-core: Field name must be constant`);
95-
}
96-
97-
this.FormStore.UpdateProps(this.FieldId, nextProps);
98-
}
99-
100-
componentWillUnmount() {
101-
if (this.StoreEventSubscription != null) {
102-
this.StoreEventSubscription.remove();
103-
}
104-
if (this.FormStore != null && this.props.destroyOnUnmount) {
105-
this.FormStore.UnregisterField(this.FieldId);
106-
}
107-
}
108-
109-
/**
110-
* ========================
111-
* Protected methods
112-
* ========================
113-
*/
114-
115-
/**
116-
* Is field currently controlled.
117-
*
118-
* @readonly
119-
* @protected
120-
*
121-
* @memberOf BaseField
122-
*/
123-
protected get IsControlled() {
124-
return false;
125-
}
126-
127-
/**
128-
* Current or default field value.
129-
*
130-
* @readonly
131-
* @protected
132-
* @type {FieldValue}
133-
* @memberOf BaseField
134-
*/
135-
protected get Value(): FieldValue {
136-
// If field is defined
137-
if (this.state != null && this.state.Value != null) {
138-
// Return its value
139-
return this.state.Value;
140-
}
141-
142-
// Return default value
143-
return this.RawDefaultValue;
144-
}
145-
146-
protected ProcessValueBeforeStore(value: FieldValue) {
147-
// Parse and normalize value
148-
return this.NormalizeValue(this.ParseValue(value));
149-
}
150-
151-
protected ProcessValueFromStore(value: FieldValue) {
152-
return this.FormatValue(value);
153-
}
154-
155-
protected ParseValue(value: FieldValue): FieldValue {
156-
if (this.props.parseValue != null) {
157-
const parser = this.props.parseValue as FieldParseValueCallback;
158-
return parser(value);
159-
}
160-
return ValueHelpers.ParseValue(
161-
React.Children.toArray(this.props.children) as Array<JSX.Element>,
162-
value
163-
);
164-
}
165-
166-
protected FormatValue(value: FieldValue): FieldValue {
167-
if (this.props.formatValue != null) {
168-
const formatter = this.props.formatValue as FieldFormatValueCallback;
169-
return formatter(value);
170-
}
171-
172-
return ValueHelpers.FormatValue(
173-
React.Children.toArray(this.props.children) as Array<JSX.Element>,
174-
value
175-
);
176-
}
177-
178-
protected NormalizeValue(value: FieldValue): FieldValue {
179-
if (this.props.normalizeValue != null) {
180-
const normalizer = this.props.normalizeValue as FieldNormalizeValueCallback;
181-
return normalizer(value);
182-
}
183-
184-
return ValueHelpers.NormalizeValue(
185-
React.Children.toArray(this.props.children) as Array<JSX.Element>,
186-
value
187-
);
188-
}
189-
190-
protected ChildrenToRender() {
191-
throw new Error("simplr-forms-core: Not implemented. Needs to filter out Validators, Modifiers and Normalizers.");
192-
}
193-
194-
protected OnStoreUpdated() {
195-
const newFormState = this.FormStore.GetState();
196-
const newFieldState = this.FormStore.GetField(this.FieldId);
197-
198-
const isStateDifferent = this.state == null ||
199-
this.state.Field !== newFieldState ||
200-
this.state.Form !== newFormState;
201-
202-
if (isStateDifferent && newFieldState != null) {
203-
this.setState((state: TState) => {
204-
if (state == null) {
205-
state = {} as any;
206-
}
207-
state.Form = newFormState;
208-
state.Field = newFieldState;
209-
state.Value = this.ProcessValueFromStore(newFieldState.Value);
210-
return state;
211-
});
212-
}
213-
}
214-
215-
protected OnValueChange(newValue: FieldValue, processValue: boolean = true) {
216-
// Noop if the component is controlled from outside
217-
if (this.IsControlled) {
218-
return;
219-
}
220-
221-
if (processValue) {
222-
newValue = this.ProcessValueBeforeStore(newValue);
223-
}
224-
225-
this.FormStore.ValueChanged(this.FieldId, newValue);
226-
}
227-
228-
/**
229-
* ========================
230-
* Abstract methods
231-
* ========================
232-
*/
233-
234-
/**
235-
* React Component's render method
236-
*/
237-
abstract render(): JSX.Element | null;
238-
239-
/**
240-
* Default field value.
241-
*
242-
* @readonly
243-
* @protected
244-
*
245-
* @memberOf BaseField
246-
*/
11+
export abstract class BaseField<TProps extends FieldProps, TState extends BaseFieldState> extends CoreField<TProps, TState> {
24712
protected abstract get RawDefaultValue(): FieldValue;
24813

249-
/**
250-
* Initial value.
251-
*/
252-
protected abstract get RawInitialValue(): FieldValue;
253-
254-
/**
255-
* Value before render.
256-
* Most common usage is for getting value from field props.
257-
*
258-
* @readonly
259-
* @protected
260-
* @type {(FieldContracts.ValueTypes | any)}
261-
* @memberOf BaseField
262-
*/
263-
protected abstract get RawValue(): FieldValue;
264-
265-
/**
266-
* ========================
267-
* Local helper methods
268-
* ========================
269-
*/
270-
271-
/**
272-
* Registers a field in FormStore or throws if the field was already registered
273-
*
274-
* @private
275-
*
276-
* @memberOf BaseField
277-
*/
278-
private registerFieldInFormStore() {
279-
if (this.FormStore.HasField(this.FieldId)) {
280-
throw new Error(`simplr-forms-core: Duplicate field id '${this.FieldId}'`);
281-
}
14+
protected get RawInitialValue(): FieldValue {
15+
return this.props.initialValue;
16+
}
28217

283-
const defaultValue = this.ProcessValueBeforeStore(this.RawDefaultValue);
284-
const initialValue = this.ProcessValueBeforeStore(this.RawInitialValue);
285-
const value = this.ProcessValueBeforeStore(this.RawValue);
286-
this.FormStore.RegisterField(
287-
this.FieldId,
288-
defaultValue,
289-
initialValue,
290-
value,
291-
this.props,
292-
this.FieldsGroupId
293-
);
18+
protected get RawValue(): FieldValue {
19+
return this.props.value;
29420
}
29521
}

0 commit comments

Comments
 (0)