

Show HN: Way.js – Simple, persistent, framework-agnostic two-way databinding - ges
http://gwendall.github.io/way/

======
lhorie
Maybe I'm just missing something, but is there no way to deal with arrays? You
know, like looping through data and displaying things for each of them? (also
related: what about looping through Object.keys()?)

What about dates? And data parsing/formatting in general?

Those are kind of important for a bi-directional bindings library. Remember
that the Javascript data is usually the canonical data and the displayed data
is derived from it, not the other way around.

If you want to compare w/ Knockout/Angular/etc then there's even more stuff
that could be considered as "missing" (e.g. condiditionals,
partials/components, how-do-i-use-select2-with-it, etc). One could argue those
are out of scope for a lightweight library, but then again, I think this
library has too many dependencies for something that advertises itself as
"lightweight".

My own framework Mithril (
[http://lhorie.github.io/mithril](http://lhorie.github.io/mithril) ) for
example is ~5kb gzipped, has no dependencies, and allows you to do quite a bit
more in terms of templating and data binding.

Incidentally, I wrote a article a while back about how two-way binding isn't
even always the best answer to your questions, and that there are often better
ways to update javascript data from forms: [http://lhorie.github.io/mithril-
blog/asymmetrical-data-bindi...](http://lhorie.github.io/mithril-
blog/asymmetrical-data-bindings.html)

~~~
nakovet
Correct link for Mithril:
[http://lhorie.github.io/mithril/](http://lhorie.github.io/mithril/)

~~~
lhorie
Yeah, sorry, I just fixed it :)

------
sleepyhead
Why use invalid 'way-data'-attributes when there is data-attributes?

~~~
datashaman
+1.

------
onion2k
Looks very nice indeed. Especially like the low overhead. I've been using an
alternative, Cortex[1], recently. It's similar, but with a pubsub based
eventing system so your updates don't need to be broadcast to every component
that uses the data model (e.g. you can subscribe callbacks to specific changes
in the model). It works nicely with React.js. Worth a look if way.js isn't
quite enough.

[1] [https://github.com/mquan/cortex](https://github.com/mquan/cortex)

------
threeseed
Might be worth benchmarking against the others:

[http://jsperf.com/angular-vs-knockout-vs-
ember/351](http://jsperf.com/angular-vs-knockout-vs-ember/351)

For me personally I am loving VueJS right now.

~~~
girvo
I'm entirely in love with VueJS. It's just amazing. I only wish I could use it
with IE8 so I could replace our old version of Angular that we're stuck with
at work, but hey, somethings got to give to get that nice an API.

~~~
nailer
Vue / Ractive / React. I'm not a reactive programming nerd, I just want
something simple, and all three of these are implemented so well.

------
plq
I've been working on something pretty similar, but on the server side. It's
called 'Neurons', and it's a pre-alpha Python library. It's built on Spyne[3],
an RPC framework which is another side project of mine that I've been working
on for ~4 years now.

The aim with neurons initially is to let you generate a html form (e.g. [1])
and related services from just a model definition and an instance of this
model (e.g. [2]), making it a breeze to publish CRUD pages. It currently
handles complex stuff like dates, times, arrays and nested objects just fine.

In Spyne terms, that's "serializing a model instance using the HtmlForm
protocol". The same object definition can be used to for other protocols like
json as well as for persisting data to a relational database (via SQLAlchemy).
You can play with the code generator at [http://spyne.io](http://spyne.io) to
get a better feel about how it works.

One could even write a Spyne protocol that renders a given model instance to
way.js code.

Help is welcome!

[1]:
[https://github.com/plq/neurons/blob/test_output/html/test_si...](https://github.com/plq/neurons/blob/test_output/html/test_simple_array.html)

[2]:
[https://github.com/plq/neurons/blob/fccab8fee4c1795f65ac3f9b...](https://github.com/plq/neurons/blob/fccab8fee4c1795f65ac3f9b20d79cb1e9279a3f/neurons/form/test/test_form.py#L193)

[3]: [http://spyne.io](http://spyne.io)

~~~
woah
Oh man, I've had to work on projects with serverside form generation (python
people are really into this stuff for some reason), and it's a huge pain.
Backend engineer thinks it's going to be way easier or something not having to
write templates, however on the frontend, the code generated by these tools is
always weird and different from the rest of the markup. No thanks.

~~~
plq
FWIW, with neurons, there's always the option to override markup generation on
a field-by-field basis, so if you don't like the generated code for a certain
part of the document, you can change it to your heart's content.

You'll even be able to pass templates down a certain object hierarchy, but
that's further down the pipeline.

------
chrismorgan
I applied to the example here the first test I always make of any things like
this: HTML injection. Result: failure. ☹

~~~
cwmma
yup, my go to test name:

\\_(ʘ_ʘ)_/ "'<!--/*༼ つ ◕_◕ ༽つ

caused it to show

{ "formData": { "name": "\\\\_(ʘ_ʘ)_/ \"'

~~~
ges
Thanks! Fixed. I added a "way-html" attribute (boolean, false by default) that
you can pass to your DOM elements.

------
ishener
That's the only javascript framework one needs.

Actually I've been wanting to write something like that for a long time but
didn't get around to it. Nice to see someone else did exactly what I wanted...

~~~
itry
Does anybody have real world examples of websites that use this kind of thing?

Im always under the assumption that the old "post data to server, save it
there" model still works best. Am I missing something?

~~~
Lazare
If what you're doing is simple enough that "serialise the form, send to
server, wait for response, do a full page reload" works for you, then no, you
don't need two-way data binding, and in fact wouldn't have any use for it. You
only need two-way data binding if you need your client-side code to respond to
user input, which a truly basic form doesn't need to do.

Of course, for a good user experience, you probably want to do client-side
validation of the form; while you can do that a bunch of ways one of the
easier ways (from a developer's point of view) is two-way data binding, and
I'm using it on a few contact forms, signup forms, file upload forms, etc.,
scattered around the web for just that purpose.

And if you're doing something more complicated, then you probably want your
client side code to respond to user input. If you're using __ANY __client-side
MVC, or if you 're getting real time updates from a server (via websockets or
whatever), or if you're basically doing any sort of "app" style functionality
in the client, you'll probably need two way data binding or its functional
equivalent. I've written a big CRM webapp that uses two-way data binding
extensively; the old "every click is a full HTTP round trip" model would
deliver a shockingly bad user experience.

That being said, two-way data binding isn't the only way to implement rich
client-side functionality, it's just one of the conceptually simplest ways of
doing it. Backbone has two-way data binding plugins, but the "default" is to
use events instead. Ditto for React. But something needs to tie your client
side code to user input, and one of the simple "somethings" is two way data
binding.

But again, if your app doesn't have any client side code, obviously you don't
need anything to tie user input to the code you don't have. So if your app
doesn't need any more client-side functionality than, eg, Hacker News has,
then you have no need for two-way data binding (or, hell, any JS code at all).
But if you want something a bit more interactive, then you need _something_.

(That being said, I still have no idea what makes this library better than any
of the many popular, mature libraries that already exist. I've used Knockout
quite a bit; it works well.)

~~~
itry
Im sceptical. You know why? You wrote all this text instead of giving me a
real world example and said "look, this would be shitty without a 2-way-data-
binding-library".

~~~
Lazare
I listed multiple real world examples. Not sure what else you want.

Again, _IF_ you have client side JS code, _AND_ it needs to respond to user
input, _THEN_ you need code to trigger that such as two-way data binding, and
event bus, dispatchers, whatever. If you do not have client side JS code, or
it does not need to respond to user input, then you don't need any of that.
Are you asking why you would have client side JS code at all, or...?

~~~
itry
> I listed multiple real world examples.

I see no URLs in you text.

> THEN you need code to trigger that

I didnt't say you never need js code that reacts to input. I said: does
anybody have real world examples where this type of library is useful?

Because most of the time I get along well with sending input to the server.
And in the few cases I needed js to deal with user input I got along nicely
with simple event handlers.

~~~
Lazare
> I didn't say you never need js code that reacts to input.

Actually, you kinda did:

> Im always under the assumption that the old "post data to server, save it
> there" model still works best.

Whatever you were trying to say with that question, I don't think it was
coming through. Anyhow, to answer your actual question:

> I wonder who benefits from this kind of library. You can react to user input
> with a simple keyup event.

Well, obviously. The use case for two-way data binding is _every single place
you would ever use a simple keyup event_. The two approaches do the same thing
in very similar ways; and a two-way data binding library is generally nothing
more than some simple boilerplate over the plain event binding. For example,
with Knockout you could put this in your HTML:

    
    
        <input data-bind="event: { keypress: handler}" />
    

Or if you like jQuery you could put this:

    
    
        <input id="field1" />
    

And then in your JS you could put this:

    
    
        $('#field1').keypress(handler);
    

As far as reacting to user input, they do the exact same thing in the exact
same way. The difference is that Knockout example has very slightly less
typing, that it's (to my eyes) very slightly clearer what's going on when you
look at the HTML.

There's a lot of ways to structure an app. Two-way data binding helps with one
of the obvious ways; it's simple and (if you're sane about it), clear. Which
is probably why it's a core part of Angular, Knockout, Ember, Mithril, Vue,
Ractive, and a bunch more frameworks besides, and provided by popular plugins
for Backbone and React.

TL;DR: People who want some boilerplate to hide a bunch of ugly event binding.

Edit: To be clear, two-way data binding is one of many ways of organising an
app, and by no means the best way. But if your question is "why not just use
some random event bindings", I'm not sure you understand the problem space.

------
ges
Github repo:
[https://github.com/gwendall/way.js](https://github.com/gwendall/way.js)

~~~
myhf
How does it compare to other framework-agnostic binders such as Rivets.js?

------
matthewmacleod
I would also suggest looking at Rivets
([http://rivetsjs.com](http://rivetsjs.com)) which is my current go-to
solution for this sort of thing.

------
mattdesl
Polluting global scope and a hard dependency on jQuery.. :(

~~~
ges
It is now stand-alone and doesn't mess with global scope anymore (except for
the "way" object allowing you to set watchers, etc)

------
Kiro
Looks very straight-forward. Good job!

OT: After building a couple of large applications in Angular I've come to
realize that I seldom need two-way bindings. The school example where you
enter something in an input box and it shows up somewhere else in real-time is
not really used in the real world. Or is it? Why do we need two-way data
binding?

~~~
AndrewDucker
I rarely need _simultaneous_ two-way databinding.

But I do sometimes need databinding from view to model (when I want users to
enter data, and it just fills in my object), and I sometimes want databinding
from model to view (where my data is nicely displayed).

So rather than doing something fiddly and different for each way, it makes
more sense to just have 2-way databinding in the first place.

And that then makes it easier for when I _do_ want 2-way databinding - for
instance allowing users to enter a filter to narrow down a list.

~~~
itry
> allowing users to enter a filter

Wouldn't it be enough to add a keydown event to the field?

------
Ronsenshi
Great job, i just wish it was at least no dependent on several other libraries
including jQuery.

~~~
batiste
I wrote this library which is similar in many ways and is also standalone

[http://batiste.info/likely.js/](http://batiste.info/likely.js/)

------
jesalg
This is cool but in real world scenarios you need more functionality to make
it useful. So far I've been using KnockoutJS where I don't need full-blown MVC
and can get away with MVVM.

------
danhanly
Is it me, or should the description read: "This form is bound to the
'formData' property" instead of "This form is binded to the 'formData'
property"

~~~
alexjeffrey
it should, but it doesn't benefit the conversation to point out grammatical
errors - plenty of HN users are not natively english-speaking so it's probably
best to just let it slide.

------
rubiquity
We're still using HTML attributes, and in this case invalid HTML attributes,
to add behavior via JavaScript? When are we going to learn :/

------
nawitus
How does Way.js detect changes made in JavaScript to the values? E.g. if you
set a new property to the object, is it reflected in the DOM?

------
dodyg
How do you compare this with ractivejs.org?

~~~
nailer
A cursory glance: ractive uses mustache, way uses HTML attributes. Ractive
requires you to actually create the binding, way just leverages that HTML.

------
antonwinter
looks damn fine,

less dependencies would be an added bonus

