Cycle.js tutorial: Registration Form – Part 2

Share

This tutorial is the second part of our previous tutorial where we built a simple registration form using Cycle.js. In this part, we will introduce some basic concepts for building Cycle.js like seeds, intents and state.

1 Cycle.js tutorial: Registration Form – Part 2

This tutorial is the second part of our previous tutorial where we built a simple registration form using Cycle.js. In this part, we will introduce some basic concepts for building Cycle.js like seeds, intents and state.

Online demo is available here. Source code for this tutorial is available in Github.

1.1 About Cycle.js

Cycle.js is a functional and reactive JavaScript framework for predictable code created by Andre Staltz from Futurice.

1.2 Create the application boilerplate

The quickest way to create a new project with Cycle.js is by using create-cycle-app.

npm install --global create-cycle-app
create-cycle-app my-awesome-app

The application folder structure will look like this:

folder-structure-small.jpg

Inside the src/ directory, we will be having the source code:

  • app.js => will have your app source code, this is where we will be putting our logic
  • main.js => will have main() function which will be executed by Cycle.run
  • app.test.js => will have tests for your app

1.3 Defining the state update function

In this section we will define a simple function for updating our application state based on the user actions automatically.

const scanFn = curry((state, updateFn) => {
  return updateFn(state);
});

We are using the curry function from ramda, which is a practical functional programming library for Javascript programmers. Unlike the likes of underscore.js and lodash, ramda really shines as a truly functional programming library for Javascript.

If you want to learn more about ramda, go to their official documentation.

1.4 Defining seeds for the application state

For any application, we need to start from somewhere to initialize the application state to a bare minimum, so that the user will have something to interact with. Seeds are the things which rightfully serve the exact place for the initial application state.

const seeds = {
  username: '',
  email: ''
};

1.5 Defining the application intents

Here we will be defining the actual user actions which in turn modify the application state as a collective object so that it will be easier for the developer to maintain the actions in a single place.

Model-View-Intent (MVI) is reactive, functional, and follows the core idea in MVC. It is reactive because Intent observes the User, Model observes the Intent, View observes the Model, and the User observes the View.

For every DOM element with which the user will be interacting with we need to define a set of actions or inputs for which the application state will be reacting to.

In our case, we will be interacting mainly with our input boxes, and for each input field we wil be doing the following:

  • From the DOM Source get the input dom element
  • Capture only the input events for the element
  • Map each event to the value of the input element i.e., the target

To know more about the MVI architecture, go the Cycle.js documentation

const intents = {
  changeUsername: sources.DOM.select("#username")
    .events('input')
    .map((event) => event.target.value),

  changeEmail: sources.DOM.select("#email")
    .events('input')
    .map((event) => event.target.value)
};

1.6 Defining our application state

Its time to define our application state based on the intents which we have created previously.

Our state is a single stream got by merging the two intents changeUsername and changeEmail and mapping their corresponding values.

const state$ = xs.merge(
    // Track fields
    intents.changeUsername.map((v) => assoc('username',v)),
    intents.changeEmail.map((v) => assoc('email',v))
  )
  .fold(scanFn,seeds)
  .remember();

1.7 Constructing the virtual DOM tree

Here we are constructing the Virtual DOM using the application state. We are using React like JSX syntax here, since it feels natural to write HTML markup in HTML rather than using some little confusingly hyperscript syntax.

For our Virtual DOM, we use snabbdom-jsx which will provide you to write some HTML markup inside Javascript.

const vtree$ = state$.map((state) => {
    return (
        <div>
          <h1>Registration</h1>
          <div className='form-element'>
            <label for='username'>Username:</label>
            <br/>
            <input id="username" type="text" autocomplete="off"/>
          </div>
          <div className='form-element'>
            <label for='email'>Email:</label>
            <br/>
            <input id="email" type="email" autocomplete="off"/>
          </div>
          <hr/>
          <h2>State SPY</h2>
          <pre>{ JSON.stringify(state,null,2)}</pre>
        </div>
    );
  });

state-spy2.jpg

Also, we are capturing the application state using the values stored in username and email and rendering them in the DOM using pre tags in JSON format.

1.8 Returning the output sinks

Finally we are returning the virtual DOM tree as output sinks back again to the main function.

const sinks = {
    DOM: vtree$
  };
return sinks;

1.9 Links