Skip to content

Instantly share code, notes, and snippets.

@avesus
Forked from MattMcFarland/gist:25fb4f0241530d2f421a
Last active August 29, 2015 14:27
Show Gist options
  • Save avesus/0646f118fed2c325c285 to your computer and use it in GitHub Desktop.
Save avesus/0646f118fed2c325c285 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