Skip to content

Instantly share code, notes, and snippets.

@veggiemonk
Forked from MattMcFarland/gist:25fb4f0241530d2f421a
Last active September 7, 2015 13:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save veggiemonk/d0a374691121a92e5ec4 to your computer and use it in GitHub Desktop.
Save veggiemonk/d0a374691121a92e5ec4 to your computer and use it in GitHub Desktop.
FLUX for Mithril

Table of Contents:

Why FLUX?

I prefer the FLUX pattern to MVC, and I have been successful in applying the FLUX pattern without running into too much trouble.

About this Guide

This mini-howto guide is intended for an audience with experience using FLUX. My personal experience with flux may easily be lesser than some of those reading. Please assume that I am happy to be corrected, should this guide imply anything that may be detrimental (other than using flux on its own of course ;))

Should there be a large enough audience, I will write a more comprehensive guide.

Library Dependencies

  • Mithril.js - Of course!
  • Bullet - an ultra-lightweight event emitter (0.975 kB minified, smaller when gzipped)
  • MSX support (I currently just use Browserify/Mithrilify, but I think babelify could be used later)

The React or Flux API libraries are NOT used.

Directory Structure

My filebase currently is comprised like so, (this is not optimized for scalability, as this is an experiment)

src/
	
	actions.js
	constants.js
	dispatcher.js
	index.js (browserify entry point)
	store.js

src/components

	...
	app.js

store.js

var Bullet = require('bullet-pubsub'),
    Constants = require('./constants'),
    _data = { showSidebar: false};


var Store = {

    getAll: function () {
        return {data: _data};
    },
    // Allow Controller-View to register itself with store
    addChangeListener: function (callback) {
        Bullet.on(Constants.CHANGE_EVENT, callback);
    },
    removeChangeListener: function (callback) {
        Bullet.removeListener(Constants.CHANGE_EVENT, callback);
    },
    // triggers change listener above, firing controller-view callback
    emitChange: function () {
        Bullet.trigger(Constants.CHANGE_EVENT);
    },

    dispatchIndex: function (payload) {
        console.log('PAYLOAD:', payload);
        switch (payload.type) {
            case Constants.ActionTypes.TEST_STORE:
                _data.message='test store works';
                Store.emitChange();
                break;
            case Constants.ActionTypes.SHOW_SIDEBAR:
                _data.showSidebar = true;
                Store.emitChange();
                break;
            case Constants.ActionTypes.HIDE_SIDEBAR:
                _data.showSidebar = false;
                Store.emitChange();
                break;

        }
    }

};

module.exports = Store;

constants.js

module.exports = {
    CHANGE_EVENT: 'CHANGE_EVENT',

    ActionTypes: {
        TEST_STORE: 'TEST_STORE',
        SHOW_SIDEBAR: 'SHOW_SIDEBAR',
        HIDE_SIDEBAR: 'HIDE_SIDEBAR'
    }
};

dispatcher.js

var Store = require('./store');

module.exports = function (payload) {

    Store.dispatchIndex(payload);

};

actions.js

var Constants = require('./constants');
var Dispatcher = require('./dispatcher');

module.exports = {

    testStore: function (data) {
        Dispatcher({
            type: Constants.ActionTypes.TEST_STORE,
            data: data
        })
    },
    showSidebar: function () {
        Dispatcher({
            type: Constants.ActionTypes.SHOW_SIDEBAR
        });
    },
    hideSidebar: function () {
        Dispatcher({
            type: Constants.ActionTypes.HIDE_SIDEBAR
        });
    }


};

app.js

require('./app.less');

// Framework
var Store = require('../store'),
    Actions = require('../actions');

// Sub-Components
var TopNav = require('./topnav'),
    Sidebar = require('./sidebar'),
    PostList = require('./PostList');

var App = {
    state: {
        data: {}
    },
    _onChange: function () {
        App.state = Store.getAll();
    },
    controller: function() {
        return {
            onunload: function () {
                Store.removeChangeListener(App._onChange);
            }
        }
    },
    view: function(ctrl) {
        return (
            <div>
                <TopNav/>
                <Sidebar/>
                <div class="container-fluid">
                    <PostList/>
                </div>
            </div>
        )
    }
};

Store.addChangeListener(App._onChange);


module.exports = App;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment