#

API Docs for: v2.11.1
Show: Inherited Protected Private Deprecated

# File: packages/ember-glimmer/lib/helpers/get.js

    import { set } from 'ember-metal';
    import { CachedReference, UPDATE } from '../utils/references';
    import {
      CONSTANT_TAG,
      UpdatableTag,
      combine,
      isConst,
      referenceFromParts
    } from 'glimmer-reference';

    /**
    @module ember
    @submodule ember-glimmer
    */

    /**
      Dynamically look up a property on an object. The second argument to `{{get}}`
      should have a string value, although it can be bound.

      For example, these two usages are equivilent:

      ```handlebars
      {{person.height}}
      {{get person "height"}}
      ```

      If there were several facts about a person, the `{{get}}` helper can dynamically
      pick one:

      ```handlebars
      {{get person factName}}
      ```

      For a more complex example, this template would allow the user to switch
      between showing the user's height and weight with a click:

      ```handlebars
      {{get person factName}}
      <button {{action (action (mut factName)) "height"}}>Show height</button>
      <button {{action (action (mut factName)) "weight"}}>Show weight</button>
      ```

      The `{{get}}` helper can also respect mutable values itself. For example:

      ```handlebars
      {{input value=(mut (get person factName)) type="text"}}
      <button {{action (action (mut factName)) "height"}}>Show height</button>
      <button {{action (action (mut factName)) "weight"}}>Show weight</button>
      ```

      Would allow the user to swap what fact is being displayed, and also edit
      that fact via a two-way mutable binding.

      @public
      @method get
      @for Ember.Templates.helpers
      @since 2.1.0
     */

    export default function(vm, args) {
      return GetHelperReference.create(args.positional.at(0), args.positional.at(1));
    }

    class GetHelperReference extends CachedReference {
      static create(sourceReference, pathReference) {
        if (isConst(pathReference)) {
          let parts = pathReference.value().split('.');
          return referenceFromParts(sourceReference, parts);
        } else {
          return new GetHelperReference(sourceReference, pathReference);
        }
      }

      constructor(sourceReference, pathReference) {
        super();
        this.sourceReference = sourceReference;
        this.pathReference = pathReference;

        this.lastPath = null;
        this.innerReference = null;

        let innerTag = this.innerTag = new UpdatableTag(CONSTANT_TAG);

        this.tag = combine([sourceReference.tag, pathReference.tag, innerTag]);
      }

      compute() {
        let { lastPath, innerReference, innerTag } = this;

        let path = this.lastPath = this.pathReference.value();

        if (path !== lastPath) {
          if (path) {
            let pathType = typeof path;

            if (pathType === 'string') {
              innerReference = this.innerReference = referenceFromParts(this.sourceReference, path.split('.'));
            } else if (pathType === 'number') {
              innerReference = this.innerReference = this.sourceReference.get(path);
            }

            innerTag.update(innerReference.tag);
          } else {
            innerReference = this.innerReference = null;
            innerTag.update(CONSTANT_TAG);
          }
        }

        return innerReference ? innerReference.value() : null;
      }

      [UPDATE](value) {
        set(this.sourceReference.value(), this.pathReference.value(), value);
      }
    }