Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

TableFilterFinalForm: support all final-form-props #81

Merged
merged 1 commit into from
Aug 8, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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>>;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FormRenderProps are defined wrong in final-form-types package. this is a fix. (I'm going to create a pull-request in types)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I addressed this missing props in this pull-request: final-form/react-final-form#575
If my pull-request gets merged this type shouldn't be needed anymore.


// 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;
};
}