javascriptmarko

Simple client-side rendering not working


I'm trying to render a component when the onMount is triggered in my smart component. The server seems to render the component correctly but when onMount is triggered on the client it does not render, I get a simple undefined.

const button = require('src/client/components/a-button');
console.log(button); // --> { path: '/home/karl/dev/instanty/node/src/client/components/a-button.marko.js', _: [Getter/Setter], '$__shouldBuffer': true, meta: {} }


const htmlServer = button.renderToString({ label: 'Click me!' }); // <-- works
console.log(htmlServer);

module.exports = class {
  onMount() {
    console.log(button); // --> Template {path: undefined, meta: undefined, _: function}

    const html = button.renderToString({ label: 'Click me!' }); // <-- does not work
    console.log(html);
  }
  //... more code
}

I'm requiring the component as stated here: http://markojs.com/docs/rendering/#rendering

I'm also using lasso, I suspect this might be why it's not working. I suspect that lasso isn't bundling the component and sending it to the client.

I read the following also: http://markojs.com/docs/lasso/#client-side-rendering


Solution

  • That's due to a limitation in Marko v4. Marko v4 was designed to render [V]DOM nodes and not HTML strings in the browser. If you really need the HTML string you will need to get the HTML string from the DOM node by using code similar to the following:

    const html = button.renderSync({ label: 'Click me!' })
        .getNode().firstChild.outerHTML;
    

    NOTE: getNode() returns a DocumentFragment node because a UI component might render multiple top-level HTML elements. We use firstChild in the code above to get the first node out of the DocumentFragment and assume that is the HTML element node you are interested in.

    With that said, we should update the docs to make this clear (or implement toString() even though it really should not be needed).