0

All the Cycle.js examples I've found so far, use a single DOM object, named "DOM", in the drivers argument to run(main, drivers). Is it possible to have more than one object, e.g., one named "DOM1" and another "DOM2"? The purpose of this would be to control two separate dynamic DOM areas within a single HTML page, in order to keep a third DOM area statically defined in index.html, and sandwiched between DOM1 and DOM2.

As a side question, the examples I've seen typically target an HTML div with an id of #app or #main-container, and then the sink is defined with a @cycle/dom div function, thus creating AFAICT an unnecessary div within a div. I haven't found a clear explanation or reference of how the virtual nodes are supposed to be defined. Say that DOM2 above targets an HTML form element and that is supposed to contain two input elements. Does it have to start with a div as in all the examples, or can the inputs be defined directly in the .map call, and if so, how?

Joe Abbate
  • 1,692
  • 1
  • 13
  • 19
  • Here's an [ESNextbin](https://esnextb.in/?gist=b54baa4131974b7f12d190fb63be8aeb) demo of two independent DOMs. – bloodyKnuckles Sep 19 '17 at 23:22
  • Thanks @bloodyKnuckles. So I guess the answer is *yes*, you can have two or more DOMs. However, my question now becomes "do the DOMs *have* to be independent?" as you mentioned and as shown in the demo, or can one DOM at least passively influence the other, e.g., the input field in DOM1 and the h1 element in DOM2. I think I can experiment on that. – Joe Abbate Sep 20 '17 at 03:46

1 Answers1

1

There is nothing preventing you from having a DOM1 and DOM2 sinks in your app. bloodyKnuckles' example illustrate that perfectly https://esnextb.in/?gist=b54baa4131974b7f12d190fb63be8aeb

That being said, I am not sure I really see the point of doing this. If it's a matter of performance, I don't think you will gain much in splitting the rendering of your app into two DOMDrivers. The virtual DOM lib (in cycle's case snabbdom) is tailored to recognize pieces of DOM that haven't change from those which have and only updates the latter.

If it's a matter of responsibilities (those 2 pieces of DOM have very different purposes), then I would rather create two different cycle apps that both render in different parts of the DOM. (and then call run twice in your main file)

function app1(sources) {
  return {
    DOM: xs.of(div("hello from app1"))
  }
}


function app2(sources) {
  return {
    DOM: xs.of(div("hello from app2"))
  }
}

run(app1, {
  DOM: makeDOMDriver("#app1")
})


run(app2, {
  DOM: makeDOMDriver("#app2")
})

This way you have a clear separation of the concerns of both apps.

Now to answer your question about why a piece of virtual DOM needs to be wrapped in a div. It is because a piece of virtual DOM have to have a single root element. Said otherwise: a piece of virtual DOM have to be standalone (just like an HTML document only has a single <html> element which is the root). It is, actually, a nice constraint to have because it forces you to have standalone components. In the example you give (with an <input> field), there is absolutely no problem in returning a vDOM like this:

DOM: xs.of(input(/*...*/))

But if your component has an input and a label, then you will need to wrap it in another vNode

DOM: xs.of(div([label(/*...*/), input(/*...*/)])
atomrc
  • 2,543
  • 1
  • 16
  • 20
  • It's neither performance nor responsibilities. I was just reluctant to code the large static area in JavaScript (actually TypeScript). However, I've now realized the "static" area does need to be updated, so the issue of splitting the areas is moot. – Joe Abbate Sep 20 '17 at 13:22