-
Notifications
You must be signed in to change notification settings - Fork 15
Getting started: build a GraphQL Form in 5 minutes
-
yarn add react-apollo-form
OR npm i react-apollo-form
then, add to your package.json
scripts
section:
"react-apollo-form": "react-apollo-form fetch-mutations <graphqlEndpoint> <outpurDir>"
-
graphqlEndpoint
should be the url of your GraphQL API, ex:"http://localhost:3000/graphql"
-
outpurDir
should be the path where files will be generated, ex:"./src/core/forms"
Just run npm run react-apollo-form
.
You should see 3 steps : "schema download", "mutations types generations", "json schema generation".
If the commands do not finish with "Done.", please check:
- that your GraphQL server is accessible (up and without authentication)
- that your GraphQL server has 'introspection' enabled !
- that the
outputDir
is writable
react-apollo-form
expose a configure(options)
function with the following options:
interface ApolloFormConfigureOptions {
client: ApolloClient<any>;
jsonSchema: JSONSchema6;
theme?: ApolloFormConfigureTheme;
}
-
client
is necessary in order to call the mutation when a form submit -
jsonSchema
is necessary for extract mutation arguments as form fields -
theme
is optional (see "Theming")
TypeScript Tips
For TypeScript users, configure()
takes a "type arguments" for mutations names union types.
The script generates 3 files, including a mutations.d.ts
that expose a ApolloFormMutationNames
type.
Providing ApolloFormMutationNames
to configure()
will allow nice autocomplete when building a form (see next section)
import * as React from 'react';
import { configure } from 'react-apollo-form';
import { client } from './apollo'; // a file thats export a configured Apollo Client
const jsonSchema = require('./core/apollo-form-json-schema.json');
export const ApplicationForm = configure<ApolloFormMutationNames>({
// tslint:disable-next-line:no-any
client: client as any,
jsonSchema
});
We now have a fresh <ApplicationForm>
form component.
Here are the available props:
type ApolloFormProps<MutationNamesType> = {
data: any;
config: ApolloFormConfig & { mutation?: { name: MutationNamesType } };
ui?: UiSchema & ApolloFormUi;
title?: string;
subTitle?: string;
onSave?: (data: object) => void;
onCancel?: () => void;
children?: React.SFC<ApolloRenderProps>;
liveValidate?: boolean;
}
Prop | Description |
---|---|
data |
initial data to fill the fields |
config |
There is two types of config , see below the table |
ui |
same as react-jsonschema-form , see below the table |
title |
Form title (string ) |
subtitle |
Form subtitle (string ) |
onSave |
callback after save ((data: object) => void ) |
onCancel |
callback on cancel action (() => void ) |
onChange |
callback on form changes ((data: object) => void ) |
liveValidate |
should the form run validation on user actions or on submit ? (boolean , default: false ) |
There is two config mode:
- form from mutation:
ApolloFormConfigMutation
- form from raw schema:
ApolloFormConfigManual
ApolloFormConfigMutation
Given a mutation name and document, ApolloForm
will fetch mutations arguments
and "convert" them to form fields (as JSON Schema properties).
ApolloForm
will call mutation.document
to save data on submit.
interface ApolloFormConfigMutation extends ApolloFormConfigBase {
mutation: {
name: string; // mutation name
document: DocumentNode; // mutation document
// apollo mutation options
variables?: object;
context?: object;
refetchQueries?: string[] | PureQueryOptions[] | RefetchQueriesProviderFn;
};
}
ApolloFormConfigManual
If your form is not linked directly to a mutation, you can switch to "manual mode" by passing a raw JSON Schema and a callback to saveData
on submit.
interface ApolloFormConfigManual extends ApolloFormConfigBase {
schema: JSONSchema6;
saveData: (formData: any) => any;
}
See "Build a form without mutation" for more information about "manual mode".
Both mode are share common properties from ApolloFormConfigBase
:
type ApolloFormConfigBase = {
// form namespace (useful for i18n)
name?: string;
// ability to ignore specific fields, eg: ["user.id"]
ignoreFields?: string[];
// ability to set specific fields to required, eg: ["user.email"]
requiredFields?: string[];
// update a existing field config (merge, not override)
updateFields?: { [k: string]: object };
// update directly schema (merge, not override)
augment?: object;
}
The ui
prop is directly forwarded to react-jsonschema-form
, please look first the UISchema Object documentation section.
ApolloForm
add some features in ui
:
type ApolloFormUi = {
// default: false, should we display errors list at the top ?
showErrorsList?: boolean;
// default: true, should we display errors at field level ?
showErrorsInline?: boolean;
// you can provide a custom component to display error list
errorListComponent?: ErrorListComponent;
};
Suppose that you have the following GraphQL Schema:
type Todo {
id: String!
name: String!
completed: Boolean
}
input TodoInputType {
name: String!
completed: Boolean
}
type Query {
todo(id: String!): Todo!
todos: [Todo!]!
}
type Mutation {
update_todo(id: String!, todo: TodoInputType!): Todo
create_todo(todo: TodoInputType!): Todo
}
After running, the react-apollo-form
script, we will have type ApolloFormMutationNames = 'update_todo' | 'create_todo'
and a complete apollo-form-json-schema.json
JSON Schema file.
Let's build a form to create a Todo
.
import * as React from 'react';
import gql from 'graphql-tag';
// ... import ApplicationForm, etc..
const createTodoMutationDocument = gql`
mutation createTodo($todo: TodoInputType!) {
create_todo(todo: $todo) {
id
}
}
`;
const form = p => (
<ApplicationForm
title="Todo Form"
liveValidate={true}
config={{
mutation: {
name: 'create_todo',
document: createTodoMutationDocument
}
}}
data={{}}
ui={{}}
/>
);
And tadaaa 🎉 :
All validations are handled by ApolloForm
, following the types and required arguments/properties exposed by the mutation.
You just built your first form with ApolloForm
.
Please continue to the following articles to build nice and advanced forms: