api


okwolo()

      
        const app = okwolo([target[, window]]);
  // target: DOM node
  // window: window object can be specified if needed
      
    

+ example

          
            const okwolo = require('okwolo/standard');

// create an app that does not render (target blob can be added later)
const app1 = okwolo();

// create an app that renders to the body
const app2 = okwolo(document.body);

// create an app that uses a different window object
const app3 = okwolo(document.body, _window);
          
        

app()

The app function defines the layout for the application. It is overloaded to also accept a path as first argument in order to easily describe routes.

      
        app(init)
  // init: curried element builder function [() => (state) => element]
app(route, init);
  // route: string pattern to match paths (same as in express)
  // init: curried element builder function [(routeParams) => (state) => element]
      
    

+ example

          
            const app = okwolo(document.body);

app.setState({
    greeting: 'Hello ',
    default: 'Hello World!',
});

// render this element if path matches
app('/user/:username', ({username}) => (state) => (
    ['div', {}, [
        state.greeting,
        username,
    ]]
));

// fallback to render this element regardless of route
app('**', () => (state) => (
    ['div', {}, [
        state.default,
    ]]
));
          
        

app.setState()

Sets the state from which layout is created.

The setState function needs to be called in order for the app to render to any target.

      
        app.setState(state);
  // state: an object to replace the current state
app.setState(updater);
  // updater: function that returns the new state [(currentState) => ... newState]
      
    

+ example

          
            // will not render until state is set
app(() => (state) => (
    ['div', {}, [
        ['h1', {}, [
            'Title',
        ]],
        ['p', {}, [
            'Content',
        ]],
    ]]
));

// will throw an error if state has not been set
app.act('ACTION_TYPE');

// will throw an error if state has not been set
app.getState();

// set the internal state
app.setState({});
          
        

app.getState()

Returns a copy of the current state.

      
        app.getState();
      
    

+ example

          
            app.setState([0, 1, 2]);

app.getState(); // [0, 1, 2]
          
        

app.act()

Executes an action on the state.

      
        app.act(type[, params]);
  // type: string of the action type
  // params: arguments given to the action handler
app.act(action);
  // action: function that returns the new state [(currentState) => ... newState]
      
    

+ example

          
            app.setState({
    friends: [],
});

app.use('action', {
    type: 'ADD_FRIEND',
    target: [],
    handler: (state, newFriend) => {
        state.friends.push(newFriend);
        return state;
    },
});

const newFriend = {
    name: 'John',
    hobbies: ['kayaking', 'cooking'],
};

/* calling an ADD_FRIEND action and passing
the newFriend to the action handler */
app.act('ADD_FRIEND', newFriend);
          
        

app.undo()

Undoes the last action (or setState).

      
        app.undo();
      
    

+ example

          
            app.setState(0);

app.use('action', {
    type: 'INC',
    target: [],
    handler: (state, amount = 1) => {
        return state + amount;
    },
});

app.act('INC'); // 1
app.act('INC', 3); // 4
app.undo(); // 1
          
        

app.redo()

Redoes the previous action.

      
        app.redo();
      
    

+ example

          
            app.setState(0);

app.use('action', {
    type: 'INC',
    target: [],
    handler: (state, amount = 1) => {
        return state + amount;
    },
});

app.act('INC'); // 1
app.act('INC', 3); // 4
app.undo(); // 1
app.redo(); // 4
          
        

app.resetHistory()

Resets the state history stacks. This will render subsequent undo/redo operations useless unless state is changed once more.

      
        app.resetHistory();
      
    

+ example

          
            app.setState(0);

app.use('action', {
    type: 'INC',
    target: [],
    handler: (state, amount = 1) => {
        return state + amount;
    },
});

app.act('INC'); // 1
app.act('INC', 3); // 4
app.resetHistory();
app.undo(); // 4
app.redo(); // 4
          
        

app.redirect()

Changes the url and renders layout from the new route.

      
        app.redirect(path[, params]);
  // path: string of the new pathname
  // params: object to be passed to the route handler
      
    

+ example

          
            app('/home', (params) => (state) => (
    ['div', {}, [
        params.content || 'home',
    ]]
));

// renders the route and passes it the params
// will also change the browser's url
app.redirect('/home', {content: 'Hello World!'});
          
        

app.show()

Renders layout from the new route.

      
        app.show(path[, params]);
  // path: string of the requested route's path
  // params: object to be passed to the route handler
      
    

+ example

          
            app('/home', (params) => (state) => (
    ['div', {}, [
        params.content || 'home',
    ]]
));

// renders the route and passes it the params
// will NOT change the browser's url
app.show('/home', {content: 'Hello World!'});
          
        

app.use()

Adds a blob to the app and notifies all modules.

      
        app.use('blobName', arg1, arg2, ...);
  // blob: the blob to be added
  // args: any object supported by the configured blob handler
      
    

+ example

          
            // use a blob with a target key
app.use('target', document.querySelector('body .wrapper'));

// blob keys can be arrays
app.use('watcher', [
    (state, actionType) => console.log(actionType),
    (state, actionType, params) => {
        if (actionType === 'MY_ACTION') {
            console.log(params);
        }
    },
]);

const plugin = {
    name: 'my-middleware-plugin',
    middleware: (next, state, actionType, params) => {
        if (state.items.length === 0) {
            params.empty = true;
        }
        next(state, actionType, params);
    },
};

// named plugins will only be added once
app.use(plugin);
app.use(plugin);
          
        

For more information about blobs, visit the dedicated page .