Tutorials

Registration Form

In this tutorial I'll be building a fully functional, however simplified, AJAX registration form for an imaginary web site.

The registration form could look something like this:

ui-sketch

Starting with the Naive Approach

This seems ridiculously simple, right? Enter username, fullname, click and you're done. As in

At first it might seem so, but if you're planning on implementing a top-notch form, you'll want to consider

  1. Username availability checking while the user is still typing the username
  2. Showing feedback on unavailable username
  3. Showing an AJAX indicator while this check is being performed
  4. Disabling the Register button until both username and fullname have been entered
  5. Disabling the Register button in case the username is unavailable
  6. Disabling the Register button while the check is being performed
  7. Disabling the Register button immediately when pressed to prevent double-submit
  8. Showing an AJAX indicator while registration is being processed
  9. Showing feedback after registration

Some requirements, huh? Still, all of these sound quite reasonable, at least to me. I'd even say that this is quite standard stuff nowadays. You might now model the UI like this:

dependencies

Now you see that, for instance, enabling/disabling the Register button depends on quite a many different things, some of them asynchronous.

In my original blog posting I actually implemented these features using jQuery, with appalling results. Believe me, or have a look...

Back to Drawing Board

Generally, this is how you implement an app with Bacon.js.

  1. Capture input into EventStreams and Properties
  2. Transform and compose signals into ones that describe your domain.
  3. Assign side-effects to signals

In practise, you'll probably pick a single feature and do steps 1..3 for that. Then pick the next feature and so on until you're done. Hopefully you'll do some refactoring on the way to keep your code clean.

Sometimes it may help to draw the thing on paper. For our case study, I've done that for you:

signals

In this diagram, the greenish boxes represent EventStreams (distinct events) and the gray boxes are Properties (values that change over time). The top three boxes represent the raw input signals:

  • Key-up events on the two text fields
  • Clicks on the register button

In this posting we'll capture the input signals, then define the username and fullname properties. In the end, we'll be able to print the values to the console. Not much, but you gotta start somewhere.

Setup

You can just read the tutorial, or you can try things yourself too. In case you prefer the latter, here are the instructions.

First, you should get the code skeleton on your machine.

So now you've cloned the source code and switched to the clean-slate branch. Alternatively you may consider forking the repo first and creating a new branch if you will.

Anyway, you can now open the index.html in your browser to see the registration form. You may also open the file in your favorite editor and have a brief look. You'll find some helper variables and functions for easy access to the DOM elements.

Capturing Input from DOM Events

Bacon.js is not a jQuery plugin or dependent on jQuery in any way. However, if it finds jQuery, it adds a method to the jQuery object prototype. This method is called asEventStream, and it is used to capture events into an EventStream. It's quite easy to use.

To capture the keyup events on the username field, you can do

And you'll get an EventStream of the jQuery keyup events. Try this in your browser Javascript console:

Now the events will be logged into the console, whenever you type something to the username field (try!). To define the username property, we'll transform this stream into a stream of textfield values (strings) and then convert it into a Property:

To see how this works in practise, just add the .log() call to the end and you'll see the results in your console.

What did we just do?

We used the map method to transform each event into the current value of the username field. The map method returns another stream that contains mapped values. Actually it's just like the map function in underscore.js, but for EventStreams and Properties.

After mapping stream values, we converted the stream into a Property by calling toProperty(""). The empty string is the initial value for the Property, that will be the current value until the first event in the stream. Again, the toProperty method returns a new Property, and doesn't change the source stream at all. In fact, all methods in Bacon.js return something, and most have no side-effects. That's what you'd expect from a functional programming library, wouldn't you?

The username property is in fact ready for use. Just name it and copy it to the source code:

I intentionally omitted "var" at this point to make it easier to play with the property in the browser developer console.

Next we could define fullname similarly just by copying and pasting. Shall we?

Nope. We'll refactor to avoid duplication:

Better! In fact, there's already a textFieldValue function available in Bacon.UI, and it happens to be included in the code already so you can just go with

So, there's a helper library out there where I've shoveled some of the things that seems to repeat in different projects. Feel free to contribute!

Anyway, if you put the code above into your source code file, reload the page in the browser and type

to the developer console, you'll see username changes in the console log.

Mapping Properties and Adding Side-Effects

To get our app to actually do something visible besides writing to the console, we'll define a couple of new Properties, and assign our first side-effect. Which is enabling/disabling the Register button based on whether the user has entered something to both the username and fullname fields.

I'll start by defining the buttonEnabled Property:

So I defined the Property by combining to props together, with the and function. The combine method works so that when either usernameEntered and fullnameEntered changes, the result Property will get a new value. The new value is constructed by applying the and function to the values of both props. Easy! And can be even easier:

This does the exact same thing as the previous one, but relies on the boolean-logic methods (and, or, not) included in Bacon.js.

But something's still missing. We haven't defined usernameEntered and fullnameEntered. Let's do.

So, we used the map method again. It's good to know that it's applicable to both EventStreams and Properties. And the nonEmpty function is actually already defined in the source code, so you don't actually have to redefine it.

The side-effect part is simple:

Try it! Now the button gets immediately disabled and will enabled once you type something to both the text fields. Mission accomplished!

But we can do better.

For example,

This relies on te fact that the onValue method, like many other Bacon.js methods, supports different sets of parameters. One of them is the above form, which can be translated as "call the attr method of the register button and use disabled as the first argument". The second argument for the attr method will be taken from the current property value.

You could also do the same by

Now we rely on the setEnabled function that's defined in our source code, as well as registerButton. The above can be translated to "call the setEnabled function and use registerButton as the first argument".

So, with some Bacon magic, we eliminated the extra anonymous function and improved readability. Om nom nom.

And that's it for now. We'll do AJAX soon.

Ajax and Stuff

This is the next step in the Bacon.js tutorial series. I hope you've read Part II already! This time we're going to implement an "as you type" username availability check with AJAX. The steps are

  1. Create an EventStream of AJAX requests for use with jQuery.ajax()
  2. Create a stream of responses by issuing an AJAX request for each request event and capturing AJAX responses into the new stream.
  3. Define the usernameAvailable Property based on the results
  4. Some side-effects: disable the Register button if username is unavailable. Also, show a message.

I suggest you checkout the example code and switch to the tutorial-2 branch which will be the starting point for the coding part of this posting. If you just want to have a look at what we've got so far, have a peek.

So, at this point we've got a Property called username which represents the current value entered to the username text input field. We want to query for username availability each time this property changes. First, to get the stream of changes to the property we'll do this:

This will return an EventStream. The difference to the username Property itself is that there's no initial value (the empty string). Next, we'll transform this to a stream that provides jQuery compatible AJAX requests:

The next step is extremely easy, using Bacon.UI.js:

This maps the requests into AJAX responses. Looks very simple, but behind the scene it takes care of request/response ordering so that you'll only ever get the response of the latest issued request in that stream. This is where, with pure jQuery, we had to resort to keeping a counter variable for making sure we don't get the wrong result because of network delays.

So, what does the ajax() method in Bacon.UI look like? Does it do stuff with variables? Lets see.

Not so complicated after all. But let's talk about flatMap now, for a while, so that you can build this kind of helpers yourself, too.

AJAX as a Promise

AJAX is asynchronous, hence the name. This is why we can't use map to convert requests into responses. Instead, each AJAX request/response should be modeled as a separate stream. And it can be done too. So, if you do

you'll get a jQuery Deferred object. This object can be thought of as a Promise of a result. Using the Promise API, you can handle the asynchronous results by assigning a callback with the done(callback) function, as in

If you try this in you browser, you should see true printed to the console shortly. You can wrap any Promise into an EventStream using Bacon.fromPromise(promise). Hence, the following will have the same result:

This is how you make an EventStream of an AJAX request.

AJAX with flatMap

So now we have a stream of AJAX requests and the knowhow to create a new stream from a jQuery AJAX. Now we need to

  1. Create a response stream for each request in the request stream
  2. Collect the results of all the created streams into a single response stream

This is where flatMap comes in:

Now you'll have a new EventStream called availabilityResponse. What flatMap does is

  1. It calls your function for each value in the source stream
  2. It expects your function to return a new EventStream
  3. It collects the values of all created streams into the result stream

Like in this diagram.

flatMap

So here we go. The only issue left is that flatMap doesn't care about response ordering. It spits out the results in the same order as they arrive. So, it may (and will) happen that

  1. Request A is sent
  2. Request B is sent
  3. Result of request B comes
  4. Result of request A comes

.. and your availabilityResponse stream will end with the wrong answer, because the latest response is not for the latest request. Fortunately there's a method for fixing this exact problem: Just replace flatMap with flatMapLatest (previously called "switch") and you're done.

switch

Now that you know how it works, you may as well use the ajax() method that Bacon.UI provides:

POW!

The easy part : side-effects

Let's show the "username not available" message. It's actually a stateful thing, so we'll convert the availabilityResponse stream into a new Property:

The boolean value is used to give the property a starting value. So now this property starts with the value true and after that reflects that value from the availabilityRequest stream. The visibility of the message element should actually equal to the negation of this property. So why not something like

Once again, this is equivalent to

... the idea in the former being that we partially-apply the setVisibility function: Bacon will call the function with unavailabilityLabel fixed as the first argument. The second argument to the function will be the value from the usernameAvailable.not() Property.

Finally, we'll also disable the Register button when the username is unavailable. This is done by changing

to

The result code can be found in the tutorial-3 branch.

Wrapping Things in Bacon

I've got a lot of question along the lines of "can I integrate Bacon with X". And the answer is, of course, Yes You Can. Assuming X is something with a Javascript API that is. In fact, for many values of X, there are ready-made solutions.

  • JQuery events is supported out-of-the box
  • With Bacon.JQuery, you get more, including AJAX, two-way bindings
  • Node.js style callbacks, with (err, result) parameters, are supported with Bacon.fromNodeCallback
  • General unary callbacks are supported with Bacon.fromCallback
  • There's probably a plenty of wrappers I haven't listed here. Let's put them on the Wiki, shall we?

In case X doesn't fall into any of these categories, you may have to roll your own. And that's not hard either. Using Bacon.fromBinder, you should be able to plug into any data source quite easily. In this blog posting, I'll show some examples of just that.

You might want to take a look at Bacon.js readme for documentation and reference.

Example 1: Timer

Let's start with a simple example. Suppose you want to create a stream that produces timestamp events each second. Easy!

Using Bacon.interval, you'll get a stream that constantly produces a value. Then you can use map to convert the values into timestamps.

Using Bacon.fromPoll, you can have Bacon call your function each 1000 milliseconds, and produce the current timestamp on each call.

So, clearly Using Bacon.fromBinder is an overkill here, but if you want to learn to roll your own streams, this might be a nice example:

Try it out: http://jsfiddle.net/PG4c4/

So,

  • you call Bacon.fromBinder and you provide your own "subscribe" function
  • there you register to your underlying data source. In the example, setInterval.
  • when you get data from your data source, you push it to the provided "sink" function. In the example, you push the current timestamp
  • from your "subscribe" function you return another function that cleans up. In this example, you'll call clearInterval

Example 2: Hammer.js

Hammer.js is a library for handling multi-touch gesture events. Just to prove my point, I created a fiddle where I introduce a "hammerStream" function that wraps any Hammer.js event into an EventStream:

Try it out: http://jsfiddle.net/axDJy/3/

It's exactly the same thing as with the above example. In my "subscribe" function, I register an event handler to Hammer.js. In this event handler I push a value "hammer time!" to the stream. I return a function that will de-register the hammer event handler.

More examples

You're not probably surprised at the fact that all the included wrappers and generators (including $.asEventStream, Bacon.fromNodeCallback, Bacon.interval, Bacon.fromPoll etc) are implemented on top of Bacon.fromBinder. So, for more examples, just dive into the Bacon.js codebase itself.

Structuring Real-Life Applications

The Internet is full of smart peanut-size examples of how to solve X with "FRP" and Bacon.js. But how to organize a real-world size application? That's been asked once in a while and indeed I have an answer up in my sleeve. Don't take though that I'm saying this is the The Definitive Answer. I'm sure your own way is as good or better. Tell me about it!

I think there are some principles that you should apply to the design of any application though, like Single Reponsibility Principle and Separation of Concerns. Given that, your application should consist of components that are fairly independent of each others implementation details. I'd also like the components to communicate using some explicit signals instead of shared mutable state (nudge nudge Angular). For this purpose, I find the Bacon.js EventStreams and Properties quite handy.

So if a component needs to act when a triggering event occurs, why not give it an EventStream representing that event in its constructor. The EventStream is an abstraction for the event source, so the implementation of your component is does not depend on where the event originates from, meaning you can use a WebSocket message as well as a mouse click as the actual event source. Similarly, if you component needs to display or act on the state of something, why not give it a Property in its constructor.

When it comes to the outputs of a component, those can exposed as EventStreams and Properties in the component's public interface. In some cases it also makes sense to publish a Bus to allow plugging in event sources after component creation.

For example, a ShoppingCart model component might look like this.

Internally, the ShoppingCart contents are composed from an initial status and addBus and removeBus streams using Bacon.update.

The external interface of this component exposes the addBus and removeBus buses where you can plug external streams for adding and removing items. It also exposes the current contents of the cart as a Property.

Now you may define a view component that shows cart contents, using your favorite DOM manipulation technology, like virtual-dom:

And a component that can be used for adding stuff to your cart:

And you can plug these guys together as follows.

So there you go!

Bus of Doom

In a previous Bacon blog post a way to structure Bacon application was outlined. It introduces Buses as a central way to glue components with each other. I'm in a very strong disagreement with the proposed style. Why?

Quoting Erik Meijer

Subjects are the "mutable variables" of the Rx world and in most cases you do not need them.

In Bacon parlance that would be

Buses are the "mutable variables" of the Bacon world and in most cases you do not need them.

Now, that needs an explanation. We can split the statement to two parts and treat each individually. "Why Buses (and mutable variables) are bad", then "why you don't usually need them".

Problems with Bus

There was a time when data structures in our programs were built by mutating those data structures. In case you have entered this field only recently you may be a lucky one and haven't seen that madness in full glory (== spaghetti).

This was a bad idea as it creates temporal dependencies all over the program, making it difficult to locally understand how a piece of code works. Instead, a global view on a program is required. Who mutates what and when. It also created many bugs as components of a system are from time to time in an invalid state. Most common invalid state being at a construction phase where fields are initialized to nulls. A whole slew of bugs were eliminated and sanity regained by moving to immutable data.

Ok, what does all that have to do with Buses? Well, Buses introduce similar temporal dependencies to your program. Is that component ready to be used? I don't know, did you plug its Buses already with this and that?

Here's a recent bug (simplified from a real world app) found in our company's internal chat. Can you spot it?

There's a chance that the ajax call on line 2 returns before line 4 is executed, thus the event is completely missed. It is temporal dependencies like that which are nearly impossible to understand in a bigger context. And what's worse, these bugs are difficult to reproduce as we are programming in a setting where stuff is nondeterministic (timers, delays, network calls etc.). I'm sure that many Bus fetished programs contain subtle bugs like above.

How to avoid Buses

I'll give examples of techniques avoiding Buses by refactoring the example in the previous blog post.

The first one is simple and obvious. Turn inputs of a component to be input arguments of the component.

Before:

After:

I'm pretty sure everyone agrees that the refactored version is simpler.

The next refactoring has to do with remove links. Each shopping cart item will have a link and clicking a link will remove the item from a cart. The refactored version of the ShoppingCart needs removeItem click stream as a function argument, but the individual items are created dynamically as the user selects items. This can be solved by event delegation.

You can state just once and for all: here's a stream of clicks of every .remove-item link in the shopping cart, and of all the future .remove-item links that will appear in the shopping cart. That is fantastic. It's like, you put it there and there it is. Event delegation is such a god sent tool and my heart fills with joy every time I have a chance to use it. After that the click events must be associated with items. A canonical way to do it is with data attributes.

Now the sample program is Bus-free.

All done? Not yet. removeItemStream is hanging there while it probably should be part of ShoppingCartView.

Whoops, now we introduced a cyclic dependency between ShoppingCart and ShoppingCartView.

Cyclic dependency is often given as an example where Buses are needed. After all the hard work should we now reintroduce Buses?

Here a Bus can be used to break the cyclic dependency, just as a mutable variable would do if you will. But we have other options too. Why don't we factor the components so that the cyclic dependency completely disappears.

Similar factorings can be almost always used to break cyclic dependencies.

Conclusion

Avoid Buses. View those as mutable variables and you will understand the kinds of problems they create. By relating Buses to mutable variables gives you an intuition on how to avoid those in a first place.