• Meteor
  • Tutorial

Reactive DOM with UI.materialize

Now we're going to start to look at how we can get an element into the DOM tree, or in other words, get an element onto the screen. We'll start by looking at a function called materialize, which is off of the UI namespace. As you can see from this comment, this is likely to change before version 1.0, but we'll cover it now anyway, and that'll give you a sense of how the concept works.

If I scroll down a bit, you can see the actual implementation of materialize, and you can see the description above. It says that the purpose of the function is to convert a pseudo DOM node into a reactive DOM node and insert it into the element or DOM range parent. We'll see how this works exactly by looking at it in the browser.

Now we're starting off with the materialize method instead of looking at rendering of components, for example, because it turns out this first parameter to materialize can be a number of different types. For example, we can pass in a string or a boolean or a number. We can pass in an array. We can even pass in a function. Scrolling down a bit more, you can see we can also pass in something called an HTML tag, which we'll look at in another video. And then scrolling down even more, we can see finely that we can also pass in a UI component.

And the function decides if it's a UI component if the node has an instantiate method. And then we see a couple of other different types that we can pass in, and then a fall-back, which is to just throw an error if it doesn't know what to do with the input. So let's head over to the browser now and play around with the different materialize inputs that we can use and see what the resulting screen looks like.

OK, with the browser open, now we're going to play around with the materialize method. And as we're doing it, remember our goal with the materialize method is to get an element into the DOM, wire it up with event handlers or anything else that's required, including making the element reactive. So let's start off by just passing in a straight string to materialize. So I'm going to say, UI.materialize. And we'll just say, hello world.

Now it's required that we pass in a parent. And in this case, we want the hello string to be put right onto the body. So we're going to say the parent is document.body. And you can see the element gets inserted right into the DOM.

And if we expand the code window a little bit, you can see that we can pass in any one of these three primitives-- a string, a boolean, or a number. And we get the same result. The materialize function will just throw it right into the DOM as a string.

Next, let's try passing in a function. Interestingly, if we look at the source code of materialize, when we see what happens when we pass in a function, we can see that Meteor creates a computation. And so simply by passing a function to materialize, we get reactivity in our rendered DOM node. So let's look at how that works.

So we can better see the function I'm going to go create in my code file. So I'll create a function called render. And the render function will grab a value from Session and then simply return that value. Now back in the browser, I'll say UI.materialize. And I'll pass in this render function as the first parameter. And then again, we want to append the results to document.body.

OK, now notice nothing got appended to the DOM. And that's because we haven't set a session value yet. So let's say Session.set value. And we'll just set it equal to the first value. And now you can see the DOM reactively updates. And the first value string gets printed.

And of course if we set it to something else, the DOM updates again. And this is because if we pass a function as the first parameter to materialize, Meteor creates this computation by calling autorun, and then calls our function inside of that reactive computation. And so if the computation gets invalidated, this entire function is run again. And we run the materialization process again with the updated content.

OK, next up we can materialize something called an HTML tag, which is another package provided in meteor-core that creates some JavaScript objects around all the various HTML tags and allows us to create tags quickly by using JavaScript and adding attributes and content to them easily. So for an example, if I create a variable called tag, and we'll just set it equal to HTML.A, and I'll pass in some anchor text as the first parameter, and we take a look at the tag, you can see it's an object that has some properties, including some children nodes and some prototype methods like the tag name, the children, and a toHTML method. So we can take this tag, and we can pass it into the materialize method.

So I'll pass it in as the first parameter. And again we'll append it to the document body. And now you can see that this new anchor text appears in the document body. And if we inspect the element, you can see the anchor tag here.

Finally, let's look at what happens when we pass in a component. A component could be a template, for instance. Or it could be a custom component that we create. The way this function determines if a component has been passed in is it looks to see whether the node has an instantiate method. And if it does, then we just assume that it's a component.

And you could see the two lines here to deal with components are first to render the component. And we'll look at that more specifically in another episode. But then it takes the resulting instance and inserts it into the DOM.

So let's just make sure that it works. And I think the easiest way to create a template or a component is just to use templates. The quickest way to create a component is just to use the templating system. And so I've created one called hello. And it just puts a text node onto the screen with a value of world. Now back over in the browser, let me show you what that template looks like.

You can see that it's a component. And I can pass that component as a first parameter to the materialize method. And again, we'll append this to the document body. And what you can see is that the world text node gets put right onto the DOM from the component.

You might be wondering when we pass in a component as the first parameter to materialize how the events get wired up. Well, just like before, if we create an event map by calling Template.hello and calling the events method, we can create a bunch of event handlers. And let me come in here, and we'll change this to a div so that we can click it.

And then we'll call UI.materialize again, and we'll materialize the template. Oops, and I need to specify document.body as the parent. And now if I click on this element, you can see that the clicked event handler gets called. And we print clicked out to the console.

The reason that happens is that when the component's DOM is inserted into the document object model, the notify parented function of the component gets called. And when that happens, this function loops over all the events for the component and wires them up. And it does that using the DOM range method called on. And we'll look at DOM range more specifically in another series.

So in this episode, we looked at UI.materialize. And we looked at how it lets us get some HTML elements onto the document object model and onto the screen in a few different ways by passing different first parameters. For example, we can pass in a straight string. Or we could pass in a component or an HTML tag, or even a function. So the UI.materialize function is an underpinning of Meteor UI, which allows us to get some reactive DOM elements onto the screen.