ChocolateChip-UI just launched version 5. This was a major upgrade. It was actually a complete rewrite–everything was rewritten in ES6 (ECMAScript 2015). The biggest change was moving widgets to ES6 classes. Also, the two main features of ChocolateChip-UI 4 – $.View and $.Model – were replaced by Component and State . If you’ve used $.View and $.Model , the move to Component and State is not drastic, but there are differences.

Let’s start with Component . On the surface its purpose and behavior is similar to ChocolateChip-UI’s $.View . You define a template bind some data. You render it to the screen with the render function. When the data changes, the changes are rendered to the DOM automatically. Where these two differ is in how they do this. Both $.View and Component expect a selector as the element that the result will be rendered to. Now let’s see how they differ.

Render

$.View

$.View

const myCompo = new Component({ element: '#peopleList', render: (person) => html` <li>${ person.firstName } ${ person.lastName }</li>` })

ChocolateChip-UI Component does not use a template like the olderfunction. Instead it has a render function that returns a template.used a special template language to define templates. It was something ChocolateChip-UI had been using for years. Version 5 threw that template language out. Instead, it uses ES6 template literals and tagged template literals. You define you component’s template by giving it a render function that takes data and returns an ES6 template literal:

Notice that in the above component’s render function, we’re using the tagged template literal html . This is provided by ChocolateChip-UI. You want to use it because it automatically escapes the data, preventing malicious script injection, and allows you to use map on arrays to data without having to end it with .join('') to avoid comma insertion in the result.

Because render is a function that returns a template literal, we can use JavaScript inside the render function as expected. For example, want to uppercase the last name? Easy, just put .toUpperCase() directly on the data:

const myCompo = new Component({ element: '#peopleList', render: (person) => html` <li>${ person.firstName } ${ person.lastName.toUpperCase() }</li>` })

Want to get the index of the loop to output numbering? That would be the second parameter of the render function, so we just need to add one, in this case, after the person parameter:

const myCompo = new Component({ element: '#peopleList', render: (person, idx) => html` <li>${ idx +1 }: ${ person.firstName } ${ person.lastName }</li>` })

JavaScript Before Returning

In the above examples the render function is immediately returning a template literal. In most cases that’s fine. But if you want to do some kind of data checks or other more complex processing before returning the template, you can do that before. In that case you use curly braces with the code:

// Only render a person if the last name is not Wobba: const myCompo = new Component({ element: '#peopleList', render: (person) => { // If the person's last name is Wobba, // don't render that person: if (person.lastName === 'Wobba') { return } else { return html` <li>${ person.firstName } ${ person.lastName }</li>` } } })

Rendering a Component

The above component has an element that it can render to and a render function with template. To make it happen we need to render it. When doing so, we need to pass it some data to use that matches the template. Let’s pretend we have an array of person objects that have the properties firstName and lastName . To render the component, invoke its render function and pass the people arrays as the argument:

myCompo.render(people)

With that, the component will pass the people array to the render function and output the result by rendering list items in the list.

Below is a Codepen of a Component:

See the Pen Simple List v5 - No State by Robert Biggs (@rbiggs) on CodePen.

Reactivity with State

This works quite well, but it’s missing one big feature: reactivity. If we change the people array, the component doesn’t know about i. The component only displays the state of the people array at the time it was rendered. If we want the component to be synched to the state of the array, we need to do two things. First, encapsulate the data in a State object. Second, give the component a state property with the State object as its value. When we do this, the component uses the value of the State object when it renders. More importantly, State objects automatically trigger the rendering of components that use them. Here’s the previous component updated to use state:

// Create State object with people array: const peopleState = new State(people) // Only render a person if the last name is not Wobba: const myCompo = new Component({ element: '#peopleList', state: peopleState, render: (person) => { // If the person's last name is Wobba, // don't render that person: if (person.lastName === 'Wobba') { return } else { return html` <li>${ person.firstName } ${ person.lastName }</li>` } } })

And here’s a Codepen of the component using state:

See the Pen Simple List v5 by Robert Biggs (@rbiggs) on CodePen.

Default Values

Because we are using ES6, we can provide out component render function with default values. Doing so means your component will render without glitch, even if data is missing. Nothing special about providing default parameter values, just follow the ES6 convention:

const myCompo = new Component({ element: '#peopleList', render: (person = { firstName: 'John', lastName: 'Doe' }, idx = 0) => html` <li>${ idx +1 }: ${ person.firstName } ${ person.lastName }</li>` })

With the above code, if there is no data, the component will render “John Doe”. If there is no index value, say you switch from an array to a single person object, the index value will still print out.

Learning More

To learn more about version 5 of ChocolateChip-UI, visit the Website.