Tidy up data binding

This commit is contained in:
Andrew Kingston 2020-11-20 10:49:39 +00:00
parent a6821814f8
commit 911fa31fe3
6 changed files with 19 additions and 51 deletions

View File

@ -24,7 +24,7 @@ import { cloneDeep, difference } from "lodash/fp"
* @returns {Array.<BindableProperty>}
*/
export default function({ componentInstanceId, screen, components, tables }) {
const walkResult = walk({
const result = walk({
// cloning so we are free to mutate props (e.g. by adding _contexts)
instance: cloneDeep(screen.props),
targetId: componentInstanceId,
@ -33,13 +33,10 @@ export default function({ componentInstanceId, screen, components, tables }) {
})
return [
...walkResult.bindableInstances
.filter(isInstanceInSharedContext(walkResult))
.map(componentInstanceToBindable(walkResult)),
...(walkResult.target?._contexts
.map(contextToBindables(tables, walkResult))
.flat() ?? []),
...result.bindableInstances
.filter(isInstanceInSharedContext(result))
.map(componentInstanceToBindable),
...(result.target?._contexts.map(contextToBindables(tables)).flat() ?? []),
]
}
@ -53,26 +50,18 @@ const isInstanceInSharedContext = walkResult => i =>
// turns a component instance prop into binding expressions
// used by the UI
const componentInstanceToBindable = walkResult => i => {
const lastContext =
i.instance._contexts.length &&
i.instance._contexts[i.instance._contexts.length - 1]
const contextParentPath = lastContext
? getParentPath(walkResult, lastContext)
: ""
const componentInstanceToBindable = i => {
return {
type: "instance",
instance: i.instance,
// how the binding expression persists, and is used in the app at runtime
runtimeBinding: `${contextParentPath}${i.instance._id}.${i.prop}`,
runtimeBinding: `${i.instance._id}`,
// how the binding exressions looks to the user of the builder
readableBinding: `${i.instance._instanceName}`,
}
}
const contextToBindables = (tables, walkResult) => context => {
const contextParentPath = getParentPath(walkResult, context)
const contextToBindables = tables => context => {
const tableId = context.table?.tableId ?? context.table
const table = tables.find(table => table._id === tableId)
let schema =
@ -98,7 +87,7 @@ const contextToBindables = (tables, walkResult) => context => {
fieldSchema,
instance: context.instance,
// how the binding expression persists, and is used in the app at runtime
runtimeBinding: `${contextParentPath}data.${runtimeBoundKey}`,
runtimeBinding: `${context.instance._id}.${runtimeBoundKey}`,
// how the binding expressions looks to the user of the builder
readableBinding: `${context.instance._instanceName}.${table.name}.${key}`,
// table / view info
@ -118,20 +107,6 @@ const contextToBindables = (tables, walkResult) => context => {
)
}
const getParentPath = (walkResult, context) => {
// describes the number of "parent" in the path
// clone array first so original array is not mtated
const contextParentNumber = [...walkResult.target._contexts]
.reverse()
.indexOf(context)
return (
new Array(contextParentNumber).fill("parent").join(".") +
// trailing . if has parents
(contextParentNumber ? "." : "")
)
}
const walk = ({ instance, targetId, components, tables, result }) => {
if (!result) {
result = {

View File

@ -12,10 +12,7 @@ export function readableToRuntimeBinding(bindableProperties, textWithBindings) {
return boundValue === `{{ ${readableBinding} }}`
})
if (binding) {
result = textWithBindings.replace(
boundValue,
`{{ ${binding.runtimeBinding} }}`
)
result = result.replace(boundValue, `{{ ${binding.runtimeBinding} }}`)
}
})
return result

View File

@ -46,7 +46,7 @@ export default `<html>
selectedComponentStyle = document.createElement('style');
document.head.appendChild(selectedComponentStyle)
var selectedCss = '[data-bb-id="' + data.selectedComponentType + '-' + data.selectedComponentId + '"]' + '{border:2px solid #0055ff !important;}'
var selectedCss = '[data-bb-id="' + data.selectedComponentId + '"]' + '{border:2px solid #0055ff !important;}'
selectedComponentStyle.appendChild(document.createTextNode(selectedCss))
styles = document.createElement('style')

View File

@ -30,14 +30,13 @@
// Extract component definition info
const componentName = extractComponentName(definition._component)
const constructor = getComponentConstructor(componentName)
const id = `${componentName}-${definition._id}`
const componentProps = extractValidProps(definition)
const dataContext = getContext("data")
const enrichedProps = dataContext.actions.enrichDataBindings(componentProps)
const children = definition._children
// Set style context to be consumed by component
setContext("style", { ...definition._styles, id })
// Set contexts to be consumed by component
setContext("style", { ...definition._styles, id: definition._id })
$: console.log("Rendering: " + componentName)
</script>

View File

@ -6,6 +6,7 @@
// Get current contexts
const dataContext = getContext("data")
const { id } = getContext("style")
// Clone current context to this context
const newDataContext = createDataContextStore($dataContext)
@ -14,7 +15,7 @@
// Add additional layer to context
let loaded = false
onMount(() => {
newDataContext.actions.addContext(row)
newDataContext.actions.addContext(row, id)
loaded = true
})
</script>

View File

@ -3,7 +3,6 @@ import { enrichDataBinding } from "../utils"
import { cloneDeep } from "lodash/fp"
const initialValue = {
parent: null,
data: null,
}
@ -12,15 +11,12 @@ export const createDataContextStore = existingContext => {
const store = writable(initial)
// Adds a context layer to the data context tree
const addContext = row => {
const addContext = (row, componentId) => {
store.update(state => {
if (state.data) {
state.parent = {
parent: state.parent,
data: state.data,
}
if (row && componentId) {
state[componentId] = row
state.data = row
}
state.data = row
return state
})
}