Initial Values
Seed a form's starting values with the value prop, async with onInit or fetch, and understand first-paint validation and the reset baseline.
Every field starts empty by default. To give a field a starting value, set the value prop on
GInput - it's the initial value, not a controlled value, so the user (and dispatchChanges) can
change it freely afterward:
<GInput formKey="name" value="Ada Lovelace" />There are three ways to seed a form, depending on where the data comes from:
| Source | Use | When |
|---|---|---|
| A value you know at render time | The value prop on GInput | Defaults, "new" forms, constants |
| The whole form, loaded async | onInit on GForm | Edit forms - load a record after mount |
| One field, loaded async | The fetch prop on GInput | A field whose value depends on an API or other fields |
The value prop is typed per field
The type of value matches the field's type, and so does the value you read back from
state / toRawData():
<GInput formKey="name" value="Ada" /> {/* string */}
<GInput formKey="age" type="number" value={30} /> {/* number */}
<GInput formKey="active" type="checkbox" value={true} /> {/* boolean */}When you don't pass a value, the field falls back to a sensible per-type default - "" for text,
0 for number, false for checkbox, null for file. (For convenience the native
defaultValue and checked attributes are accepted too, but value is the canonical way to seed.)
This works through the element render prop exactly the same way - the seeded value arrives in
props.value (or props.checked), so you just spread it:
<GInput
formKey="status"
value="on-track"
element={(input, props) => (
<select {...props}>
<option value="on-track">On track</option>
<option value="ahead">Ahead</option>
</select>
)}
/>Initial values are validated on first paint
A field that mounts with a value has its native constraints checked immediately, so an invalid starting value shows its error on the very first render - no interaction needed - and the form's native validity is synced so it can't be submitted while invalid:
const validators = {
"*": new GValidator().withRequiredMessage("Required"),
username: new GValidator(/* … */).withMinLengthMessage("At least 4 characters"),
};
// Renders already showing "At least 4 characters":
<GInput formKey="username" value="ab" minLength={4} />A field that mounts empty stays pristine - error/touched are false until the user
interacts with it (or you submit). So seeding an empty optional field costs nothing, and seeding a
value you know is invalid surfaces the problem up front.
Only native constraints (required, minLength, pattern, type="email", …) are baked at
registration for the first paint. Custom and async validators
(withCustomValidation) run in the field's mount effect with the full
field set, so a cross-field initial error appears a tick later.
Async initial values: edit forms
When the starting values come from an API, seed the whole form with onInit - it runs once after
mount and merges the partial state you return. This is the standard "load a record to edit" pattern:
<GForm<ProfileForm>
onInit={async () => {
const profile = await fetchProfile();
return {
name: { value: profile.name },
city: { value: profile.city },
};
}}
>For a single field that loads on its own (or reloads when other fields change), use GInput's
fetch prop instead. See
GForm → onInit for the full onInit contract.
Initial values define the reset baseline
A form reset restores each field to its initial value - the value
prop, or whatever onInit seeded (gform re-snapshots the baseline after onInit runs, so an edit
form resets to the loaded record, not to empty). In other words, "initial" and "reset target" are
the same thing.
Try it live
A mix of seeded fields - text, number, a checked checkbox, a select, and a username that starts
invalid so you can see its error on first paint. The form is valid as soon as username is
long enough:
The Username field shows "At least 4 characters" immediately because it mounted with an invalid
value; fix it and the Save button enables. Notice toRawData() already reflects every seeded
value before you touch anything - the number stays a number and the checkbox a boolean.
See GForm for onInit, Fetching Data for the
fetch prop, and Resetting a Form for how the initial values become
the reset baseline.