The {{collect}} helper takes a source object, a paths array and an optional defaultValue, which is used if a given path cannot be found on the source object. The defaultValue defaults to null.

{{collect source paths defaultValue="foo"}}

If the source is empty, the helper will return an empty array ([]), regardless of the paths that were specified.

If a specified path was not found on the source object, defaultValue is put in its place.

const source = {
  foo: 'ember',
  bar: 'light',
  qux: {
    quax: 'table',
    quuz: 'great'
  }
 };
 const paths = ['bar', 'qux.quax', 'unknown', 'qux.quuz'];
{{#each (collect source paths defaultValue="is") as |word|}}
  {{word}}
{{/each}}
light table is great

The specified paths on the source object are observed. This means that updating these values on the source object will cause the helper to recompute, just as you would expect. You can also replace the source object altogether or change the specified paths. Everything will always stay in sync.

To allow maximum flexibility, paths can also be a string, in which case the value is returned as is and not wrapped in an array. This means that the following two invocations have different return values:

const source = { foo: 'bar' };
const arrayPath = ['foo'];
const singularPath = 'foo';
{{collect source arrayPath}}    => ['bar']
{{collect source singularPath}} => 'bar'

This is especially useful, when you are replacing {{get}} with {{collect}}, but have some surrounding code that still expects the unwrapped value for cases where paths is not an array, but also just a single path, as it would be with {{get}}.

You can disable this behavior and make {{collect}} always return an array by passing wrapSingular=true.

{{collect source "foo" wrapSingular=true}} => ['bar']