Papercraft

Introduction

Overview

Getting Started

Community

Basic Usage

Writing Templates

Rendering Templates

HTML Elements

Built-in Methods

Template Composition

Component Templates

Working with Layouts

Advanced Usage

Deferred Rendering

Extending Papercraft

Papercraft Internals

How Papercraft Works

Component Templates

Component templates are templates used for generating HTML for certain parts of the page that may be repeated many times, each time with different dynamic data. That way, you don’t need to repeat the markup itself, but only make calls the component in your main template. Components can also be arbitrarily nested, which means that you break your page markup into small pieces, and compose them together to create bigger and bigger parts of your page.

Since Papercraft components take explicit arguments, they can be thought of as pure functions, which means that they can be safely used in any context and any situation.

By convention, Papercraft component templates are assigned to constants, which makes it easy to use them in your templates. Let’s examine a basic component:

Greet = ->(name) {
  h1 "Hello, #{name}!"
}

As you can see, the Greet component is just a regular Papercraft template. We can then use this component by making calls to Greet() inside our main template:

-> {
  div {
    Greet("foo")
    Greet("bar")
  }
}.render
#=> "<div><h1>Hello, foo!</h1><h1>Hello, bar!</h1></div>"

Components as Arguments

You can also inject arbitrary components into another template (be it a whole page template or a component template) by passing them as parameters. You can render a component given as an argument by passing it to the render method. Any additional parameters are passed to the component:

DivGreet = ->(greet, name) {
  div {
    render greet, name
  }
}

DivGreet.render(Greet, "world")
#=> "<div><h1>Hello, world!</h1></div>"

Components Passed as Block

Another way to use a component is by passing it as a block. This is done in conjunction with render_yield or render_children:

DivWrapper = ->(*args) {
  div {
    render_children *args
  }
}

DivWrapper.render(&Greet)

Organizing Component Templates

Papercraft gives you the freedom to organize your templates as you wish, but a good way to this is to put your component templates in modules. Here’s an example:

module WebComponents
  Table = ->(cols, rows) {
    table {
      thead {
        tr { cols.each { th it } }
      }
      tbody {
        rows.each { |row|
          tr { row.each { td it } }
        }
      }
    }
  }

  Card = ->(title:) {
    card {
      h2 title
      render_children
    }
  }
end

WebComponents::Card.render("My card") {
  WebComponents::Table(cols, rows)
}.render