Skip to content

Instantly share code, notes, and snippets.

@runspired
Last active February 1, 2017 07:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save runspired/a4b56f7eefe9f8e04f7f0c83e4dfeaf0 to your computer and use it in GitHub Desktop.
Save runspired/a4b56f7eefe9f8e04f7f0c83e4dfeaf0 to your computer and use it in GitHub Desktop.
Complex Attrs
import Ember from 'ember';
export default Ember.Controller.extend({
appName: 'Ember Twiddle',
trueModel: Ember.computed(function() {
return this.get('store').peekRecord('my-model', '123');
}),
actions: {
changeValue() {
let model = this.get('trueModel');
let enumerable = model.get('myEnum');
model.set('myEnum', enumerable.value === 'A' ? 'B' : 'A');
}
},
init() {
this._super();
this.get('store').pushPayload({
data: {
type: 'my-model',
id: '123',
attributes: {
'my-enum': 'A'
}
}
});
}
});
import Model from "ember-data/model";
import attr from '../utils/complex-attr';
import { belongsTo, hasMany } from "ember-data/relationships";
export const ENUM_OPTIONS = ['A', 'B', 'C', 'D'];
export default Model.extend({
myEnum: attr('enum', {
options: ENUM_OPTIONS,
defaultValue: function() { return ENUM_OPTIONS[0]; }
})
});
<h1>Welcome to {{appName}}</h1>
<br>
<br>
{{outlet}}
<b>My Enum is:</b> {{trueModel.myEnum}} <br><br>
<b>Is it A?</b> {{if trueModel.myEnum.isA 'Yes' 'No'}} <br>
<b>Is it B?</b> {{if trueModel.myEnum.isB 'Yes' 'No'}} <br>
<b>Is the model dirty?</b> {{if trueModel.hasDirtyAttributes 'Yes' 'No'}} <br>
<button {{action "changeValue"}}>Change The Enum</button>
<br>
<br>
import Transform from 'ember-data/transform';
export default Transform.extend({
deserialize(v) { return v; },
serialize(v) { return v; }
});
{
"version": "0.11.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.10.2",
"ember-data": "2.11.0",
"ember-template-compiler": "2.10.2",
"ember-testing": "2.10.2"
},
"addons": {}
}
import Ember from 'ember';
import Enum from './enum';
export default function complexAttr(type, options) {
let meta = {
type: type,
isAttribute: true,
options: options
};
const enumerable = new Enum(options.options, options.defaultValue);
return Ember.computed({
get(key) {
enumerable.__meta.key = key;
enumerable.__meta._internalModel = this._internalModel;
return enumerable;
},
set(key, value) {
var internalModel = this._internalModel;
var oldValue = enumerable.value;
var originalValue;
if (value !== oldValue) {
internalModel._attributes[key] = value;
if (key in internalModel._inFlightAttributes) {
originalValue = internalModel._inFlightAttributes[key];
} else {
originalValue = internalModel._data[key].value;
}
this._internalModel.send('didSetProperty', {
name: key,
oldValue: oldValue,
originalValue: originalValue,
value: value
});
this.notifyPropertyChange(key);
}
return enumerable;
}
}).meta(meta);
}
function assert(msg, test) {
if (!test) {
console.error(msg);
debugger;
}
}
function capitalize(s) {
return s.substr(0, 1).toUpperCase() + s.substr(1);
}
export default class Enum {
constructor(options, defaultValueFn) {
this.__meta = {
_internalModel: null,
key: '',
options,
defaultValue: null,
defaultValueFn
};
}
setUnknownProperty(key, value) {
throw new Error('illegal attempt to set a property on an Enum');
}
unknownProperty(key) {
let options = this.__meta.options;
let option = key.toUpperCase().substr(2);
assert(
`You passed the invalid isOption flag '${key}' to the ENUM: [${options.join(', ')}]`,
options.contains(option)
);
return this.value === option;
}
get value() {
let meta = this.__meta;
let key = meta.key;
let internalModel = meta._internalModel;
return internalModel._attributes[key] ||
internalModel._inFlightAttributes[key] ||
internalModel._data[key] ||
meta.defaultValue ||
(meta.defaultValue = meta.defaultValueFn());
}
set value(option) {
assert(
`You passed an invalid option value '${option}' to the ENUM: [${options.join(', ')}]`,
this.__meta.options.contains(option)
);
this.__meta.currentState = option;
}
valueOf() {
return this.value;
}
toString() {
return this.value;
}
toJSON() {
let meta = this.__meta;
let value = this.value;
let shape = {
value
};
let opts = meta.options;
for (let i = 0, j = opts.length; i < j; i++) {
let key = opts[i];
shape[`is${capitalize(key)}`] = value === key;
}
return shape;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment