Skip to content

Instantly share code, notes, and snippets.

@knownasilya
Last active January 13, 2018 23:15
Show Gist options
  • Save knownasilya/228b63aeb8f8e6464960ba019d7ce720 to your computer and use it in GitHub Desktop.
Save knownasilya/228b63aeb8f8e6464960ba019d7ce720 to your computer and use it in GitHub Desktop.
action service
import Ember from 'ember';
const { inject: { service } } = Ember;
export default Ember.Controller.extend({
userState: service('user-state'),
appName: 'Ember Twiddle',
actions: {
duplicate() {
let cloneUser = this.get('userState.state.cloneUser') || 1;
this.set('userState.state.cloneUser', cloneUser + 1);
},
setName() {
this.set('userState.state.test.name', 'bye');
}
}
});
import Ember from 'ember';
const { getOwner } = Ember;
export default Ember.Helper.extend({
compute([serviceName, actionName, ...args]) {
let service = getOwner(this).lookup(`service:${serviceName}`);
return function() {
return service.actions[actionName].apply(service, args);
};
}
});
import Ember from 'ember';
export default Ember.Service.extend({
init() {
this._super(...arguments);
this.setState(this.initState() || {});
},
initState() {
return {};
},
setState(newState) {
this.set('state', deepFreeze({ ...this.state, ...newState }));
},
pluckState(...keys) {
let openState = Object.assign({}, this.state);
let newState = keys.reduce((obj, key) => {
obj[key] = openState[key];
return obj;
}, {});
return newState;
}
});
// copied from https://github.com/jsdf/deep-freeze
function deepFreeze (o) {
Object.freeze(o);
var oIsFunction = typeof o === "function";
var hasOwnProp = Object.prototype.hasOwnProperty;
Object.getOwnPropertyNames(o).forEach(function (prop) {
if (hasOwnProp.call(o, prop)
&& (oIsFunction ? prop !== 'caller' && prop !== 'callee' && prop !== 'arguments' : true )
&& o[prop] !== null
&& (typeof o[prop] === "object" || typeof o[prop] === "function")
&& !Object.isFrozen(o[prop])) {
deepFreeze(o[prop]);
}
});
return o;
}
import Ember from 'ember';
import ActionService from './action-service';
export default ActionService.extend({
initState() {
return {
test: {
name: 'hi'
}
};
},
actions: {
duplicate() {
let user = this.state.cloneUser || 1;
let { cloneUser } = this.pluckState('cloneUser');
cloneUser = cloneUser ? cloneUser + 1 : 1;
this.setState({ cloneUser });
},
setName() {
this.setState({
test: {
name: 'good bye'
}
});
}
}
});
<h1>Action Services</h1>
<p>
Action services let you share actions and state across multiple components and
controller/template combos in a safe way.
<br><br>
An action service defines immutable state, which can only be modified by calling `setState`
on that service. The developer then creates actions on that service, and modifies the state
using `setState`. Note that async actions work using `async/await`.
<br><br>
The `\{{service-action}}` helper allows to call actions on a service directly.
`onclick=\{{service-action 'user-state' 'duplicate'}}`
</p>
<br>
<br>
<button type='button' onclick={{action 'duplicate' target=userState}}>
Duplicate With Action Service
</button>
<button type='button' onclick={{service-action 'user-state' 'duplicate'}}>
Duplicate With Action Service helper
</button>
<button type='button' onclick={{action 'duplicate'}}>
Duplicate Manually (throw)
</button>
<button type='button' onclick={{action 'setName' target=userState}}>
Test Nested
</button>
<button type='button' onclick={{action 'setName'}}>
Test Manually Nested (throw)
</button>
<hr>
userId: {{userState.state.cloneUser}}<br>
testName: {{userState.state.test.name}}
{
"version": "0.13.0",
"EmberENV": {
"FEATURES": {}
},
"options": {
"use_pods": false,
"enable-testing": false
},
"dependencies": {
"jquery": "https://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.3/jquery.js",
"ember": "2.16.2",
"ember-template-compiler": "2.16.2",
"ember-testing": "2.16.2"
},
"addons": {
"ember-data": "2.16.3"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment