Skip to content

Commit

Permalink
Add method bindListeners, inverse of bindActions
Browse files Browse the repository at this point in the history
  • Loading branch information
goatslacker committed Feb 24, 2015
1 parent 2a588c0 commit 3997f79
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 26 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,7 @@ Thus brings us to our final store point. Stores have the following available met
* `on :: lifecycleMethod, handler -> undefined`
* `bindAction :: ActionsMethod, StoreMethod -> undefined`
* `bindActions :: Actions -> undefined`
* `bindListeners :: Object -> undefined`
* `waitFor :: DispatcherToken | [DispatcherTokens] -> undefined`

`waitFor` is mostly an alias to Flux's Dispatcher waitFor. Here's an excerpt from the flux docs on what waitFor is designed for:
Expand Down
46 changes: 33 additions & 13 deletions dist/alt-with-runtime.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ var getInternalMethods = function (obj, excluded) {

var AltStore = (function () {
function AltStore(dispatcher, state) {
var _this5 = this;
var _this6 = this;
babelHelpers.classCallCheck(this, AltStore);

this[EE] = new EventEmitter();
Expand All @@ -60,7 +60,7 @@ var AltStore = (function () {
this.dispatchToken = dispatcher.register(function (payload) {
if (state[LISTENERS][payload.action]) {
var result = state[LISTENERS][payload.action](payload.data);
result !== false && _this5.emitChange();
result !== false && _this6.emitChange();
}
});

Expand Down Expand Up @@ -153,7 +153,7 @@ var StoreMixin = {
},

bindActions: function bindActions(actions) {
var _this5 = this;
var _this6 = this;
Object.keys(actions).forEach(function (action) {
var symbol = actions[action];
var matchFirstCharacter = /./;
Expand All @@ -162,19 +162,39 @@ var StoreMixin = {
});
var handler = null;

if (_this5[action] && _this5[assumedEventHandler]) {
if (_this6[action] && _this6[assumedEventHandler]) {
// If you have both action and onAction
throw new ReferenceError("You have multiple action handlers bound to an action: " + ("" + action + " and " + assumedEventHandler));
} else if (_this5[action]) {
} else if (_this6[action]) {
// action
handler = _this5[action];
} else if (_this5[assumedEventHandler]) {
handler = _this6[action];
} else if (_this6[assumedEventHandler]) {
// onAction
handler = _this5[assumedEventHandler];
handler = _this6[assumedEventHandler];
}

if (handler) {
_this5.bindAction(symbol, handler);
_this6.bindAction(symbol, handler);
}
});
},

bindListeners: function bindListeners(obj) {
var _this6 = this;
Object.keys(obj).forEach(function (methodName) {
var symbol = obj[methodName];
var listener = _this6[methodName];

if (!listener) {
throw new ReferenceError("" + methodName + " defined but does not exist in " + _this6._storeName);
}

if (Array.isArray(symbol)) {
symbol.forEach(function (action) {
return _this6.bindAction(action, listener);
});
} else {
_this6.bindAction(symbol, listener);
}
});
},
Expand Down Expand Up @@ -246,7 +266,7 @@ var Alt = (function () {
},
createStore: {
value: function createStore(StoreModel, iden) {
var _this5 = this;
var _this6 = this;
var key = iden || StoreModel.displayName || StoreModel.name;
// Creating a class here so we don't overload the provided store's
// prototype with the mixin behaviour and I'm extending from StoreModel
Expand All @@ -270,7 +290,7 @@ var Alt = (function () {
alt: this,
dispatcher: this.dispatcher,
getInstance: function () {
return _this5.stores[key];
return _this6.stores[key];
}
});

Expand All @@ -291,7 +311,7 @@ var Alt = (function () {
},
createActions: {
value: function createActions(ActionsClass) {
var _this5 = this;
var _this6 = this;
var exportObj = arguments[1] === undefined ? {} : arguments[1];
var actions = assign({}, getInternalMethods(ActionsClass.prototype, builtInProto));
var key = ActionsClass.displayName || ActionsClass.name;
Expand Down Expand Up @@ -338,7 +358,7 @@ var Alt = (function () {
var actionName = Symbol("" + key + "#" + action);

// Wrap the action so we can provide a dispatch method
var newAction = new ActionCreator(_this5, actionName, actions[action], obj);
var newAction = new ActionCreator(_this6, actionName, actions[action], obj);

// Set all the properties on action
obj[action] = newAction[ACTION_HANDLER];
Expand Down
46 changes: 33 additions & 13 deletions dist/alt.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ var getInternalMethods = function (obj, excluded) {

var AltStore = (function () {
function AltStore(dispatcher, state) {
var _this5 = this;
var _this6 = this;
_classCallCheck(this, AltStore);

this[EE] = new EventEmitter();
Expand All @@ -70,7 +70,7 @@ var AltStore = (function () {
this.dispatchToken = dispatcher.register(function (payload) {
if (state[LISTENERS][payload.action]) {
var result = state[LISTENERS][payload.action](payload.data);
result !== false && _this5.emitChange();
result !== false && _this6.emitChange();
}
});

Expand Down Expand Up @@ -163,7 +163,7 @@ var StoreMixin = {
},

bindActions: function bindActions(actions) {
var _this5 = this;
var _this6 = this;
Object.keys(actions).forEach(function (action) {
var symbol = actions[action];
var matchFirstCharacter = /./;
Expand All @@ -172,19 +172,39 @@ var StoreMixin = {
});
var handler = null;

if (_this5[action] && _this5[assumedEventHandler]) {
if (_this6[action] && _this6[assumedEventHandler]) {
// If you have both action and onAction
throw new ReferenceError("You have multiple action handlers bound to an action: " + ("" + action + " and " + assumedEventHandler));
} else if (_this5[action]) {
} else if (_this6[action]) {
// action
handler = _this5[action];
} else if (_this5[assumedEventHandler]) {
handler = _this6[action];
} else if (_this6[assumedEventHandler]) {
// onAction
handler = _this5[assumedEventHandler];
handler = _this6[assumedEventHandler];
}

if (handler) {
_this5.bindAction(symbol, handler);
_this6.bindAction(symbol, handler);
}
});
},

bindListeners: function bindListeners(obj) {
var _this6 = this;
Object.keys(obj).forEach(function (methodName) {
var symbol = obj[methodName];
var listener = _this6[methodName];

if (!listener) {
throw new ReferenceError("" + methodName + " defined but does not exist in " + _this6._storeName);
}

if (Array.isArray(symbol)) {
symbol.forEach(function (action) {
return _this6.bindAction(action, listener);
});
} else {
_this6.bindAction(symbol, listener);
}
});
},
Expand Down Expand Up @@ -256,7 +276,7 @@ var Alt = (function () {
},
createStore: {
value: function createStore(StoreModel, iden) {
var _this5 = this;
var _this6 = this;
var key = iden || StoreModel.displayName || StoreModel.name;
// Creating a class here so we don't overload the provided store's
// prototype with the mixin behaviour and I'm extending from StoreModel
Expand All @@ -280,7 +300,7 @@ var Alt = (function () {
alt: this,
dispatcher: this.dispatcher,
getInstance: function () {
return _this5.stores[key];
return _this6.stores[key];
}
});

Expand All @@ -301,7 +321,7 @@ var Alt = (function () {
},
createActions: {
value: function createActions(ActionsClass) {
var _this5 = this;
var _this6 = this;
var exportObj = arguments[1] === undefined ? {} : arguments[1];
var actions = assign({}, getInternalMethods(ActionsClass.prototype, builtInProto));
var key = ActionsClass.displayName || ActionsClass.name;
Expand Down Expand Up @@ -348,7 +368,7 @@ var Alt = (function () {
var actionName = Symbol("" + key + "#" + action);

// Wrap the action so we can provide a dispatch method
var newAction = new ActionCreator(_this5, actionName, actions[action], obj);
var newAction = new ActionCreator(_this6, actionName, actions[action], obj);

// Set all the properties on action
obj[action] = newAction[ACTION_HANDLER];
Expand Down
19 changes: 19 additions & 0 deletions src/alt.js
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,25 @@ let StoreMixin = {
})
},

bindListeners(obj) {
Object.keys(obj).forEach((methodName) => {
let symbol = obj[methodName]
let listener = this[methodName]

if (!listener) {
throw new ReferenceError(
`${methodName} defined but does not exist in ${this._storeName}`
)
}

if (Array.isArray(symbol)) {
symbol.forEach((action) => this.bindAction(action, listener))
} else {
this.bindAction(symbol, listener)
}
})
},

waitFor(tokens) {
if (!tokens) {
throw new ReferenceError('Dispatch tokens not provided')
Expand Down
46 changes: 46 additions & 0 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,12 @@ class LifeCycleStore {
this.rollback = false
this.snapshotted = false

this.bindListeners({
test: myActions.updateName,
test2: [myActions.updateName, myActions.updateTwo],
test3: myActions.updateName
})

this.on('init', () => {
this.init = true
})
Expand All @@ -194,6 +200,10 @@ class LifeCycleStore {
this.rollback = true
})
}

test() { }
test2() { }
test3() { }
}

let lifecycleStore = alt.createStore(LifeCycleStore)
Expand Down Expand Up @@ -1092,6 +1102,42 @@ let tests = {
assert.equal(e instanceof ReferenceError, true, 'must pick one')
}
},

'binding a listener that does not exist'() {
class BadListenerStore {
constructor() {
this.bindListeners({
methodThatDoesNotExist: myActions.updateName
})
}
}

try {
alt.createStore(BadListenerStore)
assert.equal(true, false, 'I was able to bind an unknown method')
} catch (e) {
assert.equal(e instanceof ReferenceError, true, 'cannot bind methods that dont exist')
}
},

'binding listeners to action that does not exist'() {
class BadListenerStore {
constructor() {
this.bindListeners({
foo: myActions.trolololololol
})
}

foo() { }
}

try {
alt.createStore(BadListenerStore)
assert.equal(true, false, 'I was able to bind an unknown method')
} catch (e) {
assert.equal(e instanceof ReferenceError, true, 'invalid action reference passed in')
}
},
}

export default tests

0 comments on commit 3997f79

Please sign in to comment.