client: providing access to component root elements

This commit is contained in:
Michael Shanks 2020-01-29 22:47:58 +00:00
parent 88e7a69996
commit 7787f33918
5 changed files with 65 additions and 47 deletions

View File

@ -5,8 +5,9 @@ import { setState, setStateFromBinding } from "./state/setState";
import { trimSlash } from "./common/trimSlash";
import { isBound } from "./state/isState";
import { _initialiseChildren } from "./render/initialiseChildren";
import { createTreeNode } from "./render/renderComponent";
export const createApp = (componentLibraries, appDefinition, user, uiFunctions) => {
export const createApp = (document, componentLibraries, appDefinition, user, uiFunctions) => {
const coreApi = createCoreApi(appDefinition, user);
appDefinition.hierarchy = coreApi.templateApi.constructHierarchy(appDefinition.hierarchy);
@ -50,19 +51,19 @@ export const createApp = (componentLibraries, appDefinition, user, uiFunctions)
if(isFunction(event)) event(context);
}
const initialiseChildrenParams = (hydrate, parentContext, childIndex) => ({
bb, coreApi, store, parentContext,
const initialiseChildrenParams = (hydrate, treeNode) => ({
bb, coreApi, store, document,
componentLibraries, appDefinition,
hydrate, uiFunctions, childIndex
hydrate, uiFunctions, treeNode
});
const bb = (componentProps, componentContext, childIndex) => ({
hydrateChildren: _initialiseChildren(initialiseChildrenParams(true, componentContext, childIndex)),
appendChildren: _initialiseChildren(initialiseChildrenParams(false, componentContext, childIndex)),
const bb = (treeNode, componentProps) => ({
hydrateChildren: _initialiseChildren(initialiseChildrenParams(true, treeNode)),
appendChildren: _initialiseChildren(initialiseChildrenParams(false, treeNode)),
insertChildren: (props, htmlElement, anchor) =>
_initialiseChildren(initialiseChildrenParams(false, componentContext, childIndex))
_initialiseChildren(initialiseChildrenParams(false, treeNode))
(props, htmlElement, anchor),
context: componentContext,
context: treeNode.context,
props: componentProps,
call:safeCallEvent,
setStateFromBinding: (binding, value) => setStateFromBinding(store, binding, value),
@ -76,6 +77,6 @@ export const createApp = (componentLibraries, appDefinition, user, uiFunctions)
parent
});
return bb();
return bb(createTreeNode());
}

View File

@ -36,6 +36,7 @@ export const loadBudibase = async ({
}
const app = createApp(
window.document,
componentLibraries,
appDefinition,
user,

View File

@ -12,18 +12,23 @@ export const _initialiseChildren = (initialiseOpts) =>
(childrenProps, htmlElement, anchor=null) => {
const { uiFunctions, bb, coreApi,
store, componentLibraries, childIndex,
appDefinition, parentContext, hydrate } = initialiseOpts;
const childComponents = [];
store, componentLibraries, treeNode,
appDefinition, document, hydrate } = initialiseOpts;
for(let childNode of treeNode.children) {
if(childNode.unsubscribe)
childNode.unsubscribe();
if(childNode.component)
childNode.component.$destroy();
}
if(hydrate) {
while (htmlElement.firstChild) {
htmlElement.removeChild(htmlElement.firstChild);
}
}
let childIndex = 0;
const renderedComponents = [];
for(let childProps of childrenProps) {
const {componentName, libName} = splitName(childProps._component);
@ -33,26 +38,23 @@ export const _initialiseChildren = (initialiseOpts) =>
const {initialProps, bind} = setupBinding(
store, childProps, coreApi,
appDefinition.appRootPath);
const componentConstructor = componentLibraries[libName][componentName];
const {component, context, lastChildIndex} = renderComponent({
const renderedComponentsThisIteration = renderComponent({
props: childProps,
parentNode: treeNode,
componentConstructor,uiFunctions,
htmlElement, anchor, childIndex,
parentContext, initialProps, bb});
childIndex = lastChildIndex;
htmlElement, anchor, initialProps,
bb, document});
const unsubscribe = bind(component);
childComponents.push({
component,
context,
unsubscribe
});
for(let comp of renderedComponentsThisIteration) {
comp.unsubscribe = bind(comp.component);
renderedComponents.push(comp);
}
}
return childComponents;
return renderedComponents;
}
const splitName = fullname => {
@ -65,4 +67,4 @@ const splitName = fullname => {
0, fullname.length - componentName.length - 1);
return {libName, componentName};
}
}

View File

@ -1,34 +1,43 @@
export const renderComponent = ({
componentConstructor, uiFunctions,
htmlElement, anchor, parentContext,
initialProps, bb, childIndex}) => {
htmlElement, anchor, props,
initialProps, bb, document,
parentNode}) => {
const func = initialProps._id
? uiFunctions[componentProps._id]
? uiFunctions[initialProps._id]
: undefined;
const parentContext = (parentNode && parentNode.context) || {};
let component;
let componentContext;
let renderedNodes = [];
const render = (context) => {
let componentContext = parentContext;
if(context) {
componentContext = {...componentContext};
componentContext.$parent = parentContext;
} else {
componentContext = parentContext;
}
initialProps._bb = bb(initialProps, componentContext);
const thisNode = createTreeNode();
thisNode.context = componentContext;
thisNode.parentNode = parentNode;
component = new componentConstructor({
parentNode.children.push(thisNode);
renderedNodes.push(thisNode);
initialProps._bb = bb(thisNode, props);
thisNode.component = new componentConstructor({
target: htmlElement,
props: initialProps,
hydrate:false,
anchor
});
});
childIndex += 1;
thisNode.rootElement = htmlElement.children[
htmlElement.children.length - 1];
}
if(func) {
@ -37,10 +46,15 @@ export const renderComponent = ({
render();
}
return ({
context: componentContext,
lastChildIndex: childIndex,
component
});
return renderedNodes;
}
export const createTreeNode = () => ({
context: {},
rootElement: null,
parentNode: null,
children: [],
component: null,
unsubscribe: () => {}
});

View File

@ -70,7 +70,7 @@ const maketestlib = (window) => ({
node.removeChild(c);
}
const components = currentProps._bb.appendChildren(currentProps._children, node);
childNodes = components.map(c => c._element);
childNodes = components.map(c => c.component._element);
} else {
currentProps._bb.hydrateChildren(currentProps._children, node);
}