Docs

Everything You Need to Know

Views

API

View

View Lifecycle

The following diagram illustrates the lifecycle of a view from instantiation to rendering. After instantiation, a view can be rendered by a change to the model it is bound to or by the render function on the view instance.

view life cycle

$.View(options)

Views can be initialized with the following options:

  • element: The element that the view will use as a temlate parent. The template will be rendered inside of this element.
  • template: A template to use. This can must be a string. You could use $(selector).text() to get a template.
  • model: A model. This will bind the view to the designated model. Setting a model on a view binds the view to that model. When the model changes, the view will get updated automatically.
  • variable: A name to use inside your templates to refer to the data being consumed. By default ChocolateChip-UI uses data. Providing a variable allows you to use a term that makes sense for the data you template is consuming.
  • events: This is an array of events to bind to a view. You can target the parent element by leaving out the `element` property or using `self` as the value for `element`. Otherwise, you can create a delegated event on the template's descendants by providing a selector for the intended target. You can also provide a bubble value of true to allow events to pass through a delegate event target to its parents:
    var myView = $.View({
      element: '#arrayTemplate1', 
      model: MyModel,
      startIndexFrom: 10,
      safeHTML: true,
      variable: 'stuff'
      events: [{
        element: 'li',
        startIndexFrom: 10,
        event: 'singletap',
        callback: function() {
          console.log($(this).text());
        },
        bubble: true
      }]
    });
  • Event Bubbling in Views

    As of version 4.4.2 you can use the bubble property with its value set to true in an event object to designate that the event should bubble. Most of the time you should not need to do this. By default this value is always false. The bubble value is only required when you want the event to pass through and be captured by the event target parent elements.

  • styles: This property takes an object defining styles for your view. In most cases you won't need to use it since the default styles will work fine. However, if you want to customize the look of your view, you can use this propertly to create a vitual stylesheet for it. The styles will be defined off of the element selector you anchor your view to using the element property. The style object looks like this:
    var myView = $.View({
      element: '#itemsList', 
      styles: {
        // Style the list itself:
        border: 'solid 1px red',
        // Style the view's child elements:
        '> li': {
          'background-color': 'red'
        }
      }
    });

    This will create a stylesheet like this:

    #itemsList {
      border: solid 1px red;
    }
    #itemsList > li {
      background-color: red;
    }

    To learn more about defining styles for a view, please read the documentation.

  • startIndexFrom: This tells ChocolateChip-UI where to start a template's index from. If you are using $.view.index in your template to output sequential numbers, the numbers will start with the value provided here.
  • safeHTML: If set to `true`, the template will render any HTML markup in the data being used. Use this with caution and only when you are use about the safety of the data you are rendering, since this could allow malicious script injection. By default ChocolateChip-UI escapes any markup in the data being used.

Data Binding

When you set a model on your view, as we did above, the view is bound to that model. This means that whenever you use model methods to change its data, the view will automatically refresh to show those changes.

Model Methods that Trigger View Refresh

The following model methods will trigger a fresh of a bound view:

Object Model

  • set
  • merge
  • mixin
  • remove

Array Model

  • push
  • pop
  • unshift
  • shift
  • setPropAt
  • splice
  • insert
  • reverse
  • sort
  • orderBy
  • concat
  • mixin
  • unique

View Methods

render

render(data, append)

The render method will render a template. If it is bound to a model, it will render the view's template with that model:

// Render a view:
myView.render();

Or you can render a view with raw JavaScript data:

// Render a view:
myView.render(myData);

When rendering a view, the current content is replaced with the data available at render time. You can choose to have the render append the its content to the current content of the view. If you wish to append content to a view that uses a collection, make sure the content you're rendering is new, otherwise you'll have unnecessary duplicates.

To append content to a rendered view, add the keyword true as the last argument:

// Append to a view:
myView.render(myData, true);

empty

empty()

Running this method on a view will remove all rendered content from the parent element.

// Empty a view:
myView.empty();

resetIndex

resetIndex()

This will reset the index ($.view.index) used by a template to 1. That means, if you had set it to start from 10, running this will set it to start from 1.

// Reset a view's index value:
myView.resetIndex();

startIndexFrom

startIndexFrom(number)

Setting this value tells the view at what number to start when rendering $.view.index in a repeating template.

// Set a view's index start value:
myView.startIndexFrom(10);

getTemplate

getTemplate()

This will return a string of the template currently being used. This is the unparsed version of the template.

// Get the template a view is using:
var template = myView.getTemplate();

setTemplate

setTemplate(template)

You can use this to change the template that a view is using. It expects a string, unparsed template.

Using this with myView.setModel(newModel) allows you to totally change what the view is rendering to the screen.

// Set a view's template:
myView.setTemplate(newTemplate);

isRendered

isRendered()

Use this method to find out if the view has rendered its template to the screen. This returns a boolean true/false.

// Check if the view is rendered:
var myViewIsRendered = myView.isRendered();

isEmpty

isEmpty()

This method returns a boolean true/false depending on whether the element has any content or not.

// Check if a view is empty:
var myViewIsEmpty = myView.isEmpty();

getElement

getElement()

This method allows you to find out what parent element the view is attached to.

// Get the element a view is attached to:
var parentElement = myView.getElement();

setElement

setElement(element)

This method allows you to change the element a view is anchored to. If you change the parent, the new element will have its content deleted. If you intend to change the parent element that a view uses, make sure that the view has the template you want and some data so that you can render it immediately.

When you change the parent element that a view is using, ChocolateChip-UI rebinds any events you have in your view. If you want different events you need to change those using the addEvent method.

// Set the parent element for the view:
myView.setElement('#newParent');
myView.render(someData);

To change the events after setting a new parent element, first unbind its events, then add the new ones:

// Set the parent element for the view:
myView.setElement('#newParent');
myView.off();
myView.addEvent({
  element: 'li',
  event: 'tap',
  callback: function() {
    console.log($(this).text());
  }
});
myView.render(someData);

addEvent

addEvent(events, replace)

This method allows you to add events to a view. The method expects an object or array. The object should have at least two properties:

// Add an event to the view:
myView.addEvent({
  event: 'tap',
  callback: function() {
    console.log($(this).text());
  }
});

You can replace all events with the provided event by passing a true value after the events. By default events are add to whatever is already there:

// Add an event to the view,
// replacing any events already registered:
myView.addEvent({
  event: 'tap',
  callback: function() {
    console.log($(this).text());
  }
}, /* Replace events */ true);

You can also add a third property for a delegated element event. This element should be a descendent of the parent element:

// Add a delegate event to the view:
myView.addEvent({
  element: 'li',
  event: 'tap',
  callback: function() {
    console.log($(this).text());
  }
});

You can also pass the method an array of these object to initialze multiple events at once:

// Add two events to a view:
myView.addEvent([
{
  element: 'li',
  event: 'tap',
  callback: function() {
    console.log($(this).text());
  }
},
{
  element: 'p',
  event: 'doubletap',
  callback: function() {
    console.log($(this).text());
  }
}]);

bindModel

setModel(myModel)

If you have initialized your view with raw JavaScript data and want to switch to using a view, you use this method. It takes one argument, the model you want the view to use. After binding the view to the model, any changes to the model will trigger a refresh of the view with the model changes.

You can also use this method to dynamically change what model a view is currently using. This method automatically unbind any previously bound model before binding the new one.

unbindModel

unbindModel(myModel)

If for some reason you wish to use plain JavaScript data with your model, or you simply don't want the view to change any more, you can unbind it from its model using this method. It takes one argument: the model you wish to unbind from.

getModel

getModel()

This method lets you get the model the view is currently bound to. If it is not bound to a model, it will generate an error.

off

off(event, element, callback)

Remove an event or all events from a view. If no argument is passed, all events are removed. Otherwise you can pass the following parameters to remove a specific event: event, element, callback

// Remove all events from a view:
myView.off();

// Remove a tap event from the view:
myView.off('tap', '#element')

defineHelper

defineHelper(callback)

This method lets you define helpers to use inside of a view's template. It expects an object in the following format:

// Define a helper to capitalize the last name:
$.defineHelper({
  bigName: function(data) {
    return data.lastName.toUpperCase();
  }
});

With a helper defined, you can then use it in a template like this:

<ul class="list cloak" id="basicRepeater">
  <!-- Use the helper to output the last name in uppercase -->
  <li>{= data.firstName }, {= $.helpers.bigName(data) }</li>
</ul>

safeHTML

safeHTML(true/false)

This method lets you tell a view to render any HTML tags in the data it is using. It takes a boolean true, otherwise it escapes any markup in the data. Setting a view to render data can allow malicious code injection, so use with caution and only when you are certain about the safety of the data you are using.

// Tell a view to render any markup in the data:
myView.safeHTML(true);

If your view is set to use safe HTML and you want to change it to escape all markup, use a falsy value. From that moment on your view will escape all markup in the view's data.

// Tell a view to render any markup in the data:
myView.safeHTML(false);

isEscapingHTML

isEscapingHTML()

Find out if a view is escaping HTML markup in its data or not. This returns a boolean true/false. By default ChocolateChip-UI escapes all data. It only renders the markup when you set the safeHTML flag in a view or set it with the view.safeHTML method described above.

// Find out if the view is escaping markup:
var isSafeOutput = myView.isEscapingHTML();

getData

getData()

This method lets you get the data the view is currently rendered with.

var viewData = myView.getData();

setData

setData()

If you have a view set to render some data and you want to use some other data, rather than just passing the data as an argument to render(newData) you can set the view to use that data and then just render the view as is:

myView.setData(newData);

// Render the view with the new data binding:
myView.render();

mount

mount()

This method is for use with JSPM and ES6 modeles. If you are not using JSPM with ES6 modules to organize your project's structure, you will not need to use this method. However if you are, you will need this method.

When you import a view from an external file, because this happens before the DOM is thoroughly loaded, ChocolateChip-UI is not able to find the view's element or bind any events that it has. To get around this problem, after importing a view you need to mount it. Mounting should always be done inside a DOM load function. Mounting a view tells it to look for its element and bind any events that it has. After mounting, a view will function as expected.

import {myView} from '../views/myView';

$(function() {
  // Mount the view and render it:
  myView.mount();
  myView.render();
});

Data Binding

If you want an imported view to be bound to a model for automatic refresh, you'll need to set the model after import:

import {cartModel} from './data/cartModel';
import * as app from './views/views';

$(() => {

  // Mount imported views:
  //======================
  app.cartView.mount();
  app.totalPurchasedItemsView.mount();

  // Set model on these views:
  //==========================
  app.cartView.setModel(cartModel);
  app.totalPurchasedItemsView.setModel(cartModel);
});

Styles

You can define styles on your view that create a virtual stylesheet. You would do this to override existing styles, style some custom layout in your view or create a styled view that you can re-use in different projects. The styles are based off of the selector you provide when you create the view. So, a style definition on a view without a element provided will not do anything. When you use setElement to change which element your view is anchored to, ChocolateChip-UI will re-create the virtual stylesheet using the new element selector.

Please note that if you define styles for your view and then want to change templates, your styles may not work with the new template. If you need to be able to change a view's templates dynamically, then don't bother to define its styles with the style property. But those styles in your app's stylesheet file instead.

To learn more about defining styles for a view, please read the documentation.