View Basics

Creating and Attaching a View

This example demonstrates the basic usage of Giraffe.View. It can be extended just like a Backbone.View.

var MyView = Giraffe.View.extend({
  template: '#my-template',
  serialize: function() {
    return {name: 'my view'};
  }
});

Giraffe implements render so it can do some useful things, and by default render expects a view's template to be the DOM selector of an Underscore template. This can be easily configured to support any form of string templating. For more information, see template, setTemplateStrategy, and templateStrategy in the API docs or the Template Strategies example. The included strategies use a view's serialize function to get the data passed into the template.

<script id="my-template" type="text/template">
  Hello <%= name %>!
</script>

Giraffe uses the function attachTo to put views into the DOM or inside one another. If a view has not yet been rendered, attachTo will call render on it.

var myView = new MyView();
myView.attachTo('body');

Here's the result:

var MyView = Giraffe.View.extend({
  template: '#my-template',
  serialize: function() {
    return {
      name: 'my view'
    };
  }
});

var myView = new MyView();
myView.attachTo('body');
<!DOCTYPE html>
<html>
  <head>
    <link rel='stylesheet' type='text/css' href='../css/reset.css' />
    
  </head>
  <body>
    <script id="my-template" type="text/template">
  Hello <%= name %>!
</script>

<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.4.4/underscore-min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.0.0/backbone-min.js"></script>
<script src="../backbone.giraffe.js" type="text/javascript"></script>
    <script type='text/javascript' src='viewbasics0-script.js'></script>
  </body>
</html>

Creating Child Views

This example demonstrates how the attachTo function automatically sets up parent-child relationships between views.

Giraffe calls the functions beforeRender and afterRender every time a view renders. These are empty functions for your views to fill in. afterRender is a good place to create and attach child views.

var ParentView = Giraffe.View.extend({
  template: '#parent-template',
  afterRender: function() {
    var childView = new ChildView({name: 'child view'});
    childView.attachTo(this);
    // or
    // this.attach(childView);
  }
});
<script id="parent-template" type="text/template">
  parent view
</script>

The ChildView will be put inside the ParentView.

var ChildView = Giraffe.View.extend({
  template: '#child-template'
});

The ChildView simply displays the name provided in its options. We aren't defining a serialize method on the ChildView, and by default, serialize passes the view to the template function.

<script id="child-template" type="text/template">
  <%= name %>
</script>

Let's create and attach the parent view.

var parentView = new ParentView();
parentView.attachTo('body');

Now is a good time to inspect the views to see what the child-parent relationship looks like. The parent has an array of children and the children have a reference to their parent.

var childView = parentView.children[0];
console.log(parentView === childView.parent); // => true

Let's create a second child view. The method option of attachTo is the jQuery method used to insert the view. The default is 'append'. In this case we'll use 'before' to put it before the first child view we created. See attachTo in the API docs for more.

var childView2 = new ChildView({name: 'child view attached with {method: "before"}'});
childView2.attachTo(childView, {method: 'before'});

The parent of childView2 is the parentView.

console.log(childView2.parent === parentView); // => true

Here's the result:

var ParentView = Giraffe.View.extend({
  template: '#parent-template',
  afterRender: function() {
    var childView = new ChildView({
      name: 'child view'
    });
    childView.attachTo(this);
    // or
    // this.attach(childView);
  }
});

var ChildView = Giraffe.View.extend({
  template: '#child-template'
});

var parentView = new ParentView();
parentView.attachTo('body');

var childView = parentView.children[0];
console.log(parentView === childView.parent); // => true

var childView2 = new ChildView({
  name: 'child view attached with {method: "before"}'
});
childView2.attachTo(childView, {
  method: 'before'
});

console.log(childView2.parent === parentView); // => true
<!DOCTYPE html>
<html>
  <head>
    <link rel='stylesheet' type='text/css' href='../css/reset.css' />
    <link rel='stylesheet' type='text/css' href='viewbasics1-style.css' />
  </head>
  <body>
    <script id="parent-template" type="text/template">
  parent view
</script>

<script id="child-template" type="text/template">
  <%= name %>
</script>

<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.4.4/underscore-min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.0.0/backbone-min.js"></script>
<script src="../backbone.giraffe.js" type="text/javascript"></script>
    <script type='text/javascript' src='viewbasics1-script.js'></script>
  </body>
</html>
[data-view-cid] {
  position: relative;
  padding: 20px;
  margin: 20px;
  border: 1px dashed #999;
}

attachTo Sequence Diagram

participant MyView
participant GView as "Giraffe.View"

MyView -> GView: attachTo #container

alt if #container has parent view
    GView -> ParentView: set MyView as child of parent
end

GView -> DOM: detach MyView's $el

alt if method is 'html'
  GView -> GView: detach views inside #container
end

GView -> DOM: put MyView's $el in #container using method

alt if MyView not yet rendered or options.forceRender
  alt if beforeRender overridden
      GView -> MyView: beforeRender()
  end

  GView -> GView: $el.empty()

  GView -> MyView: templateStrategy()

  MyView --> GView: return html string

  GView -> DOM: append html string to $el

  alt if afterRender overridden
      GView -> MyView: afterRender()
  end
end