--- title: Use Helper Libraries Effectively impact: MEDIUM impactDescription: Reduces custom helper maintenance and keeps templates concise tags: templates, helpers, ember-truth-helpers, ember-composable-helpers --- ## Use Helper Libraries Effectively Leverage community helper libraries to write cleaner templates and avoid creating unnecessary custom helpers for common operations. ## Problem Reinventing common functionality with custom helpers adds maintenance burden and bundle size when well-maintained helper libraries already provide the needed functionality. **Incorrect:** ```glimmer-js // app/utils/is-equal.js - Unnecessary custom helper export function isEqual(a, b) { return a === b; } // app/components/user-badge.gjs import { isEqual } from '../utils/is-equal'; class UserBadge extends Component { } ``` ## Solution **Note:** These helpers will be built into Ember 7 core, but currently require installing the respective addon packages. **Installation:** ```bash npm install ember-truth-helpers ember-composable-helpers ``` Use helper libraries like `ember-truth-helpers` and `ember-composable-helpers`: **Correct:** ```glimmer-js // app/components/user-badge.gjs import Component from '@glimmer/component'; import { eq } from 'ember-truth-helpers'; class UserBadge extends Component { } ``` ## Comparison Helpers (ember-truth-helpers) **Installation:** `npm install ember-truth-helpers` ```glimmer-js // app/components/comparison-examples.gjs import Component from '@glimmer/component'; import { eq, not, and, or, lt, lte, gt, gte } from 'ember-truth-helpers'; class ComparisonExamples extends Component { } ``` ## Array and Object Helpers (ember-composable-helpers) **Installation:** `npm install ember-composable-helpers` ```glimmer-js // app/components/collection-helpers.gjs import Component from '@glimmer/component'; import { array, hash } from 'ember-composable-helpers/helpers'; import { get } from 'ember-composable-helpers/helpers'; class CollectionHelpers extends Component { } ``` ## String Helpers ```glimmer-js // app/components/string-helpers.gjs import Component from '@glimmer/component'; import { concat } from '@ember/helper'; // Built-in to Ember class StringHelpers extends Component { } ``` ## Action Helpers (fn) ```glimmer-js // app/components/action-helpers.gjs import Component from '@glimmer/component'; import { fn } from '@ember/helper'; // Built-in to Ember import { on } from '@ember/modifier'; class ActionHelpers extends Component { updateValue = (field, event) => { this.args.onChange(field, event.target.value); }; deleteItem = (id) => { this.args.onDelete(id); }; } ``` ## Conditional Helpers (if/unless) ```glimmer-js // app/components/conditional-inline.gjs import Component from '@glimmer/component'; import { if as ifHelper } from '@ember/helper'; // Built-in to Ember class ConditionalInline extends Component { } ``` ## Practical Combinations **Dynamic Classes:** ```glimmer-js // app/components/dynamic-classes.gjs import Component from '@glimmer/component'; import { concat, if as ifHelper } from '@ember/helper'; // Built-in to Ember import { and, not } from 'ember-truth-helpers'; class DynamicClasses extends Component { } ``` **List Filtering:** ```glimmer-js // app/components/filtered-list.gjs import Component from '@glimmer/component'; import { tracked } from '@glimmer/tracking'; import { cached } from '@glimmer/tracking'; import { fn, concat } from '@ember/helper'; import { on } from '@ember/modifier'; import { eq } from 'ember-truth-helpers'; import { array } from 'ember-composable-helpers/helpers'; class FilteredList extends Component { @tracked filter = 'all'; @cached get filteredItems() { if (this.filter === 'all') return this.args.items; return this.args.items.filter((item) => item.status === this.filter); } } ``` ## Complex Example ```glimmer-js // app/components/user-profile-card.gjs import Component from '@glimmer/component'; import { concat, if as ifHelper, fn } from '@ember/helper'; // Built-in to Ember import { eq, not, and, or } from 'ember-truth-helpers'; import { hash, array, get } from 'ember-composable-helpers/helpers'; import { on } from '@ember/modifier'; class UserProfileCard extends Component { updateField = (field, value) => { this.args.onUpdate(field, value); }; } ``` ## Performance Impact - **Library helpers**: ~0% overhead (compiled into efficient bytecode) - **Custom helpers**: 5-15% overhead per helper call - **Inline logic**: Cleaner templates, better tree-shaking ## When to Use - **Library helpers**: For all common operations (equality, logic, arrays, strings) - **Custom helpers**: Only for domain-specific logic not covered by library helpers - **Component logic**: For complex operations that need @cached or multiple dependencies ## Complete Helper Reference **Note:** These helpers will be built into Ember 7 core. Until then: **Actually Built-in to Ember (from `@ember/helper`):** - `concat` - Concatenate strings - `fn` - Partial application / bind arguments - `if` - Ternary-like conditional value - `mut` - Create settable binding (use sparingly) **From `ember-truth-helpers` package:** - `eq` - Equality (===) - `not` - Negation (!) - `and` - Logical AND - `or` - Logical OR - `lt`, `lte`, `gt`, `gte` - Numeric comparisons **From `ember-composable-helpers` package:** - `array` - Create array inline - `hash` - Create object inline - `get` - Dynamic property access ## References - [Ember Built-in Helpers](https://guides.emberjs.com/release/templates/built-in-helpers/) - [Template Helpers API](https://api.emberjs.com/ember/release/modules/@ember%2Fhelper) - [fn Helper Guide](https://guides.emberjs.com/release/components/helper-functions/) - [ember-truth-helpers](https://github.com/jmurphyau/ember-truth-helpers) - [ember-composable-helpers](https://github.com/DockYard/ember-composable-helpers)