Skip to content

Commit

Permalink
feat(core): support pass FormPathPattern to createMutators, and fix s…
Browse files Browse the repository at this point in the history
…ome typings (#728)

* fix(schema-renderer): fix linkage can not access expressionScope

* feat(core): support pass FormPathPattern to createMutators, and fix some typings

* fix(core): fix typings
  • Loading branch information
janryWang authored Mar 17, 2020
1 parent 27de669 commit c0798c6
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 142 deletions.
10 changes: 10 additions & 0 deletions docs/zh-cn/schema-develop/form-path.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,15 +97,19 @@ import {
Reset
} from '@formily/antd' // 或者 @formily/next
import { ArrayTable, Input } from '@formily/antd-components'
import {Button} from 'antd'
import Printer from '@formily/printer'
import 'antd/dist/antd.css'

const { onFieldValueChange$ } = FormEffectHooks

const actions = createFormActions()

const App = () => {
return (
<Printer>
<SchemaForm
actions={actions}
components={{ ArrayTable, Input }}
onSubmit={values => {
console.log(values)
Expand Down Expand Up @@ -139,6 +143,12 @@ const App = () => {
<Field type="string" name="bb" title="BB" x-component="Input" />
</Field>
</Field>
<FormButtonGroup>
<Button onClick={()=>{
const mutators = actions.createMutators('array')
mutators.push({})
}}>Add</Button>
</FormButtonGroup>
</SchemaForm>
</Printer>
)
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
"@types/jest": "^24.0.18",
"@types/node": "^12.6.8",
"@typescript-eslint/eslint-plugin": "^2.20.0",
"@typescript-eslint/parser": "^2.20.0",
"@typescript-eslint/parser": "~2.23.0",
"all-contributors-cli": "^6.1.2",
"antd": "^4.0.0",
"awesome-typescript-loader": "^5.2.1",
Expand Down
38 changes: 21 additions & 17 deletions packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ import {
IFormCreatorOptions,
IFieldStateProps,
IVirtualFieldStateProps,
IForm,
IFormSubmitResult,
IFormValidateResult,
IFormResetOptions,
Expand All @@ -50,7 +49,7 @@ export * from './types'

export function createForm<FieldProps, VirtualFieldProps>(
options: IFormCreatorOptions = {}
): IForm {
) {
function onGraphChange({ type, payload }) {
heart.publish(LifeCycleTypes.ON_FORM_GRAPH_CHANGE, graph)
if (type === 'GRAPH_NODE_WILL_UNMOUNT') {
Expand Down Expand Up @@ -725,12 +724,23 @@ export function createForm<FieldProps, VirtualFieldProps>(
function getFormInitialValuesIn(path: FormPathPattern) {
return getFormIn(path, 'initialValues')
}

function createMutators(field: IField) {
if (!isField(field)) {
throw new Error(
'The `createMutators` can only accept FieldState instance.'
)
/**
*
* @param input IField | FormPathPattern
*/
function createMutators(input: any) {
let field: IField
if (!isField(input)) {
const selected = graph.select(input)
if (selected) {
field = selected
} else {
throw new Error(
'The `createMutators` can only accept FieldState instance or FormPathPattern.'
)
}
} else {
field = input
}
function setValue(...values: any[]) {
field.setState((state: IFieldState<FieldProps>) => {
Expand Down Expand Up @@ -808,8 +818,8 @@ export function createForm<FieldProps, VirtualFieldProps>(
})
}

function swapAfterState(start: number, arrayLength: number) {
for (let i = arrayLength - 1; i >= start + 1; i--) {
function swapAfterState(start: number, arrayLength: number, step = 1) {
for (let i = arrayLength - 1; i >= start + 1; i -= step) {
swapState(i, i - 1)
}
}
Expand Down Expand Up @@ -876,13 +886,7 @@ export function createForm<FieldProps, VirtualFieldProps>(
)
},
unshift(value: any) {
const arr = toArr(getValue()).slice()
arr.unshift(value)
setValue(arr)
onGraphChange(() => {
swapAfterState(0, arr.length)
})
return arr
return mutators.insert(0, value)
},
shift() {
const arr = toArr(getValue()).slice()
Expand Down
59 changes: 3 additions & 56 deletions packages/core/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
ValidateNodeResult,
ValidateFieldOptions
} from '@formily/validator'
import { createForm } from './index'
import { FormLifeCycle } from './shared/lifecycle'
import { Draft } from 'immer'

Expand Down Expand Up @@ -308,24 +309,7 @@ export type IFormExtendedValidateFieldOptions = ValidateFieldOptions & {
hostRendering?: boolean
}

export interface IMutators {
change(...values: any[]): any
focus(): void
blur(): void
push(value?: any): any[]
pop(): any[]
insert(index: number, value: any): any[]
remove(index: number | string): any
unshift(value: any): any[]
shift(): any[]
move($from: number, $to: number): any[]
moveDown(index: number): any[]
moveUp(index: number): any[]
validate(
opts?: IFormExtendedValidateFieldOptions
): Promise<IFormValidateResult>
exist(index?: number | string): boolean
}
export type IMutators = ReturnType<IForm['createMutators']>

export interface IModel<S = {}, P = {}> extends Subscribable {
state: S
Expand Down Expand Up @@ -363,41 +347,4 @@ export type IVirtualField = IModel<IVirtualFieldState, IVirtualFieldStateProps>

export type IFormInternal = IModel<IFormState, IFormStateProps>

export interface IForm {
submit(
onSubmit?: (values: IFormState['values']) => any | Promise<any>
): Promise<IFormSubmitResult>
clearErrors: (pattern?: FormPathPattern) => void
hasChanged(target: any, path: FormPathPattern): boolean
reset(options?: IFormResetOptions): Promise<void | IFormValidateResult>
validate(
path?: FormPathPattern,
options?: IFormExtendedValidateFieldOptions
): Promise<IFormValidateResult>
setFormState(callback?: (state: IFormState) => any, silent?: boolean): void
getFormState(callback?: (state: IFormState) => any): any
setFieldState(
path: FormPathPattern,
callback?: (state: IFieldUserState) => void,
silent?: boolean
): void
getFieldState(
path: FormPathPattern,
callback?: (state: IFieldState) => any
): any
unsafe_do_not_use_transform_data_path(path: FormPathPattern): FormPathPattern //eslint-disable-line
registerField(props: IFieldStateProps): IField
registerVirtualField(props: IVirtualFieldStateProps): IVirtualField
createMutators(field: IField): IMutators
getFormGraph(): IFormGraph
setFormGraph(graph: IFormGraph): void
subscribe(callback?: FormHeartSubscriber): number
unsubscribe(id: number): void
notify: <T>(type: string, payload?: T) => void
isHostRendering: () => boolean
hostUpdate: (callback?: () => any) => any
setFieldValue(path?: FormPathPattern, value?: any): void
getFieldValue(path?: FormPathPattern): any
setFieldInitialValue(path?: FormPathPattern, value?: any): void
getFieldInitialValue(path?: FormPathPattern): any
}
export type IForm = ReturnType<typeof createForm>
2 changes: 2 additions & 0 deletions packages/react/src/shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export const createFormActions = (): IFormActions => {
'setFormGraph',
'subscribe',
'unsubscribe',
'createMutators',
'isHostRendering',
'hostUpdate',
'notify',
Expand Down Expand Up @@ -62,6 +63,7 @@ export const createAsyncFormActions = (): IFormAsyncActions =>
'subscribe',
'unsubscribe',
'isHostRendering',
'createMutators',
'hostUpdate',
'notify',
'dispatch',
Expand Down
85 changes: 17 additions & 68 deletions packages/react/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,12 @@ import {
IForm,
IMutators,
IFieldState,
IFieldUserState,
IFormValidateResult,
IFormState,
IFormResetOptions,
IFormSubmitResult,
FormHeartSubscriber,
IFormGraph,
IField,
IVirtualFieldState,
IVirtualField
} from '@formily/core'
import { FormPathPattern } from '@formily/shared'
import { Observable } from 'rxjs/internal/Observable'
export * from '@formily/core'

Expand Down Expand Up @@ -144,70 +138,25 @@ export interface ISpyHook {
type: string
}

export interface IFormActions {
submit(
onSubmit?: (values: IFormState['values']) => void | Promise<any>
): Promise<IFormSubmitResult>
reset(options?: IFormResetOptions): void
hasChanged(target: any, path: FormPathPattern): boolean
validate(path?: FormPathPattern, options?: {}): Promise<IFormValidateResult>
setFormState(callback?: (state: IFormState) => any): void
getFormState(callback?: (state: IFormState) => any): any
clearErrors: (pattern?: FormPathPattern) => void
setFieldState(
path: FormPathPattern,
callback?: (state: IFieldUserState) => void
): void
getFieldState(
path: FormPathPattern,
callback?: (state: IFieldState) => any
): any
getFormGraph(): IFormGraph
setFormGraph(graph: IFormGraph): void
subscribe(callback?: FormHeartSubscriber): number
unsubscribe(id: number): void
isHostRendering: () => boolean
hostUpdate: (callback?: () => any) => any
notify: <T>(type: string, payload?: T) => void
dispatch: <T>(type: string, payload?: T) => void
setFieldValue(path?: FormPathPattern, value?: any): void
getFieldValue(path?: FormPathPattern): any
setFieldInitialValue(path?: FormPathPattern, value?: any): void
getFieldInitialValue(path?: FormPathPattern): any
}

export interface IFormAsyncActions {
submit(
onSubmit?: (values: IFormState['values']) => void | Promise<any>
): Promise<IFormSubmitResult>
reset(options?: IFormResetOptions): Promise<void>
hasChanged(target: any, path: FormPathPattern): Promise<boolean>
clearErrors: (pattern?: FormPathPattern) => Promise<void>
validate(path?: FormPathPattern, options?: {}): Promise<IFormValidateResult>
setFormState(callback?: (state: IFormState) => any): Promise<void>
getFormState(callback?: (state: IFormState) => any): Promise<any>
setFieldState(
path: FormPathPattern,
callback?: (state: IFieldUserState) => void
): Promise<void>
getFieldState(
path: FormPathPattern,
callback?: (state: IFieldState) => any
): Promise<any>
getFormGraph(): Promise<IFormGraph>
setFormGraph(graph: IFormGraph): Promise<void>
subscribe(callback?: FormHeartSubscriber): Promise<number>
unsubscribe(id: number): Promise<void>
notify: <T>(type: string, payload: T) => Promise<void>
isHostRendering: () => boolean
hostUpdate: (callback?: () => any) => Promise<any>
dispatch: <T>(type: string, payload: T) => void
setFieldValue(path?: FormPathPattern, value?: any): Promise<void>
getFieldValue(path?: FormPathPattern): Promise<any>
setFieldInitialValue(path?: FormPathPattern, value?: any): Promise<void>
getFieldInitialValue(path?: FormPathPattern): Promise<any>
type OMitActions =
| 'registerField'
| 'registerVirtualField'
| 'unsafe_do_not_use_transform_data_path'

export type IFormActions = Omit<IForm, OMitActions> & {
dispatch: (type: string, payload: any) => void
}

type WrapPromise<
T extends {
[key: string]: (...args: any) => any
}
> = {
[key in keyof T]: (...args: Parameters<T[key]>) => Promise<ReturnType<T[key]>>
}

export type IFormAsyncActions = WrapPromise<IFormActions>

export interface IEffectProviderAPI<TActions = any, TContext = any> {
waitFor: <TPayload = any>(
type: string,
Expand Down

0 comments on commit c0798c6

Please sign in to comment.