Add data binding enrichment
This commit is contained in:
parent
3a5daa8ab1
commit
0ff8a9a67b
|
@ -1,10 +1,15 @@
|
||||||
<script>
|
<script>
|
||||||
|
import { getContext } from "svelte"
|
||||||
import * as ComponentLibrary from "@budibase/standard-components"
|
import * as ComponentLibrary from "@budibase/standard-components"
|
||||||
import Router from "./Router.svelte"
|
import Router from "./Router.svelte"
|
||||||
|
import renderMustacheString from "../utils/renderMustacheString"
|
||||||
|
|
||||||
|
const dataProviderStore = getContext("data")
|
||||||
|
|
||||||
export let definition = {}
|
export let definition = {}
|
||||||
|
|
||||||
$: componentProps = extractValidProps(definition)
|
$: contextRow = dataProviderStore ? $dataProviderStore.row : undefined
|
||||||
|
$: componentProps = extractValidProps(definition, contextRow)
|
||||||
$: children = definition._children
|
$: children = definition._children
|
||||||
$: componentName = extractComponentName(definition._component)
|
$: componentName = extractComponentName(definition._component)
|
||||||
$: constructor = getComponentConstructor(componentName)
|
$: constructor = getComponentConstructor(componentName)
|
||||||
|
@ -18,13 +23,20 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extracts valid props to pass to the real svelte component
|
// Extracts valid props to pass to the real svelte component
|
||||||
const extractValidProps = component => {
|
const extractValidProps = (component, row) => {
|
||||||
let props = {}
|
let props = {}
|
||||||
Object.entries(component)
|
Object.entries(component)
|
||||||
.filter(([name]) => !name.startsWith("_"))
|
.filter(([name]) => !name.startsWith("_"))
|
||||||
.forEach(([key, value]) => {
|
.forEach(([key, value]) => {
|
||||||
props[key] = value
|
props[key] = value
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Enrich props if we're in a data provider context
|
||||||
|
if (row !== undefined) {
|
||||||
|
Object.entries(props).forEach(([key, value]) => {
|
||||||
|
props[key] = renderMustacheString(value, { data: row })
|
||||||
|
})
|
||||||
|
}
|
||||||
return props
|
return props
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
import mustache from "mustache"
|
||||||
|
|
||||||
|
// this is a much more liberal version of mustache's escape function
|
||||||
|
// ...just ignoring < and > to prevent tags from user input
|
||||||
|
// original version here https://github.com/janl/mustache.js/blob/4b7908f5c9fec469a11cfaed2f2bed23c84e1c5c/mustache.js#L78
|
||||||
|
const entityMap = {
|
||||||
|
"<": "<",
|
||||||
|
">": ">",
|
||||||
|
}
|
||||||
|
mustache.escape = text => {
|
||||||
|
return text.replace(/[<>]/g, function fromEntityMap(s) {
|
||||||
|
return entityMap[s] || s
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Regex to test inputs with to see if they are likely candidates for mustache
|
||||||
|
const looksLikeMustache = /{{.*}}/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enriches a given input with a row from the database.
|
||||||
|
*/
|
||||||
|
export default (input, context) => {
|
||||||
|
// Only accept string inputs
|
||||||
|
if (!input || typeof input !== "string") {
|
||||||
|
return input
|
||||||
|
}
|
||||||
|
// Do a fast regex check if this looks like a mustache string
|
||||||
|
if (!looksLikeMustache.test(input)) {
|
||||||
|
return input
|
||||||
|
}
|
||||||
|
return mustache.render(input, context)
|
||||||
|
}
|
|
@ -2,14 +2,18 @@
|
||||||
import { setContext, onMount } from "svelte"
|
import { setContext, onMount } from "svelte"
|
||||||
import { createDataProviderStore } from "./stores/dataProvider"
|
import { createDataProviderStore } from "./stores/dataProvider"
|
||||||
|
|
||||||
export let row
|
|
||||||
|
|
||||||
const dataProviderStore = createDataProviderStore()
|
const dataProviderStore = createDataProviderStore()
|
||||||
setContext("data", dataProviderStore)
|
setContext("data", dataProviderStore)
|
||||||
|
|
||||||
|
export let row
|
||||||
|
let loaded = false
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
await dataProviderStore.actions.setRow(row)
|
await dataProviderStore.actions.setRow(row)
|
||||||
|
loaded = true
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<slot />
|
{#if loaded}
|
||||||
|
<slot />
|
||||||
|
{/if}
|
||||||
|
|
Loading…
Reference in New Issue