Extract html into separate module (#103)

This commit is contained in:
Todd Kennedy
2016-07-02 12:55:41 +02:00
committed by Yoshua Wuyts
parent d0920f153f
commit 8f8df602c5
19 changed files with 61 additions and 52 deletions
+18 -13
View File
@@ -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
+2 -2
View File
@@ -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>
+3 -3
View File
@@ -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">
+3 -3
View File
@@ -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>
+2 -2
View File
@@ -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>
+6 -6
View File
@@ -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>
+3 -3
View File
@@ -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)}
+2 -2
View File
@@ -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>
+2 -2
View File
@@ -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)}
+2 -2
View File
@@ -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)}
+2 -2
View File
@@ -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)}
+2 -2
View File
@@ -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>
+2 -1
View File
@@ -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>
`
}
+2 -2
View File
@@ -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>
+2 -1
View File
@@ -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>
+1
View File
@@ -0,0 +1 @@
module.exports = require('yo-yo')
-1
View File
@@ -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
+2 -1
View File
@@ -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>`
})
])
+5 -4
View File
@@ -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>
`
})