UNPKG

ember-source

Version:

A JavaScript framework for creating ambitious web applications

199 lines (162 loc) 5.69 kB
import { a as createComputeRef, i as isInvokableRef, u as updateRef } from './reference-BshxG6wn.js'; import { f as reifyPositional, g as check, e as reifyNamed } from './debug-render-tree-CF5O4-WI.js'; import { j as setInternalHelperManager } from './api-zh_k31vb.js'; function internalHelper(helper) { return setInternalHelperManager(helper, {}); } /** Use the `{{array}}` helper to create an array to pass as an option to your components. ```handlebars <MyComponent @people={{array 'Tom Dale' 'Yehuda Katz' this.myOtherPerson}} /> ``` or ```handlebars {{yield people=(array 'Tom Dale' 'Yehuda Katz' this.myOtherPerson) }} ``` Would result in an object such as: ```js ['Tom Dale', 'Yehuda Katz', this.get('myOtherPerson')] ``` Where the 3rd item in the array is bound to updates of the `myOtherPerson` property. @method array @param {Array} options @return {Array} Array @public */ const array = internalHelper(({ positional }) => { return createComputeRef(() => reifyPositional(positional), null, 'array'); }); /* eslint-disable @typescript-eslint/no-empty-object-type */ function buildUntouchableThis(source) { let context = null; return context; } const context = buildUntouchableThis(); /** The `fn` helper allows you to ensure a function that you are passing off to another component, helper, or modifier has access to arguments that are available in the template. For example, if you have an `each` helper looping over a number of items, you may need to pass a function that expects to receive the item as an argument to a component invoked within the loop. Here's how you could use the `fn` helper to pass both the function and its arguments together: ```app/components/items-listing.gjs import DisplayItem from './display-item'; <template> {{#each @items as |item|}} <DisplayItem @item=item @select={{fn this.handleSelected item}} /> {{/each}} </template> ``` ```app/components/items-list.gjs import Component from '@glimmer/component'; import { action } from '@ember/object'; export default class ItemsList extends Component { handleSelected = (item) => { // ...snip... } } ``` In this case the `DisplayItem` component will receive a normal function that it can invoke. When it invokes the function, the `handleSelected` function will receive the `item` and any arguments passed, thanks to the `fn` helper. Let's take look at what that means in a couple circumstances: - When invoked as `this.args.select()` the `handleSelected` function will receive the `item` from the loop as its first and only argument. - When invoked as `this.args.select('foo')` the `handleSelected` function will receive the `item` from the loop as its first argument and the string `'foo'` as its second argument. In the example above, we used an arrow function to ensure that `handleSelected` is properly bound to the `items-list`, but let's explore what happens if we left out the arrow function: ```app/components/items-list.gjs import Component from '@glimmer/component'; export default class ItemsList extends Component { handleSelected(item) { // ...snip... } } ``` In this example, when `handleSelected` is invoked inside the `display-item` component, it will **not** have access to the component instance. In other words, it will have no `this` context, so please make sure your functions are bound (via an arrow function or other means) before passing into `fn`! See also [partial application](https://en.wikipedia.org/wiki/Partial_application). `fn` is built-in and does not require any additional imports. @method fn @public */ const fn = internalHelper(({ positional }) => { let callbackRef = check(positional[0]); return createComputeRef(() => { return (...invocationArgs) => { let [fn, ...args] = reifyPositional(positional); if (isInvokableRef(callbackRef)) { let value = args.length > 0 ? args[0] : invocationArgs[0]; return void updateRef(callbackRef, value); } else { // eslint-disable-next-line @typescript-eslint/no-unsafe-return -- @fixme return fn.call(context, ...args, ...invocationArgs); } }; }, null, 'fn'); }); /** Use the `{{hash}}` helper to create a hash to pass as an option to your components. This is especially useful for contextual components where you can just yield a hash: ```handlebars {{yield (hash name='Sarah' title=office )}} ``` Would result in an object such as: ```js { name: 'Sarah', title: this.get('office') } ``` Where the `title` is bound to updates of the `office` property. Note that the hash is an empty object with no prototype chain, therefore common methods like `toString` are not available in the resulting hash. If you need to use such a method, you can use the `call` or `apply` approach: ```js function toString(obj) { return Object.prototype.toString.apply(obj); } ``` @method hash @param {Object} options @return {Object} Hash @public */ const hash = internalHelper(({ named }) => { let ref = createComputeRef(() => { return reifyNamed(named); }, null, 'hash'); // Setup the children so that templates can bypass getting the value of // the reference and treat children lazily let children = new Map(); for (let name in named) { children.set(name, named[name]); } ref.children = children; return ref; }); export { array as a, fn as f, hash as h, internalHelper as i };