Ensure client data contexts are correctly updated if a parent context is updated
This commit is contained in:
parent
465a240e87
commit
a2a805b45b
|
@ -11,16 +11,21 @@
|
|||
// Clone and create new data context for this component tree
|
||||
const context = getContext("context")
|
||||
const component = getContext("component")
|
||||
const newContext = createContextStore($context)
|
||||
const newContext = createContextStore()
|
||||
setContext("context", newContext)
|
||||
|
||||
let initiated = false
|
||||
$: providerKey = key || $component.id
|
||||
|
||||
// Add data context
|
||||
$: {
|
||||
newContext.actions.provideData(providerKey, $context, data)
|
||||
initiated = true
|
||||
}
|
||||
|
||||
// Instance ID is unique to each instance of a provider
|
||||
let instanceId
|
||||
|
||||
// Add data context
|
||||
$: data !== undefined && newContext.actions.provideData(providerKey, data)
|
||||
|
||||
// Add actions context
|
||||
$: {
|
||||
if (instanceId) {
|
||||
|
@ -51,4 +56,6 @@
|
|||
})
|
||||
</script>
|
||||
|
||||
<slot />
|
||||
{#if initiated}
|
||||
<slot />
|
||||
{/if}
|
||||
|
|
|
@ -1,22 +1,20 @@
|
|||
import { writable } from "svelte/store"
|
||||
|
||||
export const createContextStore = existingContext => {
|
||||
const store = writable({ ...existingContext })
|
||||
export const createContextStore = () => {
|
||||
const store = writable({})
|
||||
|
||||
// Adds a data context layer to the tree
|
||||
const provideData = (providerId, data) => {
|
||||
if (!providerId) {
|
||||
return
|
||||
}
|
||||
store.update(state => {
|
||||
state[providerId] = data
|
||||
const provideData = (providerId, context, data) => {
|
||||
let newData = { ...context }
|
||||
if (providerId && data !== undefined) {
|
||||
newData[providerId] = data
|
||||
|
||||
// Keep track of the closest component ID so we can later hydrate a "data" prop.
|
||||
// This is only required for legacy bindings that used "data" rather than a
|
||||
// component ID.
|
||||
state.closestComponentId = providerId
|
||||
return state
|
||||
})
|
||||
newData.closestComponentId = providerId
|
||||
}
|
||||
store.set(newData)
|
||||
}
|
||||
|
||||
// Adds an action context layer to the tree
|
||||
|
@ -32,7 +30,6 @@ export const createContextStore = existingContext => {
|
|||
|
||||
return {
|
||||
subscribe: store.subscribe,
|
||||
update: store.update,
|
||||
actions: { provideData, provideAction },
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,46 +1,57 @@
|
|||
<script>
|
||||
import { onMount, getContext } from "svelte"
|
||||
|
||||
const { API, screenStore, routeStore, Provider, styleable } = getContext(
|
||||
"sdk"
|
||||
)
|
||||
const component = getContext("component")
|
||||
|
||||
export let table
|
||||
|
||||
const {
|
||||
API,
|
||||
screenStore,
|
||||
routeStore,
|
||||
Provider,
|
||||
styleable,
|
||||
ActionTypes,
|
||||
} = getContext("sdk")
|
||||
const component = getContext("component")
|
||||
let headers = []
|
||||
let row
|
||||
|
||||
async function fetchFirstRow() {
|
||||
const rows = await API.fetchTableData(table)
|
||||
return Array.isArray(rows) && rows.length ? rows[0] : { tableId: table }
|
||||
const fetchFirstRow = async tableId => {
|
||||
const rows = await API.fetchTableData(tableId)
|
||||
return Array.isArray(rows) && rows.length ? rows[0] : { tableId }
|
||||
}
|
||||
|
||||
async function fetchData() {
|
||||
if (!table) {
|
||||
const fetchData = async (rowId, tableId) => {
|
||||
if (!tableId) {
|
||||
return
|
||||
}
|
||||
|
||||
const pathParts = window.location.pathname.split("/")
|
||||
const routeParamId = $routeStore.routeParams.id
|
||||
|
||||
// if srcdoc, then we assume this is the builder preview
|
||||
if ((pathParts.length === 0 || pathParts[0] === "srcdoc") && table) {
|
||||
row = await fetchFirstRow()
|
||||
} else if (routeParamId) {
|
||||
row = await API.fetchRow({ tableId: table, rowId: routeParamId })
|
||||
if ((pathParts.length === 0 || pathParts[0] === "srcdoc") && tableId) {
|
||||
row = await fetchFirstRow(tableId)
|
||||
} else if (rowId) {
|
||||
row = await API.fetchRow({ tableId, rowId })
|
||||
} else {
|
||||
throw new Error("Row ID was not supplied to RowDetail")
|
||||
}
|
||||
}
|
||||
|
||||
onMount(fetchData)
|
||||
$: actions = [
|
||||
{
|
||||
type: ActionTypes.RefreshDatasource,
|
||||
callback: () => fetchData($routeStore.routeParams.id, table),
|
||||
metadata: { datasource: { type: "table", tableId: table } },
|
||||
},
|
||||
]
|
||||
|
||||
onMount(() => fetchData($routeStore.routeParams.id, table))
|
||||
</script>
|
||||
|
||||
{#if row}
|
||||
<div use:styleable={$component.styles}>
|
||||
<Provider data={row}>
|
||||
<Provider data={row} {actions}>
|
||||
<div use:styleable={$component.styles}>
|
||||
<slot />
|
||||
</Provider>
|
||||
</div>
|
||||
</div>
|
||||
</Provider>
|
||||
{/if}
|
||||
|
|
Loading…
Reference in New Issue