diff --git a/addon/create-class-computed.js b/addon/create-class-computed.js index 9939037..e28c2c0 100644 --- a/addon/create-class-computed.js +++ b/addon/create-class-computed.js @@ -97,17 +97,26 @@ export default function(observerBools, macroGenerator) { } let mappedKeys = []; + let originalKeys = []; - function rewriteComputed(obj, key) { - let mappedWithResolvedOberverKeys = mappedKeys.map((macro, i) => { + function createComputed(keys, context, key) { + let resolvedOberverKeys = keys.map((macro, i) => { let shouldObserve = observerBools[i]; if (shouldObserve) { - macro = getValue({ context: this, macro, key }); + if (context) { + macro = getValue({ context, macro, key }); + } else { + macro = undefined; + } } return macro; }); - let cp = macroGenerator.apply(this, mappedWithResolvedOberverKeys); + return macroGenerator.apply(context, resolvedOberverKeys); + } + + function rewriteComputed(obj, key) { + let cp = createComputed(mappedKeys, this, key); defineProperty(this, 'computed', cp); } @@ -121,6 +130,7 @@ export default function(observerBools, macroGenerator) { let mappedKey = resolveMappedLocation(key, i); + originalKeys.push(key); mappedKeys.push(mappedKey); if (shouldObserve) { classProperties[`key${i}DidChange`] = observer(mappedKey, rewriteComputed); @@ -150,6 +160,11 @@ export default function(observerBools, macroGenerator) { return get(propertyInstance, 'computed'); }).readOnly(); + // workaround for watching array and object rewriting properties + // in class computed scope while composing macros + // ex `first(filterBy('arr', 'prop'))` + cp._classComputed = createComputed(originalKeys); + return cp; }; } diff --git a/addon/flatten-keys.js b/addon/flatten-keys.js index c3c72a0..d3081ba 100644 --- a/addon/flatten-keys.js +++ b/addon/flatten-keys.js @@ -8,6 +8,14 @@ function flattenKey(key, flattenedKeys) { return; } + // workaround for watching array and object rewriting properties + // in class computed scope while composing macros + // ex `first(filterBy('arr', 'prop'))` + let classComputed = key._classComputed; + if (classComputed) { + dependentKeys = classComputed._dependentKeys; + } + return _flattenKeys(dependentKeys, flattenedKeys); } diff --git a/tests/acceptance/application-test.js b/tests/acceptance/application-test.js index 51d4bd7..2bb60a7 100644 --- a/tests/acceptance/application-test.js +++ b/tests/acceptance/application-test.js @@ -10,9 +10,23 @@ test('double render failing test', function(assert) { assert.equal(find('.computed').text(), 'test val 1'); }); - click('button'); + click('.button'); andThen(function() { assert.equal(find('.computed').text(), 'test val 2'); }); }); + +test('class computed array macro inside a normal array macro, handles pushes', function(assert) { + visit('/'); + + andThen(function() { + assert.equal(find('.computed2').text(), '1'); + }); + + click('.button2'); + + andThen(function() { + assert.equal(find('.computed2').text(), '3'); + }); +}); diff --git a/tests/dummy/app/controllers/application.js b/tests/dummy/app/controllers/application.js index 90c106d..28e2678 100644 --- a/tests/dummy/app/controllers/application.js +++ b/tests/dummy/app/controllers/application.js @@ -1,22 +1,31 @@ import Controller from '@ember/controller'; -import EmberObject, { set } from '@ember/object'; +import EmberObject, { get, set } from '@ember/object'; import { A as emberA } from '@ember/array'; import { readOnly } from '@ember/object/computed'; import createClassComputed from 'ember-macro-helpers/create-class-computed'; import computed from 'ember-macro-helpers/computed'; +import raw from 'ember-macro-helpers/raw'; +import normalizeArrayKey from 'ember-macro-helpers/normalize-array-key'; const getBy = createClassComputed( [false, true], (obj, key) => readOnly(`${obj}.${key}`) ); +const filterBy = createClassComputed( + [false, true], + (arr, key, val) => computed(normalizeArrayKey(arr, [key]), val, (arr, val) => arr.filterBy(key, val)) +); + export default Controller.extend({ array: emberA([ EmberObject.create({ - testProp: 'test val 1' + testProp: 'test val 1', + testProp2: 1 }), EmberObject.create({ - testProp: 'test val 2' + testProp: 'test val 2', + testProp2: 2 }) ]), index: 0, @@ -27,9 +36,20 @@ export default Controller.extend({ 'testProp' ), + computed2: computed( + filterBy('array', 'testProp', raw('test val 1')), + array => get(array[array.length - 1], 'testProp2') + ), + actions: { update() { set(this, 'index', 1); + }, + update2() { + get(this, 'array').pushObject(EmberObject.create({ + testProp: 'test val 1', + testProp2: 3 + })); } } }); diff --git a/tests/dummy/app/templates/application.hbs b/tests/dummy/app/templates/application.hbs index c7af736..0f034dc 100644 --- a/tests/dummy/app/templates/application.hbs +++ b/tests/dummy/app/templates/application.hbs @@ -1,3 +1,5 @@