
Security News
GitHub Actions Pricing Whiplash: Self-Hosted Actions Billing Change Postponed
GitHub postponed a new billing model for self-hosted Actions after developer pushback, but moved forward with hosted runner price cuts on January 1.
ember-custom-actions
Advanced tools
Ember Custom Actions is a package for defining custom API actions, dedicated for Ember 2.16 (and higher) applications.
Before you will start with documentation check our demo app: Ember-Custom-Actions Website
ember install ember-custom-actions
To define custom action like: posts/1/publish you can use
modelAction(path, options) method with arguments:
path - url of the action scoped to our api (in our case it's publish)options - optional parameter which will overwrite the configuration optionsimport Model from 'ember-data/model';
import { modelAction } from 'ember-custom-actions';
export default Model.extend({
publish: modelAction('publish', { pushToStore: false }),
});
let user = this.get('currentUser');
let postToPublish = this.get('store').findRecord('post', 1);
let payload = { publisher: user };
postToPublish.publish(payload, /*{ custom options }*/).then((status) => {
alert(`Post has been: ${status}`)
}).catch((error) => {
console.log('Here are your serialized model errors', error.serializedErrors);
});
To a define custom action like: posts/favorites you can use
resourceAction(actionId/path, options) method with arguments:
path - url of the action scoped to our api (in our case it's favorites)options - optional parameter which will overwrite the configuration optionsimport Model from 'ember-data/model';
import { resourceAction } from 'ember-custom-actions';
export default Model.extend({
favorites: resourceAction('favorites', { method: 'GET' }),
});
let user = this.get('currentUser');
let emptyPost = this.get('store').createRecord('post');
let payload = { user };
emptyPost.favorites(payload, /*{ custom options }*/).then((favoritesPosts) => {
console.log(favoritesPosts);
}).finally(()=>{
emptyPost.deleteRecord();
});
To define customAction and customize it by using ember-data flow, adapters and serializer you can use customAction(actionId, options) method with arguments:
actionId - id of the action which can be handled later on in adpaters and serializersoptions - optional parameter which will overwrite the configuration optionsIf you want to customize your request in your adapter please, implement our adapter mixin:
import JSONAPIAdapter from 'ember-data/adapters/json-api';
import { AdapterMixin } from 'ember-custom-actions';
export default JSONAPIAdapter.extend(AdapterMixin);
Now you can customize following methods in the adpater:
You can define your custom path for every customAction by adding a conditional:
export default JSONAPIAdapter.extend(AdapterMixin, {
urlForCustomAction(modelName, id, snapshot, actionId, queryParams) {
if (actionId === 'myPublishAction') {
return 'https://my-custom-api.com/publish'
}
return this._super(...arguments);
}
});
If you would like to build custom modelAction you can do it by:
import { AdapterMixin } from 'ember-custom-actions';
export default JSONAPIAdapter.extend(AdapterMixin, {
urlForCustomAction(modelName, id, snapshot, actionId, queryParams) {
if (requestType === 'myPublishAction') {
return `${this._buildURL(modelName, id)}/publish`;
}
return this._super(...arguments);
}
});
You can define your custom method for every customAction by adding a conditional:
import { AdapterMixin } from 'ember-custom-actions';
export default JSONAPIAdapter.extend(AdapterMixin, {
methodForCustomAction(params) {
if (params.actionId === 'myPublishAction') {
return 'PUT';
}
return this._super(...arguments);
}
});
You can define your custom headers for every customAction by adding a conditional:
import { AdapterMixin } from 'ember-custom-actions';
export default JSONAPIAdapter.extend(AdapterMixin, {
headersForCustomAction(params) {
if (params.actionId === 'myPublishAction') {
return {
'Authorization-For-Custom-Action': 'mySuperToken123'
};
}
return this._super(...arguments);
}
});
You can define your custom data for every customAction by adding a conditional:
import { AdapterMixin } from 'ember-custom-actions';
export default JSONAPIAdapter.extend(AdapterMixin, {
dataForCustomAction(params) {
if (params.actionId === 'myPublishAction') {
return {
myParam: 'send it to the server'
};
}
return this._super(...arguments);
}
});
params contains following data: data, actionId, modelId, model
You can define your custom options in your config/environment.js file
module.exports = function(environment) {
var ENV = {
'emberCustomActions': {
method: 'POST',
data: {},
headers: {},
queryParams: {},
ajaxOptions: {},
adapterOptions: {},
pushToStore: false,
responseType: null,
normalizeOperation: ''
},
};
return ENV;
}
methodDefault method of the request (GET, PUT, POST, DELETE, etc..)
headersAn object {} of custom headers. Eg:
{
'my-custom-auth': 'mySuperToken123'
}
ajaxOptionsYour own ajax options. ** USE ONLY IF YOU KNOW WHAT YOU ARE DOING! ** Those properties will be overwritten by ECU.
pushToStoreIf you want to push the received data to the store, set this option to true
normalizeOperationYou can define how your outgoing data should be serialized
Exemplary data:
```js
{
firstParam: 'My Name',
colors: { rubyRed: 1, blueFish: 3 }
}
After using a dasherize transformer our request data will turn into:
{
first-param: 'My Name',
colors: { ruby-red: 1, blue-fish: 3 }
}
It's great for API with request data format restrictions
Available transformers:
adapterOptionsPass custom adapter options to handle them in urlForCustomAction in case of using customAction. Required usage of mixin: AdpaterMixin
responseTypeYou can easily observe the returned model by changing responseType to array or object according to what type of data
your server will return.
When array:
model.customAction({}, { responseType: 'array' }) // returns DS.PromiseArray
When object:
model.customAction({}, { responseType: 'object' }) // returns DS.PromiseObject
When null (default):
model.customAction({}, { responseType: null }) // returns Promise
null is useful if you don't care about the response or just want to use then on the promise without using binding or display it in the template.
queryParamsYou can pass a query params for a request by passing an {} with properties, eg: { include: 'owner' }
** Remember: Query params are not normalized! You have to pass it in the correct format. **
git clone https://github.com/Exelord/ember-custom-actions.gitcd ember-custom-actionsnpm installnpm run lint:hbsnpm run lint:jsnpm run lint:js -- --fixember test – Runs the test suite on the current Ember versionember test --server – Runs the test suite in "watch mode"ember try:each – Runs the test suite against multiple Ember versionsember serveFor more information on using ember-cli, visit https://ember-cli.com/.
Big thanks to Mike North and his Project for the initial concept.
Bug reports and pull requests are welcome on GitHub at https://github.com/exelord/ember-custom-actions. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct.
This version of the package is available as open source under the terms of the MIT License.
FAQs
Custom API actions for Ember 2 applications
We found that ember-custom-actions demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
GitHub postponed a new billing model for self-hosted Actions after developer pushback, but moved forward with hosted runner price cuts on January 1.

Research
Destructive malware is rising across open source registries, using delays and kill switches to wipe code, break builds, and disrupt CI/CD.

Security News
Socket CTO Ahmad Nassri shares practical AI coding techniques, tools, and team workflows, plus what still feels noisy and why shipping remains human-led.