#

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

# File: packages/ember-runtime/lib/mixins/target_action_support.js

    /**
    @module ember
    @submodule ember-runtime
    */

    import { context } from 'ember-environment';
    import {
      assert,
      get,
      Mixin,
      computed
    } from 'ember-metal';

    /**
    `Ember.TargetActionSupport` is a mixin that can be included in a class
    to add a `triggerAction` method with semantics similar to the Handlebars
    `{{action}}` helper. In normal Ember usage, the `{{action}}` helper is
    usually the best choice. This mixin is most often useful when you are
    doing more complex event handling in Components.

    @class TargetActionSupport
    @namespace Ember
    @extends Ember.Mixin
    @private
    */
    export default Mixin.create({
      target: null,
      action: null,
      actionContext: null,

      actionContextObject: computed('actionContext', function() {
        let actionContext = get(this, 'actionContext');

        if (typeof actionContext === 'string') {
          let value = get(this, actionContext);
          if (value === undefined) { value = get(context.lookup, actionContext); }
          return value;
        } else {
          return actionContext;
        }
      }),

      /**
      Send an `action` with an `actionContext` to a `target`. The action, actionContext
      and target will be retrieved from properties of the object. For example:

      ```javascript
      App.SaveButtonView = Ember.View.extend(Ember.TargetActionSupport, {
        target: Ember.computed.alias('controller'),
        action: 'save',
        actionContext: Ember.computed.alias('context'),
        click() {
          this.triggerAction(); // Sends the `save` action, along with the current context
                                // to the current controller
        }
      });
      ```

      The `target`, `action`, and `actionContext` can be provided as properties of
      an optional object argument to `triggerAction` as well.

      ```javascript
      App.SaveButtonView = Ember.View.extend(Ember.TargetActionSupport, {
        click() {
          this.triggerAction({
            action: 'save',
            target: this.get('controller'),
            actionContext: this.get('context')
          }); // Sends the `save` action, along with the current context
              // to the current controller
        }
      });
      ```

      The `actionContext` defaults to the object you are mixing `TargetActionSupport` into.
      But `target` and `action` must be specified either as properties or with the argument
      to `triggerAction`, or a combination:

      ```javascript
      App.SaveButtonView = Ember.View.extend(Ember.TargetActionSupport, {
        target: Ember.computed.alias('controller'),
        click() {
          this.triggerAction({
            action: 'save'
          }); // Sends the `save` action, along with a reference to `this`,
              // to the current controller
        }
      });
      ```

      @method triggerAction
      @param opts {Object} (optional, with the optional keys action, target and/or actionContext)
      @return {Boolean} true if the action was sent successfully and did not return false
      @private
      */
      triggerAction(opts = {}) {
        let action = opts.action || get(this, 'action');
        let target = opts.target;

        if (!target) {
          target = getTarget(this);
        }

        let actionContext = opts.actionContext;

        function args(options, actionName) {
          let ret = [];
          if (actionName) { ret.push(actionName); }

          return ret.concat(options);
        }

        if (typeof actionContext === 'undefined') {
          actionContext = get(this, 'actionContextObject') || this;
        }

        if (target && action) {
          let ret;

          if (target.send) {
            ret = target.send.apply(target, args(actionContext, action));
          } else {
            assert('The action \'' + action + '\' did not exist on ' + target, typeof target[action] === 'function');
            ret = target[action].apply(target, args(actionContext));
          }

          if (ret !== false) {
            ret = true;
          }

          return ret;
        } else {
          return false;
        }
      }
    });

    function getTarget(instance) {
      // TODO: Deprecate specifying `targetObject`
      let target = get(instance, 'targetObject');

      // if a `targetObject` CP was provided, use it
      if (target) { return target; }

      // if _targetObject use it
      if (instance._targetObject) { return instance._targetObject; }

      target = get(instance, 'target');
      if (target) {
        if (typeof target === 'string') {
          let value = get(instance, target);
          if (value === undefined) {
            value = get(context.lookup, target);
          }

          return value;
        } else {
          return target;
        }
      }

      return null;
    }