Releases: fabrix-framework/fabrix
@fabrix-framework/unstyled@0.1.1
@fabrix-framework/graphql-config@0.4.1
@fabrix-framework/fabrix@0.7.0
Minor Changes
-
#166
d433fe0
Thanks @IzumiSy! - Support constraints for nested object field in fabrixForm directive API -
#155
b577afa
Thanks @IzumiSy! - This update contains the breaking changes specifically on functions that the children prop inFabrixComponent
passes down to bring more flexibility in rendering the view.See #168 for more about the motivation about this change.
Input and Output
The newly introduced functions in the children prop is
getInput
andgetOutput
.getInput
is a function that plays a role as a form renderer, and also an accessor of the form context and form field control. Input fields are inferred from variable definitions in the corresponding GraphQL operation.getOutput
is a function that works as a result renderer (the behaviour of it depends on the component registered in the component registry), and also a direct accessor of the query data. Output fields are inferred from selected fields in the corresponding GraphQL operation.
Here is the example implementation that renders the form to get the search condition for
Query
operation alongside the result component like tables.<FabrixComponent query={gql` query getTodos($input: GetTodoInput!) { getTodos(input: $input) { edges { node { name priority } } } } `} > {({ getInput, getOutput }) => ( <> {/* * `getInput` renders the all form fields inferred from the variables * The rendered view by `getInput` without render props also has the button to execute the query. */} {getInput()} {/* * `getOuput` renders the result of the mutation * This example assumes that `getTodos` is rendered as a table component. */} {getOutput("getTodos")} </> )} </FabrixComponent>
The important point to mention is that
getOutput
andgetInput
work in the same way both forQuery
andMutation
by this update.data
accessorWith this update,
data
accessor is accessible throughgetOuput
function, since the data is tied from the query result (output).<FabrixComponent query={gql` query getTodo { getTodo { name priority } } `} > {({ getOutput }) => getOutput("getTodo", ({ data }) => <div>Todo name: {data.name}</div>) } </FabrixComponent>
More customizable, layoutable form
Here is the complex example to create an update form to show the customizability and layoutability.
<FabrixComponent query={gql` mutation updateTodo($id: ID!, $input: CreateTodoInput!) { updateTodo(id: $id, input: $input) { id } } `} > {({ getInput }) => /* * `getInput` is a function to render form view which can acess functions to build forms. * `Field` and `getAction` are the key functions (see their explanation below) */ getInput({ /* * If the form is the one to update resource, set `defaultValues` here to prefill the form fields. * The data structure should be matched with the variables of query/mutation. */ defaultValues: { id: "user-id", input: { name: "John Doe" } } }, ({ Field, getAction }) => ( {/* * `getAction` is expcted to be passed as an descructive props to `form` element. * It is an object that contains `onSubmit` function as a member that kicks off the query execution. */} <form {...getAction()}> {/* * `Field` is a React component that renders the form field that autotimacally deciding * the corresponding component according to GraphQL type for the path specified in the `name` prop. * * `extraProps` is the prop to carry information to the form field. * In this example, I assume the component that is registered in the component registry * as the form field handles `label` to show it as a text content in the `label` element. * * The props for the `extraProps` should have more variety (e.g., `disabled`, `placeholder`, ...), * but I will work on adding them in other PRs later on. */} <HStack> <Field name="input.name" extraProps={{ label: "Task Name" }} /> <Field name="input.priority" extraProps={{ label: "Task Priority" }} /> </HStack> <Button type="submit">Add</Button> </form> )) } </FabrixComponent>
Additionally, for more page-by-page customization for the form,
getInput
functions offers more functions in its render props, mostly powered by react-hook-form that fabrix internal uses.Field-level handler
In the case that the field component automatially decided by GraphQL type does not fit the requirement in the form,
getInput
function provides the another customizable point at the field level in the form.getField
function returns the value ofUseFormRegisterReturn
in react-hook-form. Users would be able to use the another input component on the spot with this.<FabrixComponent query={`/* ... */`}> {({ getInput }) => getInput({}, ({ Field, getAction, getField }) => { <form {...getAction()}> <Field name="input.name" /> <Field name="input.priority" /> <input {...getField("input.email")} type="text" /> </form>; }) } </FabrixComponent>
Form context
The render props of
getInput
function also passes downformContext
that is the react-hook-form context that the form rendered bygetInput
internally maintains.This helps users create the flexible form-wide funcionality as they want by lerveraging the functionality of react-hook-form like inter-field interactibity.
import { UseFormReturn } from "react-hook-form"; const Page = () => ( <FabrixComponent query={`/* ... */`}> {({ getInput }) => getInput({}, ({ getAction, formContext }) => { <form {...getAction()}> <WatchingField formContext={formContext} /> </form>; }) } </FabrixComponent> ); const WatchingField = (props: { formContext: UseFormReturn }) => { /* * Watches the value on the form field using `watch` method in the form context of react-hook-form */ const status = formContext.watch("input.priority"); };
Backward incompatibility
The previous behaviour of
FabrixComponent
is that only the component for the result was rendered inQuery
and only the form forMutation
on the contrary.
However, from this relelase,FabrixComponent
will render both the form and the result of the component regardless of operation type.If you would like to maintain the previous behaviour, use directives to guide the query render only the specific component that you want.
/* * `@fabrixForm` directive does not */ <FabrixComponent query={gql` mutation updateTodo($id: ID!, $input: CreateTodoInput!) { updateTodo(id: $id, input: $input) @fabrixForm { id } } `} />
fabrixView
also works forQuery
operation in the same way.
Patch Changes
@fabrix-framework/chakra-ui@0.6.1
@fabrix-framework/fabrix@0.6.0
@fabrix-framework/chakra-ui@0.6.0
@fabrix-framework/graphql-config@0.4.0
@fabrix-framework/fabrix@0.5.0
Minor Changes
-
#153
7c104b0
Thanks @IzumiSy! - AddTypedDocumentNode
support: now when theTypedDocumentNode
query is given,data
andvariables
are typed.Also,
getComponent
has the first argument that is typed to help users select the component associated to the query. -
#152
d474f8c
Thanks @IzumiSy! - RemovegetOperation
function from children props in FabrixComponent.Now
query
prop inFabrixComponent
supports only a single query to get it future compatible with TypedDocumentNode.