Skip to content

Commit

Permalink
Merge pull request #31 from thoov/stateForCP
Browse files Browse the repository at this point in the history
New stateFor CP
  • Loading branch information
thoov committed Sep 4, 2015
2 parents 2e90798 + 4f0bc68 commit 24f5e9b
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 4 deletions.
80 changes: 80 additions & 0 deletions addon/state-for.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import Ember from 'ember';

var {
computed,
assert,
typeOf
} = Ember;

var states = {};

/*
* Create the states object for a given stateName.
*
* @param container {object} container to lookup the state factory on
* @param stateName {string} state name which is also the name of the factory
*/
function createStates(container, stateName) {
let stateContainerName = `state:${stateName}`;
let StateFactory = container.lookupFactory(stateContainerName);

if (!StateFactory) {
throw new TypeError(`Unknown StateFactory: \`${stateContainerName}\``);
}

states[stateName] = new Ember.MapWithDefault({
defaultValue: () => buildDefaultState.call(this, StateFactory)
});

return states[stateName];
}

/*
* When creating the state instance we use `initialState` method
* on the state class to build its initial state. If it not
* specified then {} is used as the default state.
*
* @param Factory {StateFactoryClass} state factory from the container
* @return {stateInstance} state instance object from the factory
*/
function buildDefaultState(Factory) {
let defaultState = {};

if (typeOf(Factory.initialState) === 'function') {
defaultState = Factory.initialState.call(this);
}

return Factory.create(defaultState);
}

/*
* Returns a computed property that returns state based off of a dynamic key.
*
* @param stateName {string} name of the state factory which is located in /states/<stateName>.js
* @param options {object}
* @param {string} options.key - required - the dynamic state key
* @param {object} options.container - optional - container reference
* @return {computed property}
*/
export default function stateFor(stateName, options) {
var { key, container } = options;

assert(`
Missing \`key\` property within the second argument. You passed: ${JSON.stringify(options)}
`, key);

return computed(key, function() {
assert(`
Could not find the container on \`this\` or passed in via:
stateFor('${stateName}', { key: ${key}, container: <pass container here> })
`, this.container || container);

if (states[stateName]) {
return states[stateName].get(this.get(key));
}

return createStates
.apply(this, [container || this.container, stateName])
.get(this.get(key));
});
}
6 changes: 2 additions & 4 deletions tests/dummy/app/components/edit-email.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import Ember from 'ember';
import stateFor from 'ember-state-services/state-for';

export default Ember.Component.extend({
tagName: 'form',
editEmailService: Ember.inject.service('edit-email'),
data: Ember.computed('email', function() {
return this.get('editEmailService').stateFor(this.get('email'));
}).readOnly(),
data: stateFor('edit-email', { key: 'email' }),

actions: {
save: function() {
Expand Down
6 changes: 6 additions & 0 deletions tests/dummy/app/states/edit-email.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
import BufferedProxy from 'ember-buffered-proxy/proxy';

BufferedProxy.reopenClass({
initialState() {
return { content: this.get('email') };
}
});

export default BufferedProxy.extend();

0 comments on commit 24f5e9b

Please sign in to comment.