Add data binding enrichment

This commit is contained in:
Andrew Kingston 2020-11-19 09:24:58 +00:00
parent a739ab811f
commit 261ae68907
3 changed files with 53 additions and 5 deletions

View File

@ -1,10 +1,15 @@
<script>
import { getContext } from "svelte"
import * as ComponentLibrary from "@budibase/standard-components"
import Router from "./Router.svelte"
import renderMustacheString from "../utils/renderMustacheString"
const dataProviderStore = getContext("data")
export let definition = {}
$: componentProps = extractValidProps(definition)
$: contextRow = dataProviderStore ? $dataProviderStore.row : undefined
$: componentProps = extractValidProps(definition, contextRow)
$: children = definition._children
$: componentName = extractComponentName(definition._component)
$: constructor = getComponentConstructor(componentName)
@ -18,13 +23,20 @@
}
// Extracts valid props to pass to the real svelte component
const extractValidProps = component => {
const extractValidProps = (component, row) => {
let props = {}
Object.entries(component)
.filter(([name]) => !name.startsWith("_"))
.forEach(([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
}

View File

@ -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 = {
"<": "&lt;",
">": "&gt;",
}
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)
}

View File

@ -2,14 +2,18 @@
import { setContext, onMount } from "svelte"
import { createDataProviderStore } from "./stores/dataProvider"
export let row
const dataProviderStore = createDataProviderStore()
setContext("data", dataProviderStore)
export let row
let loaded = false
onMount(async () => {
await dataProviderStore.actions.setRow(row)
loaded = true
})
</script>
<slot />
{#if loaded}
<slot />
{/if}