Extract html into separate module (#103)
This commit is contained in:
committed by
Yoshua Wuyts
parent
d0920f153f
commit
8f8df602c5
@@ -118,6 +118,7 @@ Let's create an input box that changes the content of a textbox in real time.
|
||||
First we import `choo` and create a new instance:
|
||||
```js
|
||||
const choo = require('choo')
|
||||
const html = require('choo/html')
|
||||
const app = choo()
|
||||
```
|
||||
|
||||
@@ -136,7 +137,7 @@ Then we create a new view. It has an `h1` tag which displays the current title,
|
||||
and an `<input>` field which sends the current value of the text box on every
|
||||
input:
|
||||
```js
|
||||
const mainView = (params, state, send) => choo.view`
|
||||
const mainView = (params, state, send) => html`
|
||||
<main>
|
||||
<h1>${state.title}</h1>
|
||||
<input
|
||||
@@ -166,6 +167,7 @@ document.body.appendChild(tree)
|
||||
And all together now:
|
||||
```js
|
||||
const choo = require('choo')
|
||||
const html = require('choo/html')
|
||||
const app = choo()
|
||||
|
||||
app.model({
|
||||
@@ -175,7 +177,7 @@ app.model({
|
||||
}
|
||||
})
|
||||
|
||||
const mainView = (params, state, send) => choo.view`
|
||||
const mainView = (params, state, send) => html`
|
||||
<main>
|
||||
<h1>${state.title}</h1>
|
||||
<input
|
||||
@@ -338,7 +340,7 @@ Views are also passed the `send` function, which they can use to dispatch action
|
||||
|
||||
```javascript
|
||||
const view = (params, state, send) => {
|
||||
return choo.view`
|
||||
return html`
|
||||
<div>
|
||||
<h1>Total todos: ${state.todos.length}</h1>
|
||||
<button onclick=${(e) => send('add', { payload: {title: 'demo'})}>Add</button>
|
||||
@@ -478,10 +480,11 @@ links they comprise most of what can be done on web pages.
|
||||
```js
|
||||
const choo = require('choo')
|
||||
const http = require('choo/http')
|
||||
const html = require('choo/html')
|
||||
const app = choo()
|
||||
|
||||
function view (params, state, send) {
|
||||
return choo.view`
|
||||
return html`
|
||||
<form onsubmit=${onSubmit}>
|
||||
<fieldset>
|
||||
<label>username</label>
|
||||
@@ -521,7 +524,7 @@ app.start()
|
||||
If you want a form element to be selected when it's loaded, add the
|
||||
[`autofocus`][html-input] property.
|
||||
```js
|
||||
const view = choo.view`
|
||||
const view = html`
|
||||
<form>
|
||||
<input type="text" autofocus>
|
||||
</form>
|
||||
@@ -535,7 +538,7 @@ is clicked, the click event is caught, and the value of `href` is passed into
|
||||
the router causing a state change. If you want to disable this behavior, set
|
||||
`app.start({ href: false })`.
|
||||
```js
|
||||
const nav = choo.view`
|
||||
const nav = html`
|
||||
<a href="/">home</a>
|
||||
<a href="/first-link">first link</a>
|
||||
<a href="/second-link">second link</a>
|
||||
@@ -574,10 +577,11 @@ In order to make our `choo` app call `app.start()` in the browser and be
|
||||
`require()`-able in Node, we check if [`module.parent`][module-parent] exists:
|
||||
```js
|
||||
const choo = require('choo')
|
||||
const html = require('choo/html')
|
||||
const app = choo()
|
||||
|
||||
app.router((route) => [
|
||||
route('/', (params, state, send) => choo.view`
|
||||
route('/', (params, state, send) => html`
|
||||
<h1>${state.message}</h1>
|
||||
`)
|
||||
])
|
||||
@@ -603,10 +607,11 @@ dehydrated DOM nodes to make them dynamic, rather than a new DOM tree and
|
||||
attaching it to the DOM.
|
||||
```js
|
||||
const choo = require('choo')
|
||||
const html = require('choo/html')
|
||||
const app = choo()
|
||||
|
||||
app.router((route) => [
|
||||
route('/', (params, state, send) => choo.view`
|
||||
route('/', (params, state, send) => html`
|
||||
<h1 id="app-root">${state.message}</h1>
|
||||
`)
|
||||
])
|
||||
@@ -642,11 +647,6 @@ arguments:
|
||||
a signature of `(action, state, send)` where `send` is a reference to
|
||||
`app.send()`
|
||||
|
||||
### choo.view\`html\`
|
||||
Tagged template string HTML builder. See
|
||||
[`yo-yo`](https://github.com/maxogden/yo-yo) for full documentation. Views
|
||||
should be passed to `app.router()`
|
||||
|
||||
### app.router(params, state, send)
|
||||
Creates a new router. See
|
||||
[`sheet-router`](https://github.com/yoshuawuyts/sheet-router) for full
|
||||
@@ -677,6 +677,11 @@ following values:
|
||||
changes (eg `localhost/#posts/123`). Enabling this option automatically
|
||||
disables `opts.history` and `opts.href`.
|
||||
|
||||
### choo/html\`html\`
|
||||
Tagged template string HTML builder. See
|
||||
[`yo-yo`](https://github.com/maxogden/yo-yo) for full documentation. Views
|
||||
should be passed to `app.router()`
|
||||
|
||||
## Errors
|
||||
### Could not find DOM node (#id) to update
|
||||
This means that a re-render of the DOM was triggered before the first render
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
const choo = require('../../../')
|
||||
const html = require('../../../html')
|
||||
|
||||
module.exports = function (params, state, send) {
|
||||
const error = state.app.error[0]
|
||||
const title = state.api.title
|
||||
return choo.view`
|
||||
return html`
|
||||
<section>
|
||||
<h1>${title}</h1>
|
||||
<h2>Latest error: ${error}</h2>
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
const dateformat = require('dateformat')
|
||||
const choo = require('../../../')
|
||||
const html = require('../../../html')
|
||||
|
||||
module.exports = function (params, state, send) {
|
||||
const mailbox = params.mailbox
|
||||
const messages = state[mailbox].messages
|
||||
return choo.view`
|
||||
return html`
|
||||
<div>
|
||||
<div class="db cf w-100">
|
||||
<div class="fl mb3 w-25 mt0 b">Date</th>
|
||||
@@ -20,7 +20,7 @@ module.exports = function (params, state, send) {
|
||||
}
|
||||
|
||||
function createMessage (message, mailbox) {
|
||||
return choo.view`
|
||||
return html`
|
||||
<div class="db cf w-100">
|
||||
<a href="${'/' + mailbox + '/' + message.id}">
|
||||
<div class="fl mb3 w-25 f6 link">
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const choo = require('../../../')
|
||||
const html = require('../../../html')
|
||||
|
||||
module.exports = function (params, state, send) {
|
||||
const mailbox = params.mailbox
|
||||
@@ -8,7 +8,7 @@ module.exports = function (params, state, send) {
|
||||
return String(msg.id) === message
|
||||
})[0]
|
||||
|
||||
return choo.view`
|
||||
return html`
|
||||
<div>
|
||||
${email ? createEmail(email) : 'error: no email found'}
|
||||
</div
|
||||
@@ -16,7 +16,7 @@ module.exports = function (params, state, send) {
|
||||
}
|
||||
|
||||
function createEmail (message) {
|
||||
return choo.view`
|
||||
return html`
|
||||
<div class="mail">
|
||||
<dl>
|
||||
<dt>From</dt>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
const choo = require('../../../')
|
||||
const html = require('../../../html')
|
||||
|
||||
module.exports = function (params, state, send) {
|
||||
return choo.view`
|
||||
return html`
|
||||
<section>
|
||||
<p>Select a mailbox</p>
|
||||
</section>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
const dateformat = require('dateformat')
|
||||
const choo = require('../../../')
|
||||
const html = require('../../../html')
|
||||
|
||||
module.exports = function () {
|
||||
return function (params, state, send) {
|
||||
@@ -12,7 +12,7 @@ module.exports = function () {
|
||||
return String(msg.id) === message
|
||||
})[0]
|
||||
|
||||
return choo.view`
|
||||
return html`
|
||||
<section class="fl mt4 w-80 db">
|
||||
<div>
|
||||
${createHeader()}
|
||||
@@ -26,7 +26,7 @@ module.exports = function () {
|
||||
</section>
|
||||
`
|
||||
} else {
|
||||
return choo.view`
|
||||
return html`
|
||||
<section class="fl mt4 w-80 db">
|
||||
${createHeader()}
|
||||
${messages.map(function (msg) {
|
||||
@@ -39,7 +39,7 @@ module.exports = function () {
|
||||
}
|
||||
|
||||
function createHeader () {
|
||||
return choo.view`
|
||||
return html`
|
||||
<div class="db cf w-100">
|
||||
<div class="fl mb3 w-25 mt0 b">Date</th>
|
||||
<div class="fl mb3 w-25 mt0 b">Subject</th>
|
||||
@@ -50,7 +50,7 @@ function createHeader () {
|
||||
}
|
||||
|
||||
function createMessage (message, mailbox) {
|
||||
return choo.view`
|
||||
return html`
|
||||
<div class="db cf w-100">
|
||||
<a href="${'/' + mailbox + '/' + message.id}">
|
||||
<div class="fl mb3 w-25 f6 link">
|
||||
@@ -65,7 +65,7 @@ function createMessage (message, mailbox) {
|
||||
}
|
||||
|
||||
function createEmail (message) {
|
||||
return choo.view`
|
||||
return html`
|
||||
<div class="mail">
|
||||
<dl>
|
||||
<dt>From</dt>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
const choo = require('../../../')
|
||||
const html = require('../../../html')
|
||||
|
||||
const mailboxes = [ 'inbox', 'spam', 'sent' ]
|
||||
|
||||
module.exports = function (params, state, send) {
|
||||
return choo.view`
|
||||
return html`
|
||||
<aside class="fl mt4 w-20 db">
|
||||
<ul>
|
||||
<li>
|
||||
@@ -19,7 +19,7 @@ module.exports = function (params, state, send) {
|
||||
}
|
||||
|
||||
function createLi (mailbox, messages) {
|
||||
return choo.view`
|
||||
return html`
|
||||
<li class="mt4 f6">
|
||||
<a href="/${mailbox}">
|
||||
${mailbox.charAt(0).toUpperCase() + mailbox.slice(1)}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
const pathname = require('pathname-match')
|
||||
const choo = require('../../../')
|
||||
const html = require('../../../html')
|
||||
|
||||
module.exports = function (params, state, send) {
|
||||
const location = state.app.location
|
||||
return choo.view`
|
||||
return html`
|
||||
<span class="fl mt4 w-100 f4 b">
|
||||
URL: ${pathname(location) || '/'}
|
||||
</span>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const choo = require('../../../')
|
||||
const html = require('../../../html')
|
||||
|
||||
const emailList = require('../elements/email-list')
|
||||
const pathname = require('../elements/pathname')
|
||||
@@ -6,7 +6,7 @@ const email = require('../elements/email')
|
||||
const nav = require('../elements/nav')
|
||||
|
||||
module.exports = function (params, state, send) {
|
||||
return choo.view`
|
||||
return html`
|
||||
<main class="mw5 mw7-ns center cf">
|
||||
${pathname(params, state, send)}
|
||||
${nav(params, state, send)}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
const choo = require('../../../')
|
||||
const html = require('../../../html')
|
||||
|
||||
const empty = require('../elements/empty-mailbox')
|
||||
const pathname = require('../elements/pathname')
|
||||
const nav = require('../elements/nav')
|
||||
|
||||
module.exports = function (params, state, send) {
|
||||
return choo.view`
|
||||
return html`
|
||||
<main class="mw5 mw7-ns center cf">
|
||||
${pathname(params, state, send)}
|
||||
${nav(params, state, send)}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
const choo = require('../../../')
|
||||
const html = require('../../../html')
|
||||
|
||||
const emailList = require('../elements/email-list')
|
||||
const pathname = require('../elements/pathname')
|
||||
const nav = require('../elements/nav')
|
||||
|
||||
module.exports = function (params, state, send) {
|
||||
return choo.view`
|
||||
return html`
|
||||
<main class="mw5 mw7-ns center cf">
|
||||
${pathname(params, state, send)}
|
||||
${nav(params, state, send)}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
const assert = require('assert')
|
||||
const choo = require('../../../')
|
||||
const html = require('../../../html')
|
||||
|
||||
module.exports = function (params, state, send) {
|
||||
const serverMessage = state.message.server
|
||||
@@ -8,7 +8,7 @@ module.exports = function (params, state, send) {
|
||||
assert.equal(typeof serverMessage, 'string', 'server should be a string')
|
||||
assert.equal(typeof clientMessage, 'string', 'client should be a string')
|
||||
|
||||
return choo.view`
|
||||
return html`
|
||||
<section id="app-root">
|
||||
<h1>server message: ${serverMessage}</h1>
|
||||
<h1>client message: ${clientMessage}</h1>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
const choo = require('../../')
|
||||
const html = require('../../html')
|
||||
|
||||
const app = choo()
|
||||
app.model(createModel())
|
||||
@@ -10,7 +11,7 @@ const tree = app.start()
|
||||
document.body.appendChild(tree)
|
||||
|
||||
function mainView (params, state, send) {
|
||||
return choo.view`
|
||||
return html`
|
||||
<div>${state.logger.msg}</div>
|
||||
`
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
const choo = require('../../../')
|
||||
const html = require('../../../html')
|
||||
|
||||
module.exports = function (params, state, send) {
|
||||
const error = state.app.error[0]
|
||||
const title = state.api.title
|
||||
return choo.view`
|
||||
return html`
|
||||
<section>
|
||||
<h1>${title}</h1>
|
||||
<h2>Latest error: ${error}</h2>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
const choo = require('../../')
|
||||
const html = require('../../html')
|
||||
|
||||
const app = choo()
|
||||
app.model({
|
||||
@@ -15,7 +16,7 @@ app.model({
|
||||
})
|
||||
|
||||
const mainView = (params, state, send) => {
|
||||
return choo.view`
|
||||
return html`
|
||||
<main class="app">
|
||||
<h1>${state.input.title}</h1>
|
||||
<label>Set the title</label>
|
||||
|
||||
@@ -10,7 +10,6 @@ const assert = require('assert')
|
||||
const xtend = require('xtend')
|
||||
const yo = require('yo-yo')
|
||||
|
||||
choo.view = yo
|
||||
module.exports = choo
|
||||
|
||||
// framework for creating sturdy web applications
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
const tape = require('tape')
|
||||
const choo = require('../../')
|
||||
const view = require('../../html')
|
||||
|
||||
tape('should render on the client', function (t) {
|
||||
t.test('state should not be mutable', function (t) {
|
||||
@@ -50,7 +51,7 @@ tape('should render on the client', function (t) {
|
||||
++loop
|
||||
asserts[loop] && asserts[loop](state.test)
|
||||
setTimeout(() => triggers[loop] && triggers[loop](send), 5)
|
||||
return choo.view`<div><span class="test">${state.foo}:${state.beep}</span></div>`
|
||||
return view`<div><span class="test">${state.foo}:${state.beep}</span></div>`
|
||||
})
|
||||
])
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
const tape = require('tape')
|
||||
const choo = require('../../')
|
||||
const view = require('../../html')
|
||||
|
||||
tape('should render on the server', function (t) {
|
||||
t.test('should render a static response', function (t) {
|
||||
@@ -7,7 +8,7 @@ tape('should render on the server', function (t) {
|
||||
|
||||
const app = choo()
|
||||
app.router((route) => [
|
||||
route('/', () => choo.view`<h1>Hello Tokyo!</h1>`)
|
||||
route('/', () => view`<h1>Hello Tokyo!</h1>`)
|
||||
])
|
||||
|
||||
const html = app.toString('/')
|
||||
@@ -21,7 +22,7 @@ tape('should render on the server', function (t) {
|
||||
const app = choo()
|
||||
app.router((route) => [
|
||||
route('/', function (params, state) {
|
||||
return choo.view`<h1>meow meow ${state.message}</h1>`
|
||||
return view`<h1>meow meow ${state.message}</h1>`
|
||||
})
|
||||
])
|
||||
|
||||
@@ -37,7 +38,7 @@ tape('should render on the server', function (t) {
|
||||
app.model({ state: { bin: 'baz', beep: 'boop' } })
|
||||
app.router((route) => [
|
||||
route('/', function (params, state) {
|
||||
return choo.view`<h1>${state.foo} ${state.bin} ${state.beep}</h1>`
|
||||
return view`<h1>${state.foo} ${state.bin} ${state.beep}</h1>`
|
||||
})
|
||||
])
|
||||
|
||||
@@ -57,7 +58,7 @@ tape('should render on the server', function (t) {
|
||||
})
|
||||
app.router((route) => [
|
||||
route('/', function (params, state) {
|
||||
return choo.view`
|
||||
return view`
|
||||
<h1>${state.hello.foo} ${state.hello.bin} ${state.hello.beep}</h1>
|
||||
`
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user