Skip to content

Commit

Permalink
feat: allow for rerendering of Marko templates
Browse files Browse the repository at this point in the history
  • Loading branch information
DylanPiercey committed Jul 17, 2019
1 parent d5b9673 commit 41754ea
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 34 deletions.
45 changes: 32 additions & 13 deletions app/marko/src/client/preview/render.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import { document } from 'global';
import { stripIndents } from 'common-tags';

const rootEl = document.getElementById('root');
let currLoadedComponent = null; // currently loaded marko widget!
let activeComponent = null; // currently loaded marko component.
let activeTemplate = null; // template for the currently loaded component.

export default function renderMain({
storyFn,
Expand All @@ -12,24 +13,42 @@ export default function renderMain({
showError,
// forceRender,
}) {
const element = storyFn();
const config = storyFn();

// We need to unmount the existing set of components in the DOM node.
if (currLoadedComponent) {
currLoadedComponent.destroy();
}

if (!element || !element.out) {
if (!config || !(config.appendTo || config.template)) {
showError({
title: `Expecting a Marko element from the story: "${selectedStory}" of "${selectedKind}".`,
title: `Expecting an object with a template property to be returned from the story: "${selectedStory}" of "${selectedKind}".`,
description: stripIndents`
Did you forget to return the Marko element from the story?
Use "() => MyComp.renderSync({})" or "() => { return MyComp.renderSync({}); }" when defining the story.
Did you forget to return the template from the story?
Use "() => ({ template: MyTemplate, input: { hello: 'world' } })" when defining the story.
`,
});
return;
} else if (config.appendTo) {
console.warn(
'@storybook/marko: returning a rendered component for a story is deprecated, return an object with `{ template, input }` instead.'
);

// The deprecated API always destroys the previous component instance.
if (activeComponent) {
activeComponent.destroy();
}

activeComponent = config.appendTo(rootEl).getComponent();
} else if (activeTemplate === config.template) {
// When rendering the same template with new input, we reuse the same instance.
activeComponent.input = config.input;
activeComponent.update();
} else {
if (activeComponent) {
activeComponent.destroy();
}

activeTemplate = config.template;
activeComponent = activeTemplate
.renderSync(config.input)
.appendTo(rootEl)
.getComponent();
}

showMain();
currLoadedComponent = element.appendTo(rootEl).getComponent();
}
13 changes: 8 additions & 5 deletions docs/src/pages/guides/guide-marko/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,15 +88,18 @@ That'll load stories in `../stories/index.js`. You can choose where to place sto
Now create a `../stories/index.js` file, and write your first story like this:
```js
/** @jsx m */
import m from 'marko';
import { storiesOf } from '@storybook/marko';
import Button from '../components/button/index.marko';
storiesOf('Button', module)
.add('with text', () => Button.renderSync({ text: 'some text'}))
.add('with emoji', () => Button.renderSync({ text: '😀 😎 👍 💯'}));
.add('with text', () => ({
template: Button,
input: { text 'some text' }
}))
.add('with emoji', () => ({
template: Button,
input: { text '😀 😎 👍 💯' }
}));
```
Each story is a single state of your component. In the above case, there are two stories for the demo button component:
Expand Down
9 changes: 6 additions & 3 deletions examples/marko-cli/src/stories/addon-actions.stories.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ import { storiesOf } from '@storybook/marko';
import { action } from '@storybook/addon-actions';
import Button from '../components/action-button/index.marko';

storiesOf('Addons|Actions/Button', module).add('Simple', () =>
Button.renderSync({ click: action('action logged!') })
);
storiesOf('Addons|Actions/Button', module).add('Simple', () => ({
template: Button,
input: {
click: action('action logged!'),
},
}));
15 changes: 7 additions & 8 deletions examples/marko-cli/src/stories/addon-knobs.stories.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,10 @@ import Hello from '../components/hello/index.marko';
storiesOf('Addons|Knobs/Hello', module)
.addParameters({ options: { panelPosition: 'right' } })
.addDecorator(withKnobs)
.add('Simple', () => {
const name = text('Name', 'John Doe');
const age = number('Age', 44);
return Hello.renderSync({
name,
age,
});
});
.add('Simple', () => ({
template: Hello,
input: {
name: text('Name', 'John Doe'),
age: number('Age', 44),
},
}));
11 changes: 7 additions & 4 deletions examples/marko-cli/src/stories/index.stories.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,15 @@ import ClickCount from '../components/click-count/index.marko';
import StopWatch from '../components/stop-watch/index.marko';
import Welcome from '../components/welcome/index.marko';

storiesOf('Main|Welcome', module).add('welcome', () => Welcome.renderSync({}));
storiesOf('Main|Welcome', module).add('welcome', () => ({ template: Welcome }));

storiesOf('Main|Hello', module)
.add('Simple', () => Hello.renderSync({ name: 'abc', age: 20 }))
.add('Simple', () => ({
template: Hello,
input: { name: 'abc', age: 20 },
}))
.add('with ERROR!', () => 'NOT A MARKO RENDER_RESULT');

storiesOf('Main|ClickCount', module).add('Simple', () => ClickCount.renderSync({}));
storiesOf('Main|ClickCount', module).add('Simple', () => ({ template: ClickCount }));

storiesOf('Main|StopWatch', module).add('Simple', () => StopWatch.renderSync({}));
storiesOf('Main|StopWatch', module).add('Simple', () => ({ template: StopWatch }));
2 changes: 1 addition & 1 deletion lib/cli/generators/MARKO/template/stories/index.stories.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { storiesOf } from '@storybook/marko';
import Welcome from './components/welcome/index.marko';

storiesOf('Welcome', module).add('welcome', () => Welcome.renderSync({}));
storiesOf('Welcome', module).add('welcome', () => ({ template: Welcome }));

0 comments on commit 41754ea

Please sign in to comment.