Skip to content

Commit

Permalink
TableFilterFinalForm: support all final-form-props
Browse files Browse the repository at this point in the history
implement childRender like done in final-form to fully support mutators
and other features which require child-components
use onSubmit if set, but that won't be needed as you normally don't submit
filter-values.
  • Loading branch information
Ben-Ho committed Jul 30, 2019
1 parent 74819f4 commit b4ba860
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 12 deletions.
5 changes: 3 additions & 2 deletions packages/react-admin-core/src/FinalForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { ApolloConsumer } from "react-apollo";
import { Form, FormRenderProps } from "react-final-form";
import { EditDialogApiContext } from "./EditDialogApiContext";
import * as sc from "./FinalForm.sc";
import { CorrectFormRenderProps, renderComponent } from "./FinalFormRenderComponent";
import { IStackApi, StackApiContext } from "./stack";
import { IWithDirtyHandlerApiProps, withDirtyHandlerApi } from "./table/withDirtyHandlerApi";
import { IWithTableQueryProps, withTableQueryContext } from "./table/withTableQueryContext";
Expand Down Expand Up @@ -82,12 +83,12 @@ class FinalForm extends React.Component<IProps> {
);
}

private renderForm = (formRenderProps: FormRenderProps) => {
private renderForm = (formRenderProps: CorrectFormRenderProps) => {
this.formRenderProps = formRenderProps;
const { classes } = this.props;
return (
<form onSubmit={this.submit}>
<sc.InnerForm>{this.props.children}</sc.InnerForm>
<sc.InnerForm>{renderComponent(formRenderProps)}</sc.InnerForm>
{formRenderProps.submitError && <div className="error">{formRenderProps.submitError}</div>}
<EditDialogApiContext.Consumer>
{editDialogApi => {
Expand Down
22 changes: 22 additions & 0 deletions packages/react-admin-core/src/finalFormRenderComponent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import * as React from "react";
import { AnyObject, FormRenderProps, RenderableProps } from "react-final-form";

// call to render-children consists of ...rest, ...renderProps, __versions, see https://github.com/final-form/react-final-form/blob/master/src/ReactFinalForm.js#L195
// whereby ...rest is FormProps destructed with all Config attributes and FormProps specific attributes, see https://github.com/final-form/react-final-form/blob/master/src/ReactFinalForm.js#L42
// which left RenderableProps in ...rest. (click FormProps and check extends). But they are missing in FormRenderProps-Type
export type CorrectFormRenderProps<FormValues = AnyObject> = FormRenderProps<FormValues> & RenderableProps<FormRenderProps<FormValues>>;

// Render children like final-form does.
export function renderComponent<T>(formRenderProps: CorrectFormRenderProps<T>) {
const { render, children, component } = formRenderProps; // not using this.props as final-form-render-component does also use function-parameters and this solves "multiple implementations" hint
if (component) {
return React.createElement<CorrectFormRenderProps<T>>(component, { ...formRenderProps, children, render });
}
if (render) {
return render(children === undefined ? formRenderProps : { ...formRenderProps, children }); // inject children back in
}
if (typeof children !== "function") {
return children;
}
return children(formRenderProps);
}
44 changes: 34 additions & 10 deletions packages/react-admin-core/src/table/TableFilterFinalForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import CancelIcon from "@material-ui/icons/Cancel";
import { debounce } from "debounce";
import isEqual = require("lodash.isequal");
import * as React from "react";
import { Form, FormRenderProps, FormSpy, FormSpyRenderProps } from "react-final-form";
import { AnyObject, Form, FormProps, FormSpy, FormSpyRenderProps } from "react-final-form";
import { CorrectFormRenderProps, renderComponent } from "../finalFormRenderComponent";
import * as sc from "./TableFilterFinalForm.sc";
import { IWithTableQueryProps, withTableQueryContext } from "./withTableQueryContext";

Expand Down Expand Up @@ -45,17 +46,43 @@ class AutoSave extends React.Component<IAutoSaveProps, IAutoSaveState> {

const ExtendedAutoSave = withTableQueryContext(AutoSave);

interface IProps {
type Props<FormValues> = Omit<FormProps<FormValues>, "onSubmit"> & {
modifySubmitVariables?: (variables: any) => any;
headline?: string;
resetButton?: boolean;
}
onSubmit?: FormProps<FormValues>["onSubmit"];
};

// tslint:disable-next-line:max-classes-per-file
export class TableFilterFinalForm extends React.Component<IProps> {
export class TableFilterFinalForm<FormValues = AnyObject> extends React.Component<Props<FormValues>> {
public render() {
return <Form onSubmit={this.handleSubmit} render={this.renderForm} />;
// remove render, children and component from forwardProps as we define render and those would interfere
const { modifySubmitVariables, headline, resetButton, render, children, component, ...forwardProps } = this.props;
return (
<Form
onSubmit={
this.props.onSubmit
? this.props.onSubmit
: () => {
return;
}
}
render={this.renderForm}
{...forwardProps}
/>
);
}
private renderForm = (formRenderProps: FormRenderProps) => {
private renderForm = (formRenderProps: CorrectFormRenderProps<FormValues>) => {
// remove render as this is defined by us and should not be contained in childFormRenderProps
const { render: ownRender, ...finalFormChildrenRenderProps } = formRenderProps;
const { render, children, component } = this.props;
// add render, children and component from own-props to childFormRenderProps as they are used to render the children
const completeFinalFormChildRenderProps = {
...finalFormChildrenRenderProps,
render,
children,
component,
};
return (
<form>
{(this.props.headline || this.props.resetButton) && (
Expand Down Expand Up @@ -87,14 +114,11 @@ export class TableFilterFinalForm extends React.Component<IProps> {
</Grid>
</sc.FormHeader>
)}
{this.props.children}
{renderComponent<FormValues>(completeFinalFormChildRenderProps)}
<FormSpy subscription={{ values: true }}>
{renderProps => <ExtendedAutoSave {...renderProps} modifySubmitVariables={this.props.modifySubmitVariables} />}
</FormSpy>
</form>
);
};
private handleSubmit = () => {
return;
};
}

0 comments on commit b4ba860

Please # to comment.