render function, with code blocks - tested simple cases

This commit is contained in:
Michael Shanks 2020-01-26 22:56:36 +00:00
parent 80514d07bc
commit 9a857dcd77
6 changed files with 147 additions and 20 deletions

View File

@ -6,8 +6,7 @@ import { trimSlash } from "./common/trimSlash";
import { isBound } from "./state/isState";
import { _initialiseChildren } from "./render/initialiseChildren";
export const createApp = (componentLibraries, appDefinition, user) => {
export const createApp = (componentLibraries, appDefinition, user, uiFunctions) => {
const coreApi = createCoreApi(appDefinition, user);
appDefinition.hierarchy = coreApi.templateApi.constructHierarchy(appDefinition.hierarchy);
@ -54,7 +53,7 @@ export const createApp = (componentLibraries, appDefinition, user) => {
const initialiseChildrenParams = (parentContext, hydrate) => ({
bb, coreApi, store,
componentLibraries, appDefinition,
parentContext, hydrate
parentContext, hydrate, uiFunctions
});
const bb = (context, props) => ({

View File

@ -1,7 +1,9 @@
import { createApp } from "./createApp";
import { trimSlash } from "./common/trimSlash";
export const loadBudibase = async ({componentLibraries, props, window, localStorage}) => {
export const loadBudibase = async ({
componentLibraries, props,
window, localStorage, uiFunctions }) => {
const appDefinition = window["##BUDIBASE_APPDEFINITION##"];
@ -33,7 +35,7 @@ export const loadBudibase = async ({componentLibraries, props, window, localStor
props = appDefinition.props;
}
const _app = createApp(componentLibraries, appDefinition, user);
const _app = createApp(componentLibraries, appDefinition, user, uiFunctions);
_app.hydrateChildren(
[props],
window.document.body);

View File

@ -6,10 +6,15 @@ import {
last
} from "lodash/fp";
import { $ } from "../core/common";
import { renderComponent } from "./renderComponent";
export const _initialiseChildren = ({ bb, coreApi, store, componentLibraries, appDefinition, parentContext, hydrate }) =>
export const _initialiseChildren = (initialiseOpts) =>
(childrenProps, htmlElement, context, anchor=null) => {
const { uiFunctions, bb, coreApi,
store, componentLibraries,
appDefinition, parentContext, hydrate } = initialiseOpts;
const childComponents = [];
if(hydrate) {
@ -19,6 +24,7 @@ export const _initialiseChildren = ({ bb, coreApi, store, componentLibraries, ap
}
for(let childProps of childrenProps) {
const {componentName, libName} = splitName(childProps._component);
if(!componentName || !libName) return;
@ -27,18 +33,19 @@ export const _initialiseChildren = ({ bb, coreApi, store, componentLibraries, ap
store, childProps, coreApi,
context || parentContext, appDefinition.appRootPath);
/// here needs to go inside renderComponent ???
const componentProps = {
...initialProps,
_bb:bb(context || parentContext, childProps)
};
const component = new (componentLibraries[libName][componentName])({
target: htmlElement,
props: componentProps,
hydrate:false,
anchor
});
const componentConstructor = componentLibraries[libName][componentName];
const {component} = renderComponent({
componentConstructor,uiFunctions,
htmlElement, anchor,
parentContext, componentProps});
bind(component);
childComponents.push(component);

View File

@ -0,0 +1,38 @@
export const renderComponent = ({
componentConstructor, uiFunctions,
htmlElement, anchor, parentContext,
componentProps}) => {
const func = uiFunctions[componentProps._id];
let component;
let componentContext;
const render = (context) => {
if(context) {
componentContext = {...componentContext};
componentContext.$parent = parentContext;
} else {
componentContext = parentContext;
}
component = new componentConstructor({
target: htmlElement,
props: componentProps,
hydrate:false,
anchor
});
}
if(func) {
func(render, parentContext);
} else {
render();
}
return ({
context: componentContext,
component
});
}

View File

@ -0,0 +1,52 @@
import { load } from "./testAppDef";
describe("controlFlow", () => {
it("should display simple div, with always true render function", async () => {
const {dom} = await load({
_component: "testlib/div",
className: "my-test-class",
_id: "always_render"
});
expect(dom.window.document.body.children.length).toBe(1);
const child = dom.window.document.body.children[0];
expect(child.className).toBe("my-test-class");
})
it("should not display div, with always false render function", async () => {
const {dom} = await load({
_component: "testlib/div",
className: "my-test-class",
_id: "never_render"
});
expect(dom.window.document.body.children.length).toBe(0);
})
it("should display 3 divs in a looped render function", async () => {
const {dom} = await load({
_component: "testlib/div",
className: "my-test-class",
_id: "three_clones"
});
expect(dom.window.document.body.children.length).toBe(3);
const child0 = dom.window.document.body.children[0];
expect(child0.className).toBe("my-test-class");
const child1 = dom.window.document.body.children[1];
expect(child1.className).toBe("my-test-class");
const child2 = dom.window.document.body.children[2];
expect(child2.className).toBe("my-test-class");
})
});

View File

@ -3,16 +3,32 @@ import { loadBudibase } from "../src/index";
export const load = async (props) => {
const dom = new JSDOM(`<!DOCTYPE html><html><body></body><html>`);
autoAssignIds(props);
setAppDef(dom.window, props);
const app = await loadBudibase({
componentLibraries: allLibs(dom.window),
window: dom.window,
localStorage: createLocalStorage(),
props
props,
uiFunctions
});
return {dom, app};
}
// this happens for real by the builder...
// ..this only assigns _ids when missing
const autoAssignIds = (props, count=0) => {
if(!props._id) {
props._id = `auto_id_${count}`;
}
if(props._children) {
for(let child of props._children) {
count += 1;
autoAssignIds(child, count);
}
}
}
const setAppDef = (window, props) => {
window["##BUDIBASE_APPDEFINITION##"] = ({
componentLibraries: [],
@ -87,5 +103,18 @@ const maketestlib = (window) => ({
}
});
const uiFunctions = ({
never_render : (render, parentContext) => {},
always_render : (render, parentContext) => {
render();
},
three_clones : (render, parentContext) => {
for(let i = 0; i<3; i++) {
render();
}
}
});