RiotControl
RiotControl copied to clipboard
Improve support to ES6 implementation
I'd like suggest an little improvement around RiotControl. I've created a simple application using ES6 syntax, and my store is simple ES6 class, that looks like:
import riot from 'riot';
class ContatoStore {
constructor() {
riot.observable(this);
this.state = [{id:'192', nome:'Abdoral Gusmao', email:'[email protected]'}];
this.on('contact_add', this.add);
this.on('contact_remove', this.remove);
this.on('contact_load', this.load);
}
load() {
this.trigger('contact_change', this.state);
}
add(contato) {
console.log('New Contact');
}
remove(id) {
console.log('Remove contact');
}
}
module.exports = ContatoStore;
There is nothing wrong with this code below, but RiotControl print out on browser's console Cannot read property 'apply' of undefined
. This error message is because el
is a function and it's not an object instance. I just did some adjustment on API, putting a validation that shows warning message. But my suggestion is to resolve this issue checking type and instantiating a object in case of function.
['on','one','off','trigger'].forEach(function(api){
RiotControl[api] = function() {
var args = [].slice.call(arguments);
this._stores.forEach(function(el) {
if (typeof el === 'object')
el[api].apply(null, args);
else
console.warn(el.name +' is not an object instance.')
});
};
});
+1
@keuller, I think using export default class ContatoStore
is better than module.exports = ContatoStore
. With this, the transpiler can change (at your command) the loader format.
Confused now. I'm testing with this todo-store.js file:
'use strict';
import riot from 'riot';
// Storage class
export default class TodoStore {
constructor(dispatcher) {
const LOCALSTORAGE_KEY = 'riot-item';
if (!this.TODO_INIT) {
this._setEvents();
}
this.dispatcher = dispatcher;
this.storage = window.localStorage;
let json = this.storage.getItem(this.LOCALSTORAGE_KEY);
riot.observable(this); // Riot provides our event emitter.
this.todos = (json && JSON.parse(json)) || [];
// Event handlers.
this.on(this.TODO_ADD, item => {
this.todos.push(item);
this._triggerChanged();
});
this.on(this.TODO_TOGGLE, item => {
item.done = !item.done;
this._triggerChanged();
});
this.on(this.TODO_CLEAR, () => {
this.todos = this.todos.filter(item => !item.done);
this._triggerChanged();
});
this.on(this.TODO_INIT, this._triggerChanged);
}
_setEvents() {
const act = ['ADD', 'TOGGLE', 'CLEAR', 'INIT', 'CHANGED'];
let props = {};
for (let v, i = 0; i < act.length; ++i) {
v = 'TODO_' + act[i];
props[v] = { value: v, enumerable: true };
}
Object.defineProperties(TodoStore.prototype, props);
}
_triggerChanged() {
// Brute force update all.
this.storage.setItem(this.LOCALSTORAGE_KEY, JSON.stringify(this.todos));
this.trigger(this.TODO_CHANGED);
}
}
in the main index.js
'use strict';
import riot from 'riot';
import TodoStore from './todo-store.js';
import dispatcher from './riotcontrol.js';
import './tags.js' // <-- precompiled tags
let todoStore = new TodoStore(dispatcher);
dispatcher.addStore(todoStore);
riot.mount('todo-app', { store: todoStore });
and I have no problems. RiotControl stores intances.
TBH I'm not taking advantage of ES6 yet. @duongphuhiep has also suggested #16
I will have to read more into this.