DEV Community

Cover image for Demystifying ember-render-modifiers
Raja SK
Raja SK

Posted on

Demystifying ember-render-modifiers

Ember modifier is one of the coolest features that I see in ember octane. Many ember addons are based on ember modifiers. ember-render-modifier is one of those addons which provides element modifiers that can be used to hook into specific portions of the rendering lifecycle.

One key point that fascinates me about ember-render-modifiers is using this, we can access the basic lifecycle hooks of a component without creating a class for it. That is, we can access them in a template(.hbs) file.

While I stumbled upon this addon, I wanted to explore more. So, I did it and like to share my learnings with you all.

How ember-render-modifier works behind the scene?

Behind the scenes, ember-render-modifiers is nothing but the customModifierManager API which was a low-level API designed especially for addon developers to create and manage custom modifiers.

To know more about Custom Modifier Manager and how they are used to manage ember modifiers, feel free to check out my previous blog.

How does a customModifierManager look like?

Each modifier manager has four life-cycle methods.

  1. createModifier - creates an instance of the modifier.
  2. installModifier - runs when a modifier is installed on a DOM element.
  3. updateModifier - runs when the arguments passed to the modifier element changes.
  4. destroyModifier - runs just before the element is to be destroyed.

The skeleton of a customModifierManager API looks like

import { setModifierManager, capabilities } from '@ember/modifier';

export default setModifierManager(
  () => ({
    capabilities: capabilities('3.6'),

    createModifier(factory, args) {
      return factory.create(args.named);
    },

    installModifier(instance, element, args) {
      // installation logic...
    },

    updateModifier(instance,args) {
      //re-render logic
    }

    destroyModifier(instance, args) {
      // teardown logic...
    }
  }), class BaseClass {}
);
Enter fullscreen mode Exit fullscreen mode

What are the modifiers provided by ember-render-modifiers?

  1. did-insert - runs when the element is inserted in the DOM.
  2. did-update - runs when the element's arguments changes
  3. will-destroy - runs when the element is destroyed.

Along with this, if we see the customModifierManager API's skeleton, we can able to understand how ember-render-modifiers are implemented.

Each modifier in this addon uses its respective lifecycle method of the customModiferManager API and runs the function passed to the modifier within that method itself.

  • did-insert => installModifier
  • did-update => updateModifier
  • will-destroy => destroyModifier

Let's take the did-insert modifier.

export default setModifierManager(
  () => ({
    capabilities: capabilities('3.13', { disableAutoTracking: true }),

    createModifier() {},

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

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

    updateModifier() {},
    destroyModifier() {},
  }),
  class DidInsertModifier {}
);
Enter fullscreen mode Exit fullscreen mode

Here, the main logic lies inside the installModifier and the other two lifecycle methods are left empty.

Similarly, in the did-update modifier, the logic lies inside the updateModifier and the state maintenance is done by installModifier

export default setModifierManager(
  () => ({
    capabilities: capabilities('3.13', { disableAutoTracking: true }),

    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 {}
);
Enter fullscreen mode Exit fullscreen mode

Also, in the will-destroy modifier, the logic lies inside the destroyModifier and installModifier is used to maintain state.

export default setModifierManager(
  () => ({
    capabilities: capabilities('3.13', { disableAutoTracking: true }),

    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 {}
);
Enter fullscreen mode Exit fullscreen mode

Among several addons that are based on ember modifier, this ember-render-modifier is one of its kind and easy to understand the implementation.

There are so many ways to play with ember modifiers. This addon is a small drop that ember modifiers can do. You can also play with your thoughts on ember modifiers and create some custom modifiers.


Hope you find my learnings on ember-render-modifiers informative. See you all in my next blog! 👋

Top comments (0)