0
votes

I am making a toy libraries-tracking app using Ember. I am refactoring some code and this sendAction came up. What is the high level purpose of sendAction? Does it lead to cleaner code? I read this already.

Sorry if Ember questions have a lot of requisite code to read. I think these are the relevant files here.

Quick note, I have a libraries.new route which loads the routes/libraries/new.js file which has a renderTemplate method which renders a form template (this form template is used in a few different areas so this DRYs up my code). Since my route handler has a renderTemplate function that renders libraries/form, this is my libraries/form template:

<h2>{{title}}</h2>

<div class="row">
    <div class="col-md-6">
      {{library-item-form item=model buttonLabel=buttonLabel action='saveLibrary'}}
    </div>

    <div class="col-md-4">
      {{#library-item item=model}}
        <br/>
      {{/library-item}}
    </div>

</div>

Questions:

  1. The library-item-form component line has an action (what is this called? Is it a property?) property that gets passed the 'saveLibrary' action from its context (the libraries/new route handler right?)
  2. Since that is the passed in action for the component, that's the action that gets called when the buttonClicked method gets called in the library-item-form component because the buttonClicked method calls sendAction?

This is my library-item-form component js file:

import Ember from 'ember';

export default Ember.Component.extend({
  buttonLabel: 'Save',

  actions: {

    buttonClicked(param) {
      this.sendAction('action', param);
    }

  }
});

Here is my component template for library-item-form.hbs. It's a 3 input field form with a submit button. The submit button has an action called buttonClicked.:

<div class="form-horizontal">
    <div class="form-group has-feedback {{if item.isValid 'has-success'}}">
        <label class="col-sm-2 control-label">Name*</label>
        <div class="col-sm-10">
          {{input type="text" value=item.name class="form-control" placeholder="The name of the Library"}}
          {{#if item.isValid}}<span class="glyphicon glyphicon-ok form-control-feedback"></span>{{/if}}
        </div>
    </div>
    <div class="form-group">
        <label class="col-sm-2 control-label">Address</label>
        <div class="col-sm-10">
          {{input type="text" value=item.address class="form-control" placeholder="The address of the Library"}}
        </div>
    </div>
    <div class="form-group">
        <label class="col-sm-2 control-label">Phone</label>
        <div class="col-sm-10">
          {{input type="text" value=item.phone class="form-control" placeholder="The phone number of the Library"}}
        </div>
    </div>
    <div class="form-group">
        <div class="col-sm-offset-2 col-sm-10">
            <button type="submit" class="btn btn-default" {{action 'buttonClicked' item}} disabled="{{unless item.isValid 'disabled'}}">{{buttonLabel}}</button>
        </div>
    </div>
</div>

Oh lastly, this is the libraries/new route handler with the saveLibrary action:

import Ember from 'ember';

export default Ember.Route.extend({

  model: function () {
    return this.store.createRecord('library');
  },

  setupController: function (controller, model) {
    this._super(controller, model);

    controller.set('title', 'Create a new library');
    controller.set('buttonLabel', 'Create');
  },

  renderTemplate() {
    this.render('libraries/form');
  },

  actions: {

    saveLibrary(newLibrary) {
      newLibrary.save().then(() => this.transitionTo('libraries'));
    },

    willTransition() {
      let model = this.controller.get('model');

      if (model.get('isNew')) {
        model.destroyRecord();
      }
    }
  }
});

Last questions

  1. So it right to say that whatever action gets passed into the component in the action property (saveLibrary) is the action that gets called when the component's js file (components/library-item-form.js) calls an action (buttonClicked) that calls the sendAction function?

  2. Does the first argument of sendAction HAVE to be called 'action'? Does the property in the line that invokes the component have to be called 'action?

1
Clarification is always helpfulJwan622

1 Answers

4
votes

What is the high level purpose of sendAction? Does it lead to cleaner code?

To send an action from a component to the parent context.

Quick note, I have a libraries.new route which loads the routes/libraries/new.js file which has a renderTemplate method which renders a form template (this form template is used in a few different areas so this DRYs up my code)

Make it a component instead. It's a nicer pattern since you won't have to muck with renderTemplate.

The library-item-form component line has an action (what is this called? Is it a property?) property that gets passed the 'saveLibrary' action from its context (the libraries/new route handler right?)

Technically it's an attribute since it's passed it, but it's usually just called an action.
The context is the controller for libraries/new, not the route. Classic actions will then [bubble up] the hierarchy of active routes.

Since that is the passed in action for the component, that's the action that gets called when the buttonClicked method gets called in the library-item-form component because the buttonClicked method calls sendAction?

Yes, because you're specifying that the action being sent is action.

So it right to say that whatever action gets passed into the component in the action property (saveLibrary) is the action that gets called when the component's js file (components/library-item-form.js) calls an action (buttonClicked) that calls the sendAction function?

No, as mentioned in the previous answer, it only calls the action bound to the action attribute because you're doing this.sendAction('action', …).
If you did this.sendAction('buttonClicked, …), it would call the action bound to the buttonClicked attribute.

Does the first argument of sendAction HAVE to be called 'action'? Does the property in the line that invokes the component have to be called 'action?

No. Actions can be named semantically.

As @torazaburo mentioned, this is documented in the Guides, albeit in a previous version.
This is the case because in v1.13.0 and up, a new kind of action was introduced that has significantly better developer ergonomics and the Guides were updated to reflect that as a best practice. I suggest you give Triggering Changes with Actions a good read and try to update your application accordingly, since you're just starting (from what I understand).