Computed Property Macros for Ember
Ember. Versions between 0.9.8 and 1.x should work fine. (If you're running Ember 0.9.x and want the CP macros from Ember 1.0, the ember_09 branch has them.)
If you are using Ember CLI, you can install ember-cpm as
an addon with npm install ember-cpm --save-dev
and you will be able to import native ES modules from
within your app.
If not, you need to add ember-cpm.js
manually to your project.
You can find the latest versions of ember-cpm in the S3 bucket in two flavours: globals or AMD.
Alternatively, you can also build from source. See Contributing for more info about how to build from source.
If you use the global build, an EmberCPM
global should be available.
In Ember CLI:
// Import only one macros
import ifNull from "ember-cpm/macros/if-null";
// or alternatively import all the namespace
import EmberCPM from "ember-cpm";
In any other scenario, include ember-cpm.js
after ember but before your app, and a gobal will be available:
Person = Ember.Object.extend({
name: null,
handle: EmberCPM.Macros.ifNull('name', 'Anonymous'),
});
You have to install Ember CLI to build this library. If you don't have it, visit www.ember-cli.com/ for further guidance about how to install it.
After running npm install
to get all the dependencies you can:
- Run
ember serve
and go tolocalhost:4200/test
to run the tests in watch mode. You can also runember serve --docs
to see generate and expose documentation in/docs
. - Run
ember test
to run all tests once (requires phantomjs). - Run
ember build
to build from source. - Run
ember yuidoc
to generate all the documentation inside the/docs
folder
- Run
ember g macro <dasherized-macro-name>
. This will generate a few files./addon/macros/dasherized-macro-name.js
(the macro)./addon/tests/dummy/unit/macro/dasherized-macro-name-test.js
(a test)*- and modify
./addon/ember-cpm.js
// import the macro
import camelizedMacroName from './macros/dasherized-macro-name.js'
...
var Macros = {
...
// allows use via EmberCPM.Macros.camelizedMacroName
camelizedMacroName: camelizedMacroName,
...
};
ember d macro <dasherized-macro-name>
will do the reverse of these changes
among
-- returnstrue
if the original value is among the given literals (testing using===
)encodeURIComponent
-- callsencodeURIComponent
on the original valueencodeURI
-- callsencodeURI
on the original valuefirstPresent
-- returns the first property with a value, as determined byEmber.isBlank
fmt
-- pass the original values into a format-stringhtmlEscape
-- escapes the original value withHandlebars.Utils.escapeExpression
and wraps the result in aHandlebars.SafeString
(since it's now safe)ifNull
-- fall back on a default valuepromise
-- wraps the original value in an already-resolved promisesafeString
-- wraps the original value in aHandlebars.SafeString
join
-- joins the supplied values together with a provided sepatatorsumBy
-- sums a property from an array of objectsquotient
-- divides one numeric property or literal by anotherdifference
-- subtracts one numeric property or literal from anotherproduct
-- multiplies numeric properties and literals togethersum
-- sums numeric properties and literals togetherconditional
-- returns values based on a boolean property (good replacement for ternary operator)
conditional
, sum
, quotient
and product
have support for composable computed property macros. This allows developers to mix other macros together without defining a bunch of otherwise-useless intermediate properties
var product = EmberCPM.Macros.product,
sum = EmberCPM.Macros.sum,
mapBy = Ember.computed.mapBy,
sumArray = Ember.computed.sum;
RestaurantCheck = Ember.Object.extend({
items: [],
taxPercent: 0.05,
discount: 5.00,
itemPrices: mapBy('items', 'price'),
subTotal: sumArray('itemPrices'), // sums over array
grandTotal: sum(
product('taxPercent', 'subTotal'), // tax
'subTotal', // main bill
product('subTotal', 0.17), // tip your waiter
product(-1, 'discount') // discount
)
});
If you would prefer to use Ember.computed.{macro}
instead of
EmberCPM.Macros.{macro}
(for the sake of uniform access), simply call
EmberCPM.install()
before your application code.