Install
$ agentstack add skill-foxhound87-skills-mobx-react-form-bindings ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Skill: mobx-react-form-bindings
Mission
Guide the user through creating and using field bindings in mobx-react-form — the mechanism that maps field properties to input component props.
Use this skill when the user needs to:
- Use default bindings with
field.bind() - Override bindings per-field or per-render
- Create custom binding rewriters (prop mapping)
- Create custom binding templates (prop logic)
- Integrate with UI frameworks (Material UI, Ant Design, React Aria, etc.)
Architecture
field.bind(props)
→ looks up binding by name (default: 'default')
→ if template exists: calls template({ $try, form, field, props, keys })
→ if rewriter exists: maps field props → component props via rewriter keys
→ returns props object to spread onto input
Default Bindings
Default Rewriter
The built-in rewriter maps standard field properties to HTML input attributes:
// Internal default rewriter:
{
id: 'id',
name: 'name',
type: 'type',
value: 'value',
checked: 'checked',
label: 'label',
placeholder: 'placeholder',
disabled: 'disabled',
autoComplete: 'autoComplete',
onChange: 'onChange',
onBlur: 'onBlur',
onFocus: 'onFocus',
autoFocus: 'autoFocus',
inputMode: 'inputMode',
onKeyUp: 'onKeyUp',
onKeyDown: 'onKeyDown',
}
Default Template
If defined, the template function receives { $try, form, field, props, keys }:
default: ({ $try, form, field, props, keys }) => ({
[keys.id]: $try(props.id, field.id),
[keys.name]: $try(props.name, field.name),
[keys.type]: $try(props.type, field.type),
[keys.value]: $try(props.value, field.value),
[keys.label]: $try(props.label, field.label),
[keys.placeholder]: $try(props.placeholder, field.placeholder),
[keys.disabled]: $try(props.disabled, field.disabled),
[keys.onChange]: $try(props.onChange, field.onChange),
[keys.onBlur]: $try(props.onBlur, field.onBlur),
[keys.onFocus]: $try(props.onFocus, field.onFocus),
[keys.autoFocus]: $try(props.autoFocus, field.autoFocus),
})
> $try() returns the first defined argument — props take precedence over field properties.
Using Bindings in Components
Basic usage
const SimpleInput = observer(({ field, ...props }) => (
));
// In parent:
Override props at bind-time
Props passed to bind() take precedence over field-defined properties.
Custom Bindings
Creating a Rewriter (prop mapping)
For UI framework components with different prop names:
const bindings = {
MaterialTextField: {
id: 'id',
name: 'name',
type: 'type',
value: 'value',
label: 'floatingLabelText', // Material-UI prop name
placeholder: 'hintText', // Material-UI prop name
disabled: 'disabled',
error: 'errorText', // Material-UI prop name
onChange: 'onChange',
onBlur: 'onBlur',
onFocus: 'onFocus',
autoFocus: 'autoFocus',
},
};
new Form({ fields }, { bindings });
Creating a Template (custom logic)
A template is a function that returns the bindings object. It has full control over the output:
const onBlur = field => (e) => {
e.preventDefault();
field.onBlur();
field.validate(); // validate on blur
};
const bindings = {
MaterialTextField: ({ $try, form, field, props }) => ({
type: $try(props.type, field.type),
id: $try(props.id, field.id),
name: $try(props.name, field.name),
value: $try(props.value, field.value),
floatingLabelText: $try(props.label, field.label),
hintText: $try(props.placeholder, field.placeholder),
errorText: field.validating
? props.validatingText
: $try(props.error, field.error),
errorStyle: field.validating
? { background: 'yellow', color: 'black' }
: {},
disabled: props.disabled || field.disabled || form.disabled || form.submitting,
onChange: $try(props.onChange, field.onChange),
onBlur: $try(props.onBlur, onBlur(field)),
onFocus: $try(props.onFocus, field.onFocus),
autoFocus: $try(props.autoFocus, field.autoFocus),
}),
};
Assigning Bindings to Fields
Via field definition
const fields = {
username: {
bindings: 'UppercaseInput', // use custom binding
},
price: {
bindings: 'CurrencyInput',
},
};
Via separated mode
const bindings = {
username: 'UppercaseInput',
price: 'CurrencyInput',
};
new Form({ fields: ['username', 'price'], bindings }, { bindings: customBindings });
Via form constructor
new Form(
{ fields, ... },
{
bindings: {
UppercaseInput: ({ $try, field, props }) => ({ /* ... */ }),
CurrencyInput: ({ $try, field, props }) => ({ /* ... */ }),
},
}
);
Via extended class
class MyForm extends Form {
bindings() {
return {
UppercaseInput: ({ $try, field, props }) => ({ /* ... */ }),
};
}
}
Real-World Binding Examples
UppercaseInput
Transforms input to uppercase on every keystroke:
UppercaseInput: ({ $try, field, props }) => ({
type: 'text',
name: field.name,
value: field.value,
placeholder: field.placeholder,
onChange: (e) => {
e.target.value = e.target.value.toUpperCase();
field.onChange(e);
},
/* onBlur, onFocus, disabled... */
}),
CurrencyInput
Strips non-numeric characters, preserves cursor position:
CurrencyInput: ({ $try, field, props }) => ({
type: 'text',
value: String(field.value),
onChange: (e) => {
const el = e.target;
const cursor = el.selectionStart;
const cleaned = el.value.replace(/[^0-9.,]/g, '');
el.value = cleaned;
field.onChange(e);
requestAnimationFrame(() => {
el.setSelectionRange(Math.min(cursor, cleaned.length), Math.min(cursor, cleaned.length));
});
},
}),
DebugInput
Logs every event to console:
DebugInput: ({ $try, field, props }) => ({
onChange: (e) => {
console.log(`[Debug] onChange — ${field.path}:`, e.target.value);
field.onChange(e);
},
onBlur: (e) => {
console.log(`[Debug] onBlur — ${field.path}:`, e.target.value);
field.onBlur?.(e);
},
onFocus: (e) => {
console.log(`[Debug] onFocus — ${field.path}:`, e.target.value);
field.onFocus?.(e);
},
}),
Ant Design Input
AntdInput: ({ $try, field, props }) => ({
id: field.id,
name: field.name,
value: field.value,
placeholder: field.placeholder,
status: field.error ? 'error' : undefined,
onChange: (e) => field.onChange(e),
onBlur: () => field.onBlur(),
onFocus: () => field.onFocus(),
disabled: field.disabled,
}),
React Select
ReactSelect: ({ $try, field, props }) => ({
name: field.name,
value: field.extra?.options?.find(o => o.value === field.value),
options: field.extra?.options || [],
onChange: (selected) => field.onChange(selected?.value || ''),
onBlur: field.onBlur,
onFocus: field.onFocus,
isDisabled: field.disabled,
}),
The $try Utility
$try() takes unlimited arguments and returns the first defined (non-undefined) value:
$try(props.value, field.value, 'fallback')
Priority: props.value → field.value → 'fallback'
This allows component-level overrides while keeping sensible defaults.
Override Default Binding Template Globally
const bindings = {
default: ({ $try, form, field, props, keys }) => ({
// your custom default for ALL fields
...defaultBindings,
disabled: props.disabled || field.disabled || form.disabled || form.submitting,
}),
};
No need to update field bindings props since they already default to 'default'.
Key Takeaways
- Rewriters: Simple key mapping — field prop name → component prop name.
- Templates: Full control — functions that return the props object.
- $try priority:
bind(props)args → field properties → fallback. - Per-field assignment: Via
bindingsfield prop or separatedbindingsobject. - Event customization: Override
onChange,onBlur,onFocusin templates to transform values. - Framework integration: Create one binding per UI framework component type.
Related Skills
- [mobx-react-form-api](../mobx-react-form-api/SKILL.md) — Core API prerequisite
- [mobx-react-form-flat](../mobx-react-form-flat/SKILL.md) — Field definitions with bindings
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: foxhound87
- Source: foxhound87/skills
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.