Skip to content

Commit

Permalink
fix: updating groups from disk
Browse files Browse the repository at this point in the history
It now correctly targets each field in the group individually
  • Loading branch information
ncphillips committed Sep 30, 2019
1 parent 6d551cd commit a56b127
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 15 deletions.
36 changes: 34 additions & 2 deletions packages/core/core/src/cms-forms/form.ts
@@ -1,4 +1,10 @@
import { FormApi, createForm, Config } from 'final-form'
import { FormApi, createForm, Config, Unsubscribe } from 'final-form'

interface FieldSubscription {
path: string
field: Field
unsubscribe: Unsubscribe
}

export class Form<S = any> {
id: any
Expand All @@ -7,14 +13,40 @@ export class Form<S = any> {
finalForm: FormApi<S>
actions: any[]

constructor({ id, label, fields, actions, ...options }: FormOptions<S>) {
fieldSubscriptions: { [key: string]: FieldSubscription } = {}

constructor({ id, label, fields, actions, ...options }: FormOptions<S>) {
this.id = id
this.label = label
this.fields = fields
this.finalForm = createForm<S>(options)
/**
* We register fields at creation time so we don't have to relay
* on `react-final-form` components being rendered.
*/
this.registerFields(this.fields)
this.actions = actions || []
}

private registerFields(fields: Field[], pathPrefix?: string) {
fields.forEach(field => {
let path = pathPrefix ? `${pathPrefix}.${field.name}` : field.name

// @ts-ignore
let subfields = field.fields
if (subfields) {
// This will work for groups. But not for group-lists or blocks.
this.registerFields(subfields, path)
} else {
this.fieldSubscriptions[path] = {
path,
field,
unsubscribe: this.finalForm.registerField(path, () => {}, {}),
}
}
})
}

subscribe: FormApi<S>['subscribe'] = (cb, options) => {
return this.finalForm.subscribe(cb, options)
}
Expand Down
22 changes: 9 additions & 13 deletions packages/react/react-tinacms-remark/src/useRemarkForm.tsx
@@ -1,4 +1,4 @@
import { FormOptions, Form } from '@tinacms/core'
import { FormOptions, Form, Field } from '@tinacms/core'
import { ActionButton } from '@tinacms/tinacms'
import { useCMSForm, useCMS, watchFormValues } from '@tinacms/react-tinacms'
import {
Expand Down Expand Up @@ -35,6 +35,10 @@ export function useRemarkForm(
[markdownRemark.rawFrontmatter]
)
let fields = formOverrrides.fields || generateFields(initialValues)
// The `frontmatter` object might be used by fields for previewing.
// We register it just so we can update keep it up-to-date.
// @ts-ignore
fields.push({ name: 'frontmatter', component: () => null as any })

let [values, form] = useCMSForm({
label,
Expand Down Expand Up @@ -92,26 +96,18 @@ export function useRemarkForm(
* 1. registered with the form
* 2. not currently active
*
* It also updates the `markdownRemark.frontmatter` property. This is
* in-case that field is being used in previewing.
* TODO: Move into `react-tinacms`
*/
function syncFormWithInitialValues(form: Form, initialValues: any) {
useEffect(() => {
if (!form) return
form.finalForm.batch(() => {
/**
* Only update form fields that are observed.
*/
form.fields.forEach((field: any) => {
let state = form.finalForm.getFieldState(field.name)
Object.entries(form.fieldSubscriptions).forEach(([path]) => {
let state = form.finalForm.getFieldState(path)
if (state && !state.active) {
form.finalForm.change(field.name, get(initialValues, field.name))
form.finalForm.change(path, get(initialValues, path))
}
})
/**
* Also update frontmatter incase it's being used for previewing.
*/
form.finalForm.change('frontmatter', initialValues.frontmatter)
})
}, [initialValues])
}
Expand Down

0 comments on commit a56b127

Please sign in to comment.