AFASSoftware / maquette

Pure and simple virtual DOM library

Home Page:https://maquettejs.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Node array rendering.

ismail-codar opened this issue · comments

http://maquettejs.org/docs/component-approach.html is good. But looks components must be inside a container node. In real world otherwise true. For example: Bootstrap tab code has two nodes in level 0. ul and div.

<ul class="nav nav-tabs">
    <li class="active"><a href="#home">Home</a></li>
    <li class=""><a href="#profile">Profile</a></li>
</ul>
<div class="tab-content">
    <div id="home" class="tab-pane fade active in">
        <p>1</p>
    </div>
    <div id="profile" class="tab-pane fade">
        <p>2</p>
    </div>
</div>

We can utilize this within a fake div like h("div.fake", [h("ul.nav.nav-tabs", [..]), h("div .tab-content", [..])]) but it's annoying.

It would be a nice feature if renderMaquette functions can be return virtual node array.

You can get a renderMaquette function to return an array of VNodes. I've altered the input example found on the website to demonstrate: (http://codepen.io/anon/pen/rrozZo)
If you're doing this in typescript make sure the renderMaquette function's returnvalue is a VNode[].

document.addEventListener('DOMContentLoaded', function () {
  var h = maquette.h;
  var domNode = document.body;
  var projector = maquette.createProjector();

var yourName = ''; // Piece of data
var createDoubleInput = (getName, inputHandler) => {
  return {
    renderMaquette: () => {
      return [
        h('input', { 
          type: 'text', placeholder: 'What is your name?', 
          value: getName(),
          oninput: inputHandler
        }),
        h('input', { 
          type: 'text', placeholder: 'What is your name?', 
          value: getName(),
          oninput: inputHandler
        })
      ]
    }
  };
};
// Plain event handler
function handleNameInput(evt) {
  yourName = evt.target.value;
}

// This function uses the 'hyperscript' notation to create the virtual DOM. 
var doubleInput = createDoubleInput(() => yourName, handleNameInput);
function renderMaquette() {
  return h('div', [
    doubleInput.renderMaquette(),
    h('p.output', ['Hello ' + (yourName || 'you') + '!'])
  ]);
}

projector.append(domNode, renderMaquette);

});`

I am trying to use maquettejs with a page router. Moving routers main section to inside application main renderMaquette function can fix my problem.
In the above example undermost renderMaquette function returns a container div not array.
My problem actually appending vnode arrays with projector. But another solition is possible

document.addEventListener('DOMContentLoaded', function () {
  var h = maquette.h;
  var domNode = document.body;
  var projector = maquette.createProjector();

var createLinks = () => {
  return {
    renderMaquette: () => {
      return [
        h('a', { 
          href:"#/link1"
        }, ["link1"]),
        [" | "],
        h('a', { 
          href:"#/link2"
        }, ["link2"])
      ]
    }
  };
};

var createRouter = ()=> {
  return {
    renderMaquette: ()=> {
      if(document.location.hash == "#/link1") {
        return h("span", ["page 1"])
      }
      else if(document.location.hash == "#/link2") {
        return [
          h("span", {key:"page1"}, ["page"]), 
          h("span", {key:"page2"}, ["2"])
        ]
      }
    }
  };
}

// This function uses the 'hyperscript' notation to create the virtual DOM. 
var links = createLinks();
var router = createRouter();
function renderMaquette() {
  return h('div', [
    links.renderMaquette(),
    h("hr"),
    router.renderMaquette()
  ]);
}

projector.append(domNode, renderMaquette);
window.onhashchange = function (evt) {
  projector.scheduleRender();
};
});
`

It looks like you can omit the extra 'div' by using projector.merge instead of projector.append in your code snippet above. See http://maquettejs.org/docs/typedoc/interfaces/_maquette_.projector.html#merge