![require(esm) Backported to Node.js 20, Paving the Way for ESM-Only Packages](https://cdn.sanity.io/images/cgdhsj6q/production/be8ab80c8efa5907bc341c6fefe9aa20d239d890-1600x1097.png?w=400&fit=max&auto=format)
Security News
require(esm) Backported to Node.js 20, Paving the Way for ESM-Only Packages
require(esm) backported to Node.js 20, easing the transition to ESM-only packages and reducing complexity for developers as Node 18 nears end-of-life.
@oarepo/data-renderer
Advanced tools
A library for providing simple (but configurable) UI for rendering of JSON data
A library for providing simple (but configurable) UI for rendering JSON data.
<template lang="pug">
data-renderer(:data="data")
</template>
<script>
export default {
data: function() {
return {
data: { 'title': 'Hello world' }
}
}
}
</script>
yarn add @oarepo/data-renderer vue-uid
To register/configure the library, add a new boot file to quasar (or main.js for vue-cli projects):
import DataRenderer from '@oarepo/data-renderer'
import VueUid from 'vue-uid';
export default async ({ Vue, store, router }) => {
Vue.use(VueUid);
Vue.use(DataRenderer, {})
}
DataRendererComponent
component iterates the layout tree and converts layout
into a VueJS component. Without any settings, the created component tree will look like:
wrapper.wrapperClass(:style="wrapperStyle" ...wrapperAttrs)
label.labelClass(:style="labelStyle" ...labelAttrs)
| labelValue
value.valueClass(:style="valueStyle" ...valueAttrs) {{ valueOnPath }}
childrenWrapper.childrenWrapperClass(:style="childrenWrapperStyle" ...childrenWrapperAttrs)
// children rendered in here
This tree is defined via the following layout:
elementProperties = {
element: null,
class: {}, // element classes
style: '', // element style
attrs: {}, // element attrs
visible: true // set to false to not render the element, just its content
}
layout = {
wrapper: {
...elementProperties,
element: 'div',
},
label: {
...elementProperties,
element: 'label',
label: 'Label to be shown',
},
value: {
...elementProperties,
element: 'div',
},
'children-wrapper': {
...elementProperties,
element: 'div',
},
'array-wrapper': {
...elementProperties,
element: 'div',
},
prop: '', // json path pointing to the displayed value inside record metadata
showEmpty: false, // if true, the element will be rendered even if there is no value
children: [] // layout of children of this node
}
Every property can be a function func({context, layout, data, vue, paths, ...})
where context
points to the actual parts of the data that is being rendered. To use property as a function, wrap it inside f
:
export default {
layout: {
prop: 'thumbnail',
value: {
component: 'img',
attrs: {
src: f(({ value }) => { return value }),
width: '16'
}
}
}
}
To apply this layout, add to template:
<template lang="pug">
data-renderer(:layout="layout" :data="data"
schema="block|inline|table|<object with default definition>")
</template>
data
passed to data renderer must be an object. To render data consisting of an array of objects, data renderer can be wrapped with an element using v-for directive. Example:
<template lang="pug">
div(v-for="item in array")
data-renderer(:data="item")
</template>
The layout
element might contain the layout as shown above, or shortcut can be used:
export default {
layout: {
title: {
label: {
value: 'Title label'
}
},
location: {
children: [ ... ]
}
}
}
Array and object children can be defined in layout
. The array or object itself is placed inside children
in layout
and may contain another array of children
. See the examples below.
Object layout definition may look like this:
export default {
data: {
object: {}
},
layout: {
showEmpty: true,
'children-wrapper': {
element: 'div'
},
children: [
{
prop: 'location',
label: {
label: 'Location label'
},
children: [
{
prop: 'street',
label: {
label: 'Street'
}
},
{
prop: 'number',
label: {
label: 'Number'
}
},
{
prop: 'zipcode',
label: {
label: 'Zipcode'
}
}]
}]
}
}
Layout of an array contains the item property with definition of layout for array items:
export default {
data: {
object: {}
},
layout: {
showEmpty: true,
'array-wrapper': {
element: 'div'
},
children: [
{
prop: 'Contact',
label: {
label: 'List of contacts'
},
item: {
label: {
label: 'Phone number'
}
}
}]
}
}
If the item of an array is a complex value, then the item
property in layout
must contain children
. Example:
export default {
data: {
object: {}
},
layout: {
showEmpty: true,
'array-wrapper': {
element: 'div'
},
children: [
{
prop: 'Contact',
label: {
label: 'List of contacts'
},
item: {
children: [
{
prop: 'phone',
label: {
label: 'Phone number'
}
}
]
}
}]
}
}
It might be useful to be able to override the layout for selected paths.
To do this, pass :path-layouts
property.
The value of the property is:
export default {
data: {
object: {
a: 'red text'
}
},
pathLayouts: {
a: {
value: {
class: ['text-red']
}
}
}
}
As stated above, the path is composed based on the jsonpath of rendered data. The set of paths for each rendered node is constructed as follows:
export default {
layout: {
prop: "location",
children: [
{ prop: 'street' },
{ prop: 'number' },
{ prop: 'zipcode' }
]
}
}
The path for the root is ['location']
. The path for street
is ['location-street', 'street']
,
i.e. for each of the parent paths, '-street'
is appended to the path and an extra street
.
A function can be registered to create/translate labels. Set either a global labelTranslator when the module is
initialized or a :labelTranslator
prop containing function with the following layout:
func({label, context, layout, data, vue, paths, schema})
and returning the translated label or null if the label should not appear. The default implementation adds ':'
after the label for inline
schema.
Using the same logic, boolean values can be translated with :booleanTranslator
.
If there is no layout specified for the object, it is created dynamically from the data passed to data-renderer.
To render the value as a link, define <a></a>
html tag and href attribute in pathLayouts.
export default {
a: {
value: {
element: 'a',
attrs: {
href: f(({url}) => { return url })
}
}
}
}
Components for primitive values contain a before
and after
slot which can be used to render custom code before and after rendered value. Example:
<template lang="pug">
data-renderer(:layout="layout" :data="data")
template(v-slot:before)
div a
template(v-slot:after)
div b
</template>
To render custom component before or after rendered data, register component in layout, e.g.: before: CustomComponent
, after: CustomComponent
Custom components can be used based instead of default ones, when passed to :renderer-components
property. Example:
<template lang="pug">
data-renderer(:layout="layout" :data="data" renderer-components="rendererComponents")
</template>
export default {
data: {
a: 'string value',
b: 1,
c: 'string value',
d: true
},
rendererComponents:{
string: CustomComponent
}
}
FAQs
A library for providing simple (but configurable) UI for rendering of JSON data
The npm package @oarepo/data-renderer receives a total of 1 weekly downloads. As such, @oarepo/data-renderer popularity was classified as not popular.
We found that @oarepo/data-renderer demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 4 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
require(esm) backported to Node.js 20, easing the transition to ESM-only packages and reducing complexity for developers as Node 18 nears end-of-life.
Security News
PyPI now supports iOS and Android wheels, making it easier for Python developers to distribute mobile packages.
Security News
Create React App is officially deprecated due to React 19 issues and lack of maintenance—developers should switch to Vite or other modern alternatives.