Code Monkey home page Code Monkey logo

hyperapp's Introduction

Hyperapp

The tiny framework for building hypertext applications.

  • Do more with less—We have minimized the concepts you need to learn to get stuff done. Views, actions, effects, and subscriptions are all pretty easy to get to grips with and work together seamlessly.
  • Write what, not how—With a declarative API that's easy to read and fun to write, Hyperapp is the best way to build purely functional, feature-rich, browser-based apps using idiomatic JavaScript.
  • Smaller than a favicon—1 kB, give or take. Hyperapp is an ultra-lightweight Virtual DOM, highly-optimized diff algorithm, and state management library obsessed with minimalism.

Here's the first example to get you started. Try it here—no build step required!

<script type="module">
  import { h, text, app } from "https://unpkg.com/hyperapp"

  const AddTodo = (state) => ({
    ...state,
    value: "",
    todos: state.todos.concat(state.value),
  })

  const NewValue = (state, event) => ({
    ...state,
    value: event.target.value,
  })

  app({
    init: { todos: [], value: "" },
    view: ({ todos, value }) =>
      h("main", {}, [
        h("h1", {}, text("To do list")),
        h("input", { type: "text", oninput: NewValue, value }),
        h("ul", {},
          todos.map((todo) => h("li", {}, text(todo)))
        ),
        h("button", { onclick: AddTodo }, text("New!")),
      ]),
    node: document.getElementById("app"),
  })
</script>

<main id="app"></main>

Check out more examples

The app starts by setting the initial state and rendering the view on the page. User input flows into actions, whose function is to update the state, causing Hyperapp to re-render the view.

When describing how a page looks in Hyperapp, we don't write markup. Instead, we use h() and text() to create a lightweight representation of the DOM (or virtual DOM for short), and Hyperapp takes care of updating the real DOM efficiently.

Installation

npm install hyperapp

Documentation

Learn the basics in the Tutorial, check out the Examples, or visit the Reference.

Packages

Official packages provide access to Web Platform APIs in a way that makes sense for Hyperapp. For third-party packages and real-world examples, browse the Hyperawesome collection.

Package Status About
@hyperapp/dom npm Inspect the DOM, focus and blur.
@hyperapp/svg npm Draw SVG with plain functions.
@hyperapp/html npm Write HTML with plain functions.
@hyperapp/time npm Subscribe to intervals, get the time now.
@hyperapp/events npm Subscribe to mouse, keyboard, window, and frame events.
@hyperapp/http npm Talk to servers, make HTTP requests (#1027).
@hyperapp/random npm Declarative random numbers and values.
@hyperapp/navigation npm Subscribe and manage the browser URL history.

Need to create your own effects and subscriptions? You can do that too.

Help, I'm stuck!

If you've hit a stumbling block, hop on our Discord server to get help, and if you remain stuck, please file an issue, and we'll help you figure it out.

Contributing

Hyperapp is free and open-source software. If you want to support Hyperapp, becoming a contributor or sponsoring is the best way to give back. Thank you to everyone who already contributed to Hyperapp! <3

License

MIT

hyperapp's People

Contributors

andyrj avatar atomiks avatar danigb avatar eschaefer avatar frenzzy avatar fvj avatar icylace avatar jaeh avatar jorgebucaran avatar kofifus avatar lazarljubenovic avatar loteoo avatar lukejacksonn avatar madebyherzblut avatar maraisr avatar mrozbarry avatar mytrill avatar okwolf avatar pspeter3 avatar sahassar avatar sergey-shpak avatar shish avatar skanne avatar skaterdad avatar slacktracer avatar swizz avatar terkelg avatar tzellman avatar warwickgrigg avatar zaceno avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

hyperapp's Issues

Sourcemaps 🗺

Could we have sourcemaps for the minified versions? Would make debugging so much easier. You can do it with Webpack.

Edit: #49 (comment)

1kb file size?

Hi, just wondering how you arrived at the 1kb file size, when app.min.js.gz is 1.7kb in this repo.

Also I think it would be good to state the size of html.min.js somewhere in the README if that's not factored into the file size.

Badges not loading on README

Seems like shields.io has some serious latency issues. This results in the badges never loading in our README. That looks pretty unprofessional, like we don't know what we're doing. I'd suggest reducing the number of badges to reduce the latency. The Slack badge always loads, the others never. I think having the version is important so I'd suggest leading that one and the Slack one. I'm laying this issue at Shields feet because I'm noticing some serious delays on their own site as well.

multiple `app()`s / component approach / return dom

So, it is just amazing lib. A was working on some idea like that, code name mitak ;d Based on events with just router, pub/sub system. For now it is 450bytes gzip. But yea, anyway.

So the problem of return nothing just bumped while I tried to make a Todo List in components way.

So lets get started. We have 3 app()s - TodoItem, TodoList and main.

  • main - main entry, place for header & footer for example
  • TodoItem - component for each todo, e.g. <li></li>
  • TodoList - component holding all TodoItems, actions and view which is just like <ul>TodoItem()</ul>

main

const { app, html } = require('hyperapp')

const main = app({
  // root: document.body,
  model: {
    title: 'Todo List Example',
    link: 'https://github.com/hyperapp/hyperapp'
  },
  view: (state) => html`<main id="HyperApp">
    <h1>${state.title}</h1>
    ${TodoList()}
    <footer>Powered by <a data-no-routing href="${state.link}">HyperApp</a></footer>
  </main>`
})

TodoList

const TodoList = () => app({
  model: {
    todos: [],
    count: 0,
    input: '',
    placeholder: 'Add new todo'
  },
  update: {
    toggle: (state, data) => ({
      todos: state.todos.map((item) => {
        return data.id === item.id
          ? Object.assign({}, item, { done: !data.done })
          : item
      })
    }),
    remove: (state, data) => ({
      todos: state.todos.map((todo) => todo.id !== data.id)
    }),
    add: (state) => ({
      todos: state.todos.concat({
        id: state.count++,
        done: false,
        text: state.input
      })
    }),
    input: (state, data) => ({ input: data.value })
  },
  view: (state, action) => html`<section>
    <ul>${state.todos.map((item) => TodoItem(item, action))}</ul>
    <p>
      <input
        class="add"
        type="text"
        onkeyup=${e => e.keyCode === 13 ? action.add() : ''}
        oninput=${e => action.input({ value: e.target.value })}
        placeholder=${state.placeholder}
      />
      <button onclick=${action.add}>add</button>
    </p>
  </section>`
})

TodoItem

const TodoItem = (state, actions) => app({
  model: state,
  update: actions,
  view: (item, action) => html`<li onclick=${e => action.toggle(item)}>${item.text}</li>`
})

All is okey, but it adds Todo to DOM body two times

2017-01-31-14 53 55_1280x1024_scrot

Passing opts.root seems to not deal with that problem.

The only thing that I changed to the core source code, is to return node from app function.

Browserify errors.

Using the hello world code I get the following error from browserify:

> browserify -g uglifyify index.js | uglifyjs > bundle.js
Error
    at new JS_Parse_Error (eval at <anonymous> (/Users/seru/Share/Devel/Projects/Web/hyperapp/node_modules/uglify-js/tools/node.js:28:1), <anonymous>:1547:18)
    at js_error (eval at <anonymous> (/Users/seru/Share/Devel/Projects/Web/hyperapp/node_modules/uglify-js/tools/node.js:28:1), <anonymous>:1555:11)
    at croak (eval at <anonymous> (/Users/seru/Share/Devel/Projects/Web/hyperapp/node_modules/uglify-js/tools/node.js:28:1), <anonymous>:2094:9)
    at token_error (eval at <anonymous> (/Users/seru/Share/Devel/Projects/Web/hyperapp/node_modules/uglify-js/tools/node.js:28:1), <anonymous>:2102:9)
    at unexpected (eval at <anonymous> (/Users/seru/Share/Devel/Projects/Web/hyperapp/node_modules/uglify-js/tools/node.js:28:1), <anonymous>:2108:9)
    at expr_atom (eval at <anonymous> (/Users/seru/Share/Devel/Projects/Web/hyperapp/node_modules/uglify-js/tools/node.js:28:1), <anonymous>:2635:9)
    at maybe_unary (eval at <anonymous> (/Users/seru/Share/Devel/Projects/Web/hyperapp/node_modules/uglify-js/tools/node.js:28:1), <anonymous>:2797:19)
    at expr_ops (eval at <anonymous> (/Users/seru/Share/Devel/Projects/Web/hyperapp/node_modules/uglify-js/tools/node.js:28:1), <anonymous>:2832:24)
    at maybe_conditional (eval at <anonymous> (/Users/seru/Share/Devel/Projects/Web/hyperapp/node_modules/uglify-js/tools/node.js:28:1), <anonymous>:2837:20)
    at maybe_assign (eval at <anonymous> (/Users/seru/Share/Devel/Projects/Web/hyperapp/node_modules/uglify-js/tools/node.js:28:1), <anonymous>:2861:20

If I remove the uglify bit I get this:

> browserify index.js
import { app, html } from "hyperapp"
^
ParseError: 'import' and 'export' may appear only with 'sourceType: module'

For reference, my index.js file:

import { app, html } from "hyperapp"
app({
   model: "Hello World!",                                                                             
    view: model =>  html`<h1>${model}</h1>`
})

DIY chapter in User Guide needed! 📌

hi.
I have been using react/vue to build web application, to be honest, both of them are greet, but I really want to known how these modern ui framework are built from scratch.

I found this library accidently, and happy to notice that there are "do it yourself" chapter in the user guide, so my question is when this chapter can be readed. what's more, it would be appreciate if I am able to contribute to make this repo better.

sorry to bother you, and thanks to reply!

Why msg?

Why are actions called msg? Is there any reason for keeping this? I know that (and actually use) they can be renamed, as it's just a "conventional name".

I'd vote for changing it to actions though, assuming that there's nothing I'm missing of course.

[question] using real dom nodes

heya, cool lib!

Got a question: have you considered using real dom nodes rather than virtual ones for this lib? Something we've got going with choo is that anything that produces real dom nodes will work natively - e.g. charts, forms, all the stuff.

Figured it might be cool if hyperapp instances could interop with choo and the other way around - making it easy to mount inside each other and like reuse packages and stuff. I think especially with nanomorph slowly stabilizing this might become exciting.

Was mostly wondering about your reasoning - thanks! ✨

see also

Examples as a standalone repository

It's tough copying and pasting code from Gomix or your ready snippets trying to piece them together as something that runs locally. It would be nice if there was another repository under hyperapp for examples.

The spinoffs: Hyperapp 🎢

Just fyi for anyone interested, the funness of this repo inspired me to make something similar. The differences being that the view rendering is decoupled, so you can plug in any render function, and it's all es5 — no build tools required. Thanks @jbucaran for making a cool thing.

https://github.com/nichoth/h-app

Both className and class attributes created.

There is classname and class attributes at the created DOM nodes.

2017-02-13-00 08 36_1280x1024_scrot

Kinda feel that i faced that while decoupling the dom diffing and fixed it but cant remember how and where it was and where the codes are. (just did kinda dozen rewrites of few things in a couple of folders; wrote 3-4 new packages that i am lazy to write tests and docs, haha. i'm totally 🤒 👿 💢)

Consider extract the routing code from core

Hi @jbucaran,

I felt in love with hyperapp because is almost the perfect essence of the Elm application architecture. All the code is clean, simple and functional 👍 The only part that looks a little bit hacky is the routing code. But there are other reasons to extract it:

  • Not all applications need routing. That would help to reduce the size of the core.
  • Even if they use routing, is not always to change the view.

I don't know the best solution (that's why I'm opening this issue), but I think the API could be something like:

import { html, routes, app } from 'hyperapp'

const model = {}
const view = routes({
     "*": (model, msg) => {},
     "/": (model, msg) => {},
     "/:slug": (model, msg, params) => {}
    }
})

app({ model, view })

The new routes function should create a view (function) that selects the route proper view function using the browser history, and previously it registers the required event handlers, probably using the lifecycle events (more or less, the same code now it's inside the app.js file)

What do you think?

Anyway, congrats for this nice library

Extract Hyperx from core

Depending on https://github.com/substack/hyperxify/pull/8 to be merged to move forward is not reasonable. But the truth is that even if it's not merged, hyperxify can still be used with HyperApp, it's just a little more laborious.

const { h, app } = require("hyperapp")
const hyperx = require("hyperx")
const html = hyperx(h)

app({
    model: "Hi.",
    view: model => html`<h1>${model}</h1>`
})
browserify -t hyperxify index.js -g uglifyify | uglifyjs > bundle.js

HyperApp is officially neutral in the Hyperx/template functions VS JSX debate (although the README is biased in favor of JSX on the premise that it looks "cool"), so extracting Hyperx seems a natural move.

I'll update online examples still using html via HyperApp and write the docs.

Don't distribute hyperapp.hx.js

Browser usage has a fairly limited use case, so if one is working on a production site, please compile your templates/hyperx/jsx during development-time. How? Use Browserify, Webpack, Rollup. There are some examples in the README. There's also:

Put this another way, https://unpkg.com/hyperapp/dist/hyperapp.js should be reserved for prototyping, CodePens, fiddles, etc., not a production site.

With that in mind, I no longer see the value of distributing hyperapp.hx.js.

Nested Update/Effects

Have you considered this:

app({
	update: {
		example: {
			attempt: () => alert(1)
		}
	}
})

It should then be possible to call msg.example.attempt().


Meanwhile I ended up using this
const convert = (actions, prefix = '') => Object
	.keys(actions)
	.map(name => typeof actions[name] === 'function'
		? ({[`${prefix[0].toLowerCase()}${prefix.slice(1)}${name[0].toUpperCase()}${name.slice(1)}`]: actions[name]})
		: (convert(actions[name], `${prefix}${name[0].toUpperCase()}${name.slice(1)}`))
	)
	.reduce((a, b) => Object.assign(a, b), {})

app({
	update: convert({
		example: {
			attempt: () => alert(1)
		}
	})
})

This maps example.attempt to exampleAttempt.

How To Reference An Element?

Let's say I want to access an element from a function bound to a button. In react/JSX it'd be possible to use ref=. Is there anything similar for hyperapp without manually keeping track of ids or going through the reducer?

OnBeforeCreate lifecycle event ... or something?

I've hit a wall in my self-assumed hyperapp tutorial project (app that you just log in & out from). I want the main view (route: /) to render if the user is already logged in, and if not, I want the app rerouted to /login, where the login form is rendered. On successful login, you get routed back to /.

Tried implementing this by calling `msg.setLocation('/login') in an oncreated event on the root-div of the "main view". But I notice that this does not prevent the main view from being rendered once before being sent to /login (where the page renders the login view instead)

The problem here, of course, is that hyperapp is already busy rendering my view in the oncreated event, and isn't about to abort that rendering just because I reroute the application.

So I was thinking, perhaps there should be a view lifecycle event, or a hook maybe, that happens before the 'point of no return'. Allowing for a last minute change of heart, so to speak.

If that doesn't make sense, how do you suggest solving the problem of (as in my example) having an authentication-guard for certain pages that bounces you to a login page if you're not logged in?

How to use function for composition

In the checkin #77 you mention about returning a function for composition. This is not mentioned in the README. An example would be nice to illustrate how this works. Is this a feature that only works with JSX? Is so, could it also be implemented to work with Hyperx?

Server Rendering?

The Problem

Server-side rendering mostly improves the following aspects of web-applications. They're arguably the most important ones:

  1. Time to load. The client can already start rendering without even loading the .js
  2. Search engine optimization. Most SEs (notable exception: Google) don't parse JavaScript-only websites or rank them down. Responding with a "real" HTML solves this perfectly.
  3. Especially reduces initial load times on mobile.
  4. Greatly improve the experience for people that disabled javascript. Especially given that hyperapp's router uses plain links that work on the server-side too.

Proposed Usage

  1. Create an app() that works on the client-side.
  2. Require said app() on the server-side
  3. Render it somehow (maybe with a hyperapp/server, so that the client-version isn't polluted )
  4. Get a string or buffer back
  5. Return said buffer via HTTP/etc.

So basically, the same as react. 😄

Notable Challenges

  • Router has to be able to run on the server-side. I suggest we add a state.router.url property to the state for both browser and server usage. If state.router.url is defined, the router should always make sure to set the browser URL to that URL too.

Bonus feature?

Just thought about file-sizes. Wouldn't it be possible to somehow re-use the already rendered HTML version to make the javascript components even smaller? Maybe gzip already fixes that if you bundle the JS as well. Not sure.


Is this possible or planned? Would be awesome if this could completely replace React.

Subs or Substitutions?

I really like the API, a complete copy of ElmArchitecture in JavaScript. My only peeve is subs. I think it would be better to use the term subscriptions like Elm and Choo. I remember the first time I looked at the counter example and saw the sub function in the update method. I immediately assumed it was a singular instance of subs, whatever they were. Then when I saw the subs in actions I was thinking, hmmm... substitutions?, subtractions? subordinations? subscripts? or maybe he wants to give us all foot long subs!!! Yay! I'll have two please. OK, I know you used subs to save a few letters typing, but going forward if you want this project to gain traction it would be better to use the more explicit term subscriptions to save people the mental work of constantly translating subs to subscriptions in our heads. Even in your README you describe subs as: Subscriptions are functions that run once when the DOM is ready. Use a subscription to register global events, like mouse or keyboard listeners. I'm suspecting you probably just lobbed off the tail end of pubsub for the term. My point is explicit terms are always better than implicit terms in API design. It's not like people would have to type the term a thousand times. It's just once. Then when you scan the page and see subscriptions it would be immediately clear what you are looking at, even if you were not familiar with this API.

What are the design goals of this project? 🎯

Hi. Cool repo. I was wondering if you have goals for the project and how they might differ from existing libraries (there are so many). For example, choo comes to mind as having a similar elm-like design.

Modernize


TL;DR 👋

If you are reading this issue now, just be aware we considered rewriting the source in ES6 at some point, but eventually decided not to. The rationale is ES6 would make it slightly more difficult for developers to hack with Hyperapp without introducing a build system and still no CommonJS support out of the box.

Hyperapp is a minimal library and with an unchanging goal of staying forever lean and beginner friendly.

You can take an hour and read through the entire 250ish LOC here and here and you'd understand pretty much everything. Zero dependency. It's all there, the virtual DOM, the state container, etc.


See original discussion
@maraisr Summarizing the discussion in #29, #30, #31 and #32 we'd like to modernize the code base to use more ES6 idioms and introduce webpack to bundle the distribution.

Rationale

  • Using more ES6 idioms may encourage more contributions.

  • Using more ES6 idioms means a smaller bundle for users targetting really modern browsers. For example, in production users may consume our src directory directly with their application and don't babelify (or maybe babelify a some things via plugins) and use something like babili to minify modern JavaScript. This means even smaller bundles.

  • Other than prototyping, examples, presentations and maybe even real small-ish apps, users will want to bundle their apps using a bundler like browserify, webpack, rollup, etc.

Which event should be used to start the code?

When I used window.addEventListener('load', () => app(...)) the subs didn't work correctly, as they never seemed to receive the event. How should we handle this without adding the <script> to the last line of the HTML?


Note: It should work with both <script async ...> and <script> if possible.

Should HyperApp Wait For The DOM Before Rendering?

If you only want to make your vote count please just 👍 or 👎 this comment. I added both so it's easy to click.

Things that need to be done

  • Decide if window.addEventListener('load') should be implicit
  • Add documentation for agreed upon behavior

The Problem

When including app() in a script in <head> hyperapp will crash because it tries to append itself onto the not-yet-existing DOM.

Note: Some might suggest to just include the script at the bottom of the page, however - in some use-cases (like mine) that's not possible. It also feels like a workaround IMHO.

This can be solved in (at least) 2 ways:

Solution 1

Force users to add window.addEventListener('load', () => app(...)) to their scripts.

import {app, html} from 'hyperapp'

window.addEventListener('load', () => app({
	view: html`<div>Example</div>`
}))

Pro

  • less implicit behavior, more control/information for the dev

Contra

It just crashes for no reason, even though I copied the whole example!
- Frustrated first-time users.

Solution 2

Implicitly do the same as in solution 1.

import {app, html} from 'hyperapp'

app({
	view: html`<div>Example</div>`
})

Pro

  • more straight-forward code
  • less stuff to consider/know for the dev

It just works!

Contra

Might be barely considered "Magic". Should be properly documented. However I don't see any use-case where hyperapp is supposed to crash. 😄


Meta:

Follow-up issue
Initial issue: subs didn't work when ran by onload

Error function in effects "is not a function"

There seems to be a regression, or the docs are wrong, regarding the signature of an effect-function.

When attempting to use the third parameter sent to an effect-function (documented as "error" -- a function you may call if something goes wrong), there console says:

Uncaught TypeError: error is not a function

(... assuming error is the name I gave the third parameter)

Demo: http://codepen.io/anon/pen/VPEYjj (forked from the effects-demo)

Push new release

This is not a big issue, just confuses newcomers, I guess:
now that you separated the router from the rest of the framework, (which is a good thing), the simple example in the getting started docs is no longer working, since the latest version has not been tagged && updated in npm. Of course, installing from git works out of the box.

HyperApp looks and feels really awesome, please continue your terrific work!

Breaks When Using <br/>

I tried to modify the counter example. When inserting a line-break <br/> it broke. 🙁

Console

InvalidCharacterError (DOM Exception 5): The string contains invalid characters.

Minimal Repro

app({
    view: () => html`<div>a<br/>b</div>`
})

Meta

Corresponding issue on hyperx's repo.
Related to choojs/hyperx#34.


Note that I do realize that <br> works. <br/> is more explicit though and as a React-user I'd like to keep this pattern.

Reorganize the dom diffing

I mean, it would be better to separate/reorganize the dom diffing "algorithm". Currently it works "by reference", so I think it would be better to be something like patch(newNode, oldNode) which would return the updated element.

I'm playing with this last days. And especially built something similar from scratch - 900bytes gzipped, without the html thing - it can be anything from custom to bel. Anyway, I'm just playing and currently I'm using nanomorph.

edit: hope you get what I'm talking about, haha.

Pass parameters to effects functions?

I am trying to build a simple login form with hyperapp. You are either already logged in, in which case you get a link to log out, or you are not logged in, in which case you get a username/password form.

Now to do the actual authentication of the username & password via the backend, I need to use an effect (asynchronous operation). But since effects don't take any parameters (as per the docs), and only have access to the model, that means I need to store the currently input username & password in my model. To achieve this, I must use reducers bound to oninput in each field. Just so I know i have the latest input value available to the login-effect, when it is called (in the onsubmit event of the form tag)

Two problems with this, that the ability to pass parameters to effects (just like you can for reducers), would solve:

  1. What the user types in the input & password fields is a temporary state. Those slots in the model aren't relevant once the user has logged in, and it seems wasteful to allocate space in the model for something that will only be relevant before the user is logged in. (And if they are already logged in, those slots will never be used)

  2. I don't really need the username/passwords in the model for any other reason. I'm just using the model to carry the values into the login-effect. So it seems a waste of computing power to have to update the model every time a key is typed, when all i really care about is what the values of the fields are at the time the user presses submit.

Errors for input tags in template strings

A simple demo:

app({
  model:  'hello',
  view: model => html`<div><input type="text" value="anything"></div>`
})

... errors out with:

TypeError: undefined is not an object (evaluating 't.data')

See here http://codepen.io/anon/pen/mRKJdZ

It can be simplified even further: just a plain <input> with no attributes has same result. Also trying to close it various ways ( <input />, <input></input> ... ) makes no difference.

Looks like it happens in the hyperx part of the code. However, I'm not familiar enough with hyperx to debug it or know how to submit a bug report to them. Or perhaps I'm doing something fundamentally wrong?

Router: Don't support browsers without history.pushState

Leaves out <=IE9, but includes IE10.

Why?

To save a few bytes is one reason, but more importantly, if we are going to support IE9, routing is not the only place that'll need refactoring, so it doesn't make sense to support hash-based routing on the premise that pushState is not supported in IE9 if we are not handling other IE9 edge cases.

Delegated Events

In all your examples you have events created directly on elements in your hyperx code. This is fine for simple examples. But if you have a situation where you are creating a complex UI with many interactive elements, attaching events to every single one is inefficient, and eats up memory. It would be nice if there was some way to delegate the events off of the view root. Maybe this is a problem due to using hyperx, since I don't see event delegation as possible in that framework either. Luckily Elm itself does have a solution for event delegation.

The Elm Architecture 🍵

Maybe it would be better if effects shouldn't be called directly by user but go along with result of updating model as a second element in an array or some other structure and that second element should be handled by runtime so it will be look more like TEA:

update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
  case msg of
    MorePlease ->
      (model, getRandomGif model.topic)

    NewGif (Ok newUrl) ->
      ( { model | gifUrl = newUrl }, Cmd.none)

    NewGif (Err _) ->
      (model, Cmd.none)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.