Skip to content

Commit

Permalink
Initial implementation of emberjs/rfcs#415
Browse files Browse the repository at this point in the history
This is the initial implementation of
[emberjs/rfcs#415](https://emberjs.github.io/rfcs/0415-render-element-modifiers.html).

It currently depends on
[ember-modifier-manager-polyfill](https://github.com/rwjblue/ember-modifier-manager-polyfill)
in order to support Ember versions prior to 3.8 (should work back to at
least 2.12).
  • Loading branch information
rwjblue committed Jan 28, 2019
1 parent 082cfc5 commit f5ae31a
Show file tree
Hide file tree
Showing 11 changed files with 189 additions and 0 deletions.
Empty file removed addon/.gitkeep
Empty file.
17 changes: 17 additions & 0 deletions addon/modifiers/did-insert.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import Ember from 'ember';

export default Ember._setModifierManager(
() => ({
createModifier() {},

installModifier(_state, element, args) {
let [fn, ...positional] = args.positional;

fn(element, positional, args.named);
},

updateModifier() {},
destroyModifier() {},
}),
class DidInsertModifier {}
);
22 changes: 22 additions & 0 deletions addon/modifiers/did-update.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import Ember from 'ember';

export default Ember._setModifierManager(
() => ({
createModifier() {
return { element: null };
},
installModifier(state, element) {
// save element into state bucket
state.element = element;
},

updateModifier({ element }, args) {
let [fn, ...positional] = args.positional;

fn(element, positional, args.named);
},

destroyModifier() {},
}),
class DidUpdateModifier {}
);
22 changes: 22 additions & 0 deletions addon/modifiers/will-destroy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import Ember from 'ember';

export default Ember._setModifierManager(
() => ({
createModifier() {
return { element: null };
},

installModifier(state, element) {
state.element = element;
},

updateModifier() {},

destroyModifier({ element }, args) {
let [fn, ...positional] = args.positional;

fn(element, positional, args.named);
},
}),
class WillDestroyModifier {}
);
Empty file removed app/.gitkeep
Empty file.
1 change: 1 addition & 0 deletions app/modifiers/did-insert.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from '@ember/render-modifiers/modifiers/did-insert';
1 change: 1 addition & 0 deletions app/modifiers/did-update.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from '@ember/render-modifiers/modifiers/did-update';
1 change: 1 addition & 0 deletions app/modifiers/will-destroy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from '@ember/render-modifiers/modifiers/will-destroy';
52 changes: 52 additions & 0 deletions tests/integration/modifiers/did-insert-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { render } from '@ember/test-helpers';
import hbs from 'htmlbars-inline-precompile';

module('Integration | Modifier | did-insert', function(hooks) {
setupRenderingTest(hooks);

test('it basically works', async function(assert) {
assert.expect(2);

this.someMethod = element => {
assert.equal(element.tagName, 'DIV', 'correct element tagName');
assert.dom(element).hasAttribute('data-foo', 'some-thing');
};
await render(hbs`<div data-foo="some-thing" {{did-insert this.someMethod}}></div>`);
});

test('it can accept arguments', async function(assert) {
assert.expect(4);

this.someMethod = (element, positional, named) => {
assert.equal(element.tagName, 'DIV', 'correct element tagName');
assert.dom(element).hasAttribute('data-foo', 'some-thing');

assert.deepEqual(named, { some: 'hash-value' }, 'named args match');
assert.deepEqual(positional, ['some-positional-value'], 'positional args match');
};

await render(
hbs`<div data-foo="some-thing" {{did-insert this.someMethod "some-positional-value" some="hash-value"}}></div>`
);
});

test('it is not invoked again when arguments change', async function(assert) {
assert.expect(4);

this.someMethod = (element, positional, named) => {
assert.equal(element.tagName, 'DIV', 'correct element tagName');
assert.dom(element).hasAttribute('data-foo', 'some-thing');

assert.deepEqual(named, {}, 'named args match');
assert.deepEqual(positional, ['initial'], 'positional args match');
};

this.set('firstArg', 'initial');
await render(
hbs`<div data-foo="some-thing" {{did-insert this.someMethod this.firstArg}}></div>`
);
this.set('firstArg', 'updated');
});
});
27 changes: 27 additions & 0 deletions tests/integration/modifiers/did-update-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { render } from '@ember/test-helpers';
import hbs from 'htmlbars-inline-precompile';

module('Integration | Modifier | did-update', function(hooks) {
setupRenderingTest(hooks);

test('it basically works', async function(assert) {
assert.expect(4);

this.someMethod = (element, positional, named) => {
assert.equal(element.tagName, 'DIV', 'correct element tagName');
assert.dom(element).hasAttribute('data-foo', 'some-thing');

assert.deepEqual(named, {}, 'named args match');
assert.deepEqual(positional, ['update'], 'positional args match');
};

this.set('boundValue', 'initial');
await render(
hbs`<div data-foo="some-thing" {{did-update this.someMethod this.boundValue}}></div>`
);

this.set('boundValue', 'update');
});
});
46 changes: 46 additions & 0 deletions tests/integration/modifiers/will-destroy-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { render } from '@ember/test-helpers';
import hbs from 'htmlbars-inline-precompile';

module('Integration | Modifier | will-destroy', function(hooks) {
setupRenderingTest(hooks);

test('it basically works', async function(assert) {
assert.expect(2);

this.someMethod = element => {
assert.equal(element.tagName, 'DIV', 'correct element tagName');
assert.dom(element).hasAttribute('data-foo', 'some-thing');
};
this.set('show', true);

await render(
hbs`{{#if show}}<div data-foo="some-thing" {{will-destroy this.someMethod}}></div>{{/if}}`
);

// trigger destroy
this.set('show', false);
});

test('it can accept arguments', async function(assert) {
assert.expect(4);

this.someMethod = (element, positional, named) => {
assert.equal(element.tagName, 'DIV', 'correct element tagName');
assert.dom(element).hasAttribute('data-foo', 'some-thing');

assert.deepEqual(named, { some: 'hash-value' }, 'named args match');
assert.deepEqual(positional, ['some-positional-value'], 'positional args match');
};

this.set('show', true);

await render(
hbs`{{#if show}}<div data-foo="some-thing" {{will-destroy this.someMethod "some-positional-value" some="hash-value"}}></div>{{/if}}`
);

// trigger destroy
this.set('show', false);
});
});

0 comments on commit f5ae31a

Please sign in to comment.