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?
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!