Dynamic data provider capabilities for JSONForms with Vue 3 integration
npm install @narrative.io/jsonforms-provider-protocols






A Vue 3 library that adds dynamic data provider capabilities to JSONForms, enabling form fields to fetch and display data from various sources like REST APIs, databases, and custom protocols.
- 🔌 Protocol-based Architecture: Extensible system for different data sources
- 🚀 Vue 3 Integration: Seamless integration with JSONForms Vue renderers
- 💾 Built-in Caching: TTL-based caching with configurable expiration
- 🔄 Dynamic Data Loading: Support for mount, focus, and query-based loading
- 🎯 Template Support: Dynamic URL and parameter templating
- 📦 TypeScript Support: Full TypeScript definitions included
- 🔐 Authentication: Flexible authentication mechanism support
``bashUsing bun (recommended)
bun add @narrative.io/jsonforms-provider-protocols
🚀 Quick Start
$3
`typescript
import { createApp } from 'vue'
import ProviderProtocols, { RestApiProtocol } from '@narrative.io/jsonforms-provider-protocols'const app = createApp(App)
app.use(ProviderProtocols, {
protocols: [RestApiProtocol()]
})
`$3
`json
{
"type": "Control",
"scope": "#/properties/country",
"options": {
"provider": {
"ref": "countries",
"protocol": "rest_api",
"config": {
"url": "https://api.example.com/countries",
"items": "$.data[*]",
"map": {
"label": "$.name",
"value": "$.code"
}
}
}
}
}
`$3
`vue
:data="data"
:schema="schema"
:uischema="uischema"
:renderers="markRaw(providerRenderers)"
@change="handleChange"
/>
`📖 Documentation
$3
- Installation & Setup
- Basic Examples$3
- Protocols - How to fetch and transform data
- Authentication - Configure and use authentication
- Vue Components - Available components and composables
- API Reference - Complete API documentation$3
- Simple Dropdown
- Cascading Dropdowns
- Autocomplete Search
- Custom Protocols
- Custom Renderers
- More Examples$3
- Troubleshooting Guide
- GitHub Issues🔧 Key Concepts
$3
Define how data is fetched and transformed:`typescript
const CustomProtocol: Protocol = {
protocol: 'my-api',
async resolve(config, context) {
const response = await fetch(config.url)
const data = await response.json()
return {
items: data.map(item => ({
label: item.name,
value: item.id
})),
ttl: 300
}
}
}
`$3
Transform API response data before mapping to form items using a pipeline of transforms:`json
{
"provider": {
"protocol": "rest_api",
"config": {
"url": "https://api.example.com/data",
"items": "$.data[*]",
"transforms": [
{
"name": "flatten",
"key": "children",
"labelFormat": "{parent.name} → {name}"
},
{
"name": "filter",
"key": "active",
"values": [true]
}
],
"map": {
"label": "$.name",
"value": "$.id"
}
}
}
}
`#### Built-in Transforms
Flatten Transform
Recursively flattens nested tree structures into a single-level array:
`json
{
"name": "flatten",
"key": "children",
"labelFormat": "{parent.name} → {name}"
}
`-
key: The property containing nested children arrays
- labelFormat (optional): Template for formatting labels using parent and child properties
- Adds _depth, _parent, and _formattedLabel metadata to itemsFilter Transform
Filters items based on property values:
`json
{
"name": "filter",
"key": "category",
"values": ["A", "B"]
}
`-
key: The property to check
- values (optional): Array of values to match. If omitted, filters by key existenceCombining Transforms
Transforms are applied sequentially in pipeline order:
`json
{
"transforms": [
{ "name": "flatten", "key": "children" },
{ "name": "filter", "key": "type", "values": ["product"] }
]
}
`Custom Transforms
Register custom transforms for your specific needs:
`typescript
import { registerTransform } from '@narrative.io/jsonforms-provider-protocols'registerTransform('uppercase', (items, config) => {
return items.map(item => ({
...item,
name: item.name.toUpperCase()
}))
})
`$3
Create dynamic URLs using form data:`json
{
"url": "https://api.example.com/countries/{{data.country}}/states",
"query": { "search": "{{ui.query}}" }
}
`$3
Control when data is fetched:-
mount - Load when component mounts (default)
- onFocus - Load when field receives focus
- query - Load when user types (autocomplete)$3
Auto-populate fields from form data or external sources:`json
{
"type": "Control",
"scope": "#/properties/derived_field",
"options": {
"derive": "country",
"mode": "follow",
"readonly": true
}
}
`#### External Data Support
Access external data sources separate from form data using the
externalData() syntax:`vue
``json
{
"type": "Control",
"scope": "#/properties/tree_preference",
"options": {
"derive": "externalData(tree.name)",
"mode": "follow",
"readonly": true
}
}
`$3
Control error display behavior with the showError property:`json
{
"provider": {
"protocol": "rest_api",
"config": {
"url": "https://api.example.com/data",
"showError": false,
"items": "$.data[*]",
"map": { "label": "$.name", "value": "$.id" }
}
}
}
`When
showError is false, failed requests return empty results instead of throwing errors. Defaults to true.$3
Use providers directly in your components:`vue
`🛠 Development
`bash
Install dependencies
bun installRun tests
bun testBuild library
bun run buildType checking
bunx vue-tsc --noEmit
``Contributions are welcome! Please read our Contributing Guide and check out the issue tracker.
MIT - see LICENSE file for details.