This package has been deprecated

Author message:

Deprecated in favor of the official `ember-modifier` addon: https://github.com/ember-modifier/ember-modifier#api-differences

ember-oo-modifiers

0.5.2 • Public • Published

ember-oo-modifiers

This addon provides a useLayoutEffect-like API for adding modifiers to elements in Ember.

For more information on modifiers, please check out @pzuraq's wonderful blog post.

Compatibility

This is currently compatible with:

  • Ember.js v3.8 or above
  • Ember CLI v2.13 or above

In the future, it will be supported with:

  • Ember.js v2.18 or above
  • Ember CLI v2.13 or above

(Support for v2.18 is blocked by: https://github.com/rwjblue/ember-modifier-manager-polyfill/issues/6)

Installation

ember install ember-oo-modifiers

Usage

This addon does not provide any modifiers out of the box; instead (like Helpers), this library allows you to write your own.

Much of this addon was inspired (and some copied) from ember-functional-modifiers by @spencer516

The difference between the two is that ember-functional-modifiers exposes a functional style API while this addon exposes an Object Oriented API.

Example without Cleanup

For example, if you wanted to implement your own scrollTop modifier (similar to this), you may do something like this:

Ember Object

// app/modifiers/scroll-top.js
import { Modifier } from 'ember-oo-modifiers';
 
const ScrollTopModifier = Modifier.extend({
  didReceiveArguments([scrollPosition]) {
    this.element.scrollTop = scrollPosition;
  }
});
 
export default ScrollTopModifier;

Then, use it in your template:

<div class="scroll-container" {{scroll-top @scrollPosition}}>
  {{yield}}
</div>

Native Class

// app/modifiers/scroll-top.js
import Modifier from 'ember-oo-modifiers';
 
export default class ScrollTopModifier extends Modifier {
  didReceiveArguments([scrollPosition]) {
    this.element.scrollTop = scrollPosition;
  }
}

Then, use it in your template:

<div class="scroll-container" {{scroll-top @scrollPosition}}>
  {{yield}}
</div>

modifier function

The native class example can be implemented using modifier function, which calls passed function argument on didReceiveArguments with these arguments

  • element on which is the modifier installed,
  • array of positional arguments passed on the modifier,
  • object of named arguments passed on the modifier.
// app/modifiers/scroll-top.js
import { modifier } from 'ember-oo-modifiers';
 
export default modifier(function scrollTop(element, [scrollPosition]) {
  element.scrollTop = scrollPosition;
})

Example with Cleanup

If the functionality you add in the modifier needs to be torn down when the element is removed, you can return a function for the teardown method.

For example, if you wanted to have your elements dance randomly on the page using setInterval, but you wanted to make sure that was canceled when the element was removed, you could do:

Ember Object

// app/modifiers/move-randomly.js
import { Modifier } from 'ember-oo-modifiers';
 
const { random, round } = Math;
const INTERVAL_DELAY = 1000;
 
const MoveRandomlyModifier = Modifier.extend({
  updateTransform() {
    let top = round(random() * 500);
    let left = round(random() * 500);
    this.element.style.transform = `translate(${left}px, ${top}px)`;
  },
 
  didInsertElement() {
    this.timer = setInterval(() => this.updateTransform(), INTERVAL_DELAY);
  },
 
  willDestroyElement() {
    clearInterval(this.timer);
    this.timer = null;
  }
});
 
export default MoveRandomlyModifier;
<div style="position: fixed;" {{move-randomly}}>
  Try to catch me!
</div>

Native Class

// app/modifiers/move-randomly.js
import Modifier from 'ember-oo-modifiers';
 
const { random, round } = Math;
const INTERVAL_DELAY = 1000;
 
export default class MoveRandomlyModifier extends Modifier {
  updateTransform() {
    let top = round(random() * 500);
    let left = round(random() * 500);
    this.element.style.transform = `translate(${left}px, ${top}px)`;
  }
 
  didInsertElement() {
    this.timer = setInterval(() => this.updateTransform(), INTERVAL_DELAY);
  }
 
  willDestroyElement() {
    clearInterval(this.timer);
    this.timer = null;
  }
}
<div style="position: fixed;" {{move-randomly}}>
  Try to catch me!
</div>

Example with Service Injection

You may also want to inject a service into your modifier.

You can do that by supplying an injection object before the the modifier function. For example, suppose you wanted to track click events with ember-metrics:

Ember Object

// app/modifiers/track-click.js
import { inject as service } from '@ember/service';
import { Modifier } from 'ember-oo-modifiers';
 
const TrackClickModifier = Modifier.extend({
  metrics: service(),
 
  didInsertElement([eventName], options) {
    this.trackingCallback = () => this.metrics.trackEvent(eventName, options);
    this.element.addEventListener('click', this.trackingCallback, true);
  },
 
  willDestroyElement() {
    this.element.removeEventListener('click', this.trackingCallback, true);
    this.trackingCallback = null;
  }
});
 
export default TrackClickModifier;

Then, you could use this in your template:

<button {{track "Clicked the THING!"}}>
  Click Me!
</button>

Native Class

// app/modifiers/track-click.js
import { inject as service } from '@ember-decorators/service';
import Modifier from 'ember-oo-modifiers';
 
export default class TrackClickModifier extends Modifier {
  @service metrics
 
  didInsertElement([eventName], options) {
    this.trackingCallback = () => this.metrics.trackEvent(eventName, options);
    this.element.addEventListener('click', this.trackingCallback, true);
  }
 
  willDestroyElement() {
    this.element.removeEventListener('click', this.trackingCallback, true);
    this.trackingCallback = null;
  }
}

Then, you could use this in your template:

<button {{track "Clicked the THING!"}}>
  Click Me!
</button>

NOTE: Because we are not observing the properties in the service in any way, if we are reading a property on a service, the modifier will not recompute if that value changes. If that's the behavior you need, you probably want to pass that value into the modifier as an argument, rather than injecting it.

API

element
the DOM element the modifier is attached to.
didInsertElement(positional: Array, named: Object)
Called when the modifier is installed on the DOM element.
didReceiveArguments(positional: Array, named: Object)
Called when the modifier is installed and anytime the arguments are updated.
didUpdateArguments(positional: Array, named: Object)
Called anytime the arguments are updated but not on the initial install.
willDestroyElement(positional: Array, named: Object)
Called when the modifier is about to be destroyed; use for teardown code.

Ember Object Import

import { Modifier } from 'ember-oo-modifiers';
 
const MyModifier = Modifier.extend({
});
 
export default MyModifier;

Native Class Import

import Modifier from 'ember-oo-modifiers';
 
export default class MyModifier extends Modifier {
}

Contributing

See the Contributing guide for details.

License

This project is licensed under the MIT License.

Readme

Keywords

Package Sidebar

Install

npm i ember-oo-modifiers

Weekly Downloads

2

Version

0.5.2

License

MIT

Unpacked Size

21.4 kB

Total Files

13

Last publish

Collaborators

  • sukima