3

I want to write an Octane/Glimmer style component where passing in the action is optional. What is the best way to write this?

For example, I want both of these uses of the component to be valid:

<MyComponent />
<MyComponent @validate={{action this.validate}} />

Right now, my component class has a lot of code that looks like this, checking to see if an action was passed in before calling it:

if (this.args.validate) {
  this.args.validate()
}

That works fine for one action, but not if I need to call several optional methods in succession. What other options are there?

handlebears
  • 2,168
  • 8
  • 18

1 Answers1

8

There are several options available to make this optional actions code neater - use a getter, use tryInvoke, use a helper, or write a decorator.

Using a getter is vanilla JavaScript and may be easiest for others reading the code to understand:

import Component from '@glimmer/component';
import { action } from '@ember/object';

export default class MyComponent extends Component {
  get validate() {
    return this.args.validate || function() {};
  }

  @action
  someOtherAction() {
    this.validate()
  }
}

tryInvoke is an Ember API method that checks if a function exists before calling it. The drawbacks are that when other people are searching the code for uses of the function, their search may not find it:

tryInvoke(this.args, 'validate'); 

You could install or create your own optional helper. The ember-composable-helpers addon has an optional helper. Use it like this in a template.

{{action (optional @validate) someArg}}

Finally, you could possibly write your own decorator and call it something like @argumentFallback, then use it to label the defaults your component should use if no arguments are provided to the component.

Thanks to bendemboski and theroncross for the information!

handlebears
  • 2,168
  • 8
  • 18