Closed GavinJoyce closed 8 years ago
@cibernox I'd be happy to build this if you'd like to include it in ember-cpm. If not, I'll create an addon
I'm concerned (generally) that using the same syntax as template strings would lead to confusion. As a general user, I often use template strings interchangeably and in the example you gave if you had used back ticks instead of single quotes to surround the string it would have been evaluated at module parse time and not at runtime.
I think a better pattern would be:
import { computedString } from "ember-cpm";
// ... Snip ...
catchPhrase: computedString'Hi, my name is ${name} and I will teach you ${course}'
That template string function would expand to a CP (as you mentioned)...
PS: On iOS I can't type back ticks, please replace single quotes with backticks in my example above.
@rwjblue nice suggestion, :+1: on the computedString
template string function.
@rwjblue I'm just reading up on tagged templates, it seems that:
fn`Hello ${you}! You're looking ${adjective} today!`
desugars into:
fn(["Hello ", "! You're looking ", " today!"], you, adjective);
meaning that we'll get runtime and jshint errors due to you
and adjective
not being defined. We also don't get access to the variable names, which we would need to build the CP dependant keys
Here's an example
Perhaps I'm missing something?
Look at ember-cli-htmlbars-inline-precompiler. It replaces the imported template string at build time. This technique should allow us to rewrite so that no special stuff is needed at runtime.
I also think that the template precompiler is a nice trick that happens and build time. If it's doable I'd also prefer that.
Note to self, something like:
before:
import { computedString } from "ember-cpm";
var teacher = Ember.Object.extend({
name: 'Miguel',
course: {
name: 'Javacript'
},
catchPhrase: computedString`Hi, my name is ${name} and I will teach you ${course.name}`
}).create();
after:
import { computedString } from "ember-cpm";
var teacher = Ember.Object.extend({
name: 'Miguel',
course: {
name: 'Javacript'
},
catchPhrase: computedString('name', 'course.name', function() {
var values = [
this.get('name'),
this.get('course.name')
];
return `Hi, my name is ${values[0]} and I will teach you ${values[1]}`;
}
}).create();
or, without template strings:
import { computedString } from "ember-cpm";
var teacher = Ember.Object.extend({
name: 'Miguel',
course: {
name: 'Javacript'
},
catchPhrase: computedString('name', 'course.name', function() {
let templates = ['Hi, my name is ', this.get('name'), " and I will teach you ", this.get('course.name')];
return templates.join();
}
}).create();
I create a simple proof of concept addon, there are two notable files:
This works fine:
import Em from 'ember';
export default Em.Controller.extend({
name: 'Gavin',
greeting: computedString`hello ${name}` //this will be rewritten by the `BabelPluginSpike` in `/index.js`
});
One thing I'm not sure how to solve is the jshint warnings for the template string arguments though:
This seems to run before the babel plugin has had a chance to make its transform so don't think I can transform my way out of this (the transformed source should pass jshint without warning).
Any suggestions?
I built support for the string version of this in Intercom today, tests below. If we can't find a solution to the jshint issue, perhaps you would like to include this in ember-cpm
? If not, I'll open source a focused addon
import Em from 'ember';
import Computed from 'embercom-computed-properties/computed';
import { module, test } from 'qunit';
module("Computed.templateString");
var Person = Em.Object.extend({
name: 'Alex',
age: 2,
config: {
path: '/home'
},
simple: Computed.templateString('this has no dependant keys, ok?'),
greeting: Computed.templateString('Hello ${name}, you are ${age} years old'),
nested: Computed.templateString('the path is ${config.path}, ok?'),
multi: Computed.templateString('hi ${name}, bye ${name}')
});
test('A template with no properties', function(assert) {
var person = Person.create();
assert.equal(person.get('simple'), 'this has no dependant keys, ok?');
});
test('A template with two properties', function(assert) {
var person = Person.create({ name: 'Alex', age: 2 });
assert.equal(person.get('greeting'), 'Hello Alex, you are 2 years old');
person.setProperties({ name: 'Ben', age: 1 });
assert.equal(person.get('greeting'), 'Hello Ben, you are 1 years old');
});
test('A template with a nested property', function(assert) {
var person = Person.create();
assert.equal(person.get('nested'), 'the path is /home, ok?');
person.set('config.path', '/garden');
assert.equal(person.get('nested'), 'the path is /garden, ok?');
});
test('A template with a key used multiple times', function(assert) {
var person = Person.create({ name: 'Ben' });
assert.equal(person.get('multi'), 'hi Ben, bye Ben');
person.set('name', 'Sarah');
assert.equal(person.get('multi'), 'hi Sarah, bye Sarah');
});
I'll create a separate addon for this
Thanks for the PR anyway. Will use the template strings?
Will use the template strings?
I don't think it's possible: https://github.com/cibernox/ember-cpm/issues/135#issuecomment-184807607
It's a shame that jshint prevents that approach.
Agreed. Sorry for the extra work implementing only to find out it fails linting :(
I just released https://github.com/intercom/ember-computed-template-string
As
Ember.String.fmt
is depreciated, it would be nice to define a CP macro with a similar syntax to ES6 Template Strings:We'd parse the string to identify the computed property keys and build a function which would be optimized for generating the appropriate output