Ember: Send child component's action to a parent component












0














I am trying to call/trigger a child component's action from a parent. I've tried this a couple ways but I'm not getting anywhere. This is basically what I have so far.

I am attempting to send the action up to the parent by passing it as a parameter in the action that was passed down...

This seems a bit like a spaghetti situation but the way my project is organized, this is my result.


If anyone could, please tell me how to successfully pass an action up to the parent as a parameter. (I'm curious to know how, if possible)

If anyone also has a better suggestion on how to call a child's action, please share. Thanks in advance!



parent-component.hbs



{{child-component anAction=(action "anAction")}}
<div onclick={{action actionPassedFromChild}}></div>


parent-component.js



actionPassedFromChild: null,
....
actions: {
parentAction(childAction){
this.set('actionPassedFromChild', childAction);
}
}





child-component.hbs



<div onclick={{action "anAction"}}


child-component.js



....
actions: {
anAction(){
this.parentAction(childAction);
}
childAction(){
//Some operation
}
}


In this example, if I stop the code inside of 'anAction', I do have 'childAction'. But by the time that it gets passed into 'parentAction', it is undefined. Could anyone explain why?










share|improve this question





























    0














    I am trying to call/trigger a child component's action from a parent. I've tried this a couple ways but I'm not getting anywhere. This is basically what I have so far.

    I am attempting to send the action up to the parent by passing it as a parameter in the action that was passed down...

    This seems a bit like a spaghetti situation but the way my project is organized, this is my result.


    If anyone could, please tell me how to successfully pass an action up to the parent as a parameter. (I'm curious to know how, if possible)

    If anyone also has a better suggestion on how to call a child's action, please share. Thanks in advance!



    parent-component.hbs



    {{child-component anAction=(action "anAction")}}
    <div onclick={{action actionPassedFromChild}}></div>


    parent-component.js



    actionPassedFromChild: null,
    ....
    actions: {
    parentAction(childAction){
    this.set('actionPassedFromChild', childAction);
    }
    }





    child-component.hbs



    <div onclick={{action "anAction"}}


    child-component.js



    ....
    actions: {
    anAction(){
    this.parentAction(childAction);
    }
    childAction(){
    //Some operation
    }
    }


    In this example, if I stop the code inside of 'anAction', I do have 'childAction'. But by the time that it gets passed into 'parentAction', it is undefined. Could anyone explain why?










    share|improve this question



























      0












      0








      0







      I am trying to call/trigger a child component's action from a parent. I've tried this a couple ways but I'm not getting anywhere. This is basically what I have so far.

      I am attempting to send the action up to the parent by passing it as a parameter in the action that was passed down...

      This seems a bit like a spaghetti situation but the way my project is organized, this is my result.


      If anyone could, please tell me how to successfully pass an action up to the parent as a parameter. (I'm curious to know how, if possible)

      If anyone also has a better suggestion on how to call a child's action, please share. Thanks in advance!



      parent-component.hbs



      {{child-component anAction=(action "anAction")}}
      <div onclick={{action actionPassedFromChild}}></div>


      parent-component.js



      actionPassedFromChild: null,
      ....
      actions: {
      parentAction(childAction){
      this.set('actionPassedFromChild', childAction);
      }
      }





      child-component.hbs



      <div onclick={{action "anAction"}}


      child-component.js



      ....
      actions: {
      anAction(){
      this.parentAction(childAction);
      }
      childAction(){
      //Some operation
      }
      }


      In this example, if I stop the code inside of 'anAction', I do have 'childAction'. But by the time that it gets passed into 'parentAction', it is undefined. Could anyone explain why?










      share|improve this question















      I am trying to call/trigger a child component's action from a parent. I've tried this a couple ways but I'm not getting anywhere. This is basically what I have so far.

      I am attempting to send the action up to the parent by passing it as a parameter in the action that was passed down...

      This seems a bit like a spaghetti situation but the way my project is organized, this is my result.


      If anyone could, please tell me how to successfully pass an action up to the parent as a parameter. (I'm curious to know how, if possible)

      If anyone also has a better suggestion on how to call a child's action, please share. Thanks in advance!



      parent-component.hbs



      {{child-component anAction=(action "anAction")}}
      <div onclick={{action actionPassedFromChild}}></div>


      parent-component.js



      actionPassedFromChild: null,
      ....
      actions: {
      parentAction(childAction){
      this.set('actionPassedFromChild', childAction);
      }
      }





      child-component.hbs



      <div onclick={{action "anAction"}}


      child-component.js



      ....
      actions: {
      anAction(){
      this.parentAction(childAction);
      }
      childAction(){
      //Some operation
      }
      }


      In this example, if I stop the code inside of 'anAction', I do have 'childAction'. But by the time that it gets passed into 'parentAction', it is undefined. Could anyone explain why?







      javascript ember.js handlebars.js action






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 16 '18 at 19:19

























      asked Nov 16 '18 at 19:11









      Nate Thompson

      425




      425
























          1 Answer
          1






          active

          oldest

          votes


















          2














          It seems like you have some typos. For example, parentAction is not passed to child component. But if I understood what do you want to achieve right - it is doable, however I can't even imagine why you might need this.



          You can play with my example here. Select is in child component and button is in parent component. When you choose something in select - child component sends one of two functions to parent component. And when you click a button - parent component calls that function.



          Code:



          //child-component.js
          import Ember from 'ember';


          export default Ember.Component.extend({
          line1: "Say Hi!",
          line2: "Say Yeah!",

          changeAction(newAction) {
          switch (newAction) {
          case "1":
          this.onActionChange(this.action1);
          break;

          case "2":
          this.onActionChange(this.action2);
          break;

          default:
          this.onActionChange(undefined);
          break;
          }
          },

          action1: Ember.computed(function(){
          const that = this;
          return function() {
          alert(that.line1);
          }
          }),

          action2: Ember.computed(function(){
          const that = this;
          return function() {
          alert(that.line2);
          }
          })
          });

          //child-component.hbs
          <select onchange={{action changeAction value="target.value"}}>
          <option>Choose something</option>
          <option value="1">Action 1</option>
          <option value="2">Action 2</option>
          </select>

          //parent-component.js
          import Ember from 'ember';

          export default Ember.Component.extend({
          childishAction() {
          if (typeof this.childAction === 'function') {
          this.childAction();
          }
          }
          });

          //parent-component.hbs
          {{child-component onActionChange=(action (mut childAction))}}
          <div><button disabled={{unless childAction true false}} onclick={{action childishAction}}>Let's do it!</button></div>


          What happens here - you can't pass to action helper something that is not defined when ember renders template. So you need to store action that child-component sends into some variable and call it using some intermediate action of parent component.



          In my example, function returned from child component is stored in childAction property of parent component and childishAction of parent component calls it.



          Hope this helps. But you probably trying to solve some problem in not a right way.






          share|improve this answer























          • Assigning the child function to a property helped. Thank you!
            – Nate Thompson
            Nov 16 '18 at 20:32











          Your Answer






          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "1"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53344020%2fember-send-child-components-action-to-a-parent-component%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          1 Answer
          1






          active

          oldest

          votes








          1 Answer
          1






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          2














          It seems like you have some typos. For example, parentAction is not passed to child component. But if I understood what do you want to achieve right - it is doable, however I can't even imagine why you might need this.



          You can play with my example here. Select is in child component and button is in parent component. When you choose something in select - child component sends one of two functions to parent component. And when you click a button - parent component calls that function.



          Code:



          //child-component.js
          import Ember from 'ember';


          export default Ember.Component.extend({
          line1: "Say Hi!",
          line2: "Say Yeah!",

          changeAction(newAction) {
          switch (newAction) {
          case "1":
          this.onActionChange(this.action1);
          break;

          case "2":
          this.onActionChange(this.action2);
          break;

          default:
          this.onActionChange(undefined);
          break;
          }
          },

          action1: Ember.computed(function(){
          const that = this;
          return function() {
          alert(that.line1);
          }
          }),

          action2: Ember.computed(function(){
          const that = this;
          return function() {
          alert(that.line2);
          }
          })
          });

          //child-component.hbs
          <select onchange={{action changeAction value="target.value"}}>
          <option>Choose something</option>
          <option value="1">Action 1</option>
          <option value="2">Action 2</option>
          </select>

          //parent-component.js
          import Ember from 'ember';

          export default Ember.Component.extend({
          childishAction() {
          if (typeof this.childAction === 'function') {
          this.childAction();
          }
          }
          });

          //parent-component.hbs
          {{child-component onActionChange=(action (mut childAction))}}
          <div><button disabled={{unless childAction true false}} onclick={{action childishAction}}>Let's do it!</button></div>


          What happens here - you can't pass to action helper something that is not defined when ember renders template. So you need to store action that child-component sends into some variable and call it using some intermediate action of parent component.



          In my example, function returned from child component is stored in childAction property of parent component and childishAction of parent component calls it.



          Hope this helps. But you probably trying to solve some problem in not a right way.






          share|improve this answer























          • Assigning the child function to a property helped. Thank you!
            – Nate Thompson
            Nov 16 '18 at 20:32
















          2














          It seems like you have some typos. For example, parentAction is not passed to child component. But if I understood what do you want to achieve right - it is doable, however I can't even imagine why you might need this.



          You can play with my example here. Select is in child component and button is in parent component. When you choose something in select - child component sends one of two functions to parent component. And when you click a button - parent component calls that function.



          Code:



          //child-component.js
          import Ember from 'ember';


          export default Ember.Component.extend({
          line1: "Say Hi!",
          line2: "Say Yeah!",

          changeAction(newAction) {
          switch (newAction) {
          case "1":
          this.onActionChange(this.action1);
          break;

          case "2":
          this.onActionChange(this.action2);
          break;

          default:
          this.onActionChange(undefined);
          break;
          }
          },

          action1: Ember.computed(function(){
          const that = this;
          return function() {
          alert(that.line1);
          }
          }),

          action2: Ember.computed(function(){
          const that = this;
          return function() {
          alert(that.line2);
          }
          })
          });

          //child-component.hbs
          <select onchange={{action changeAction value="target.value"}}>
          <option>Choose something</option>
          <option value="1">Action 1</option>
          <option value="2">Action 2</option>
          </select>

          //parent-component.js
          import Ember from 'ember';

          export default Ember.Component.extend({
          childishAction() {
          if (typeof this.childAction === 'function') {
          this.childAction();
          }
          }
          });

          //parent-component.hbs
          {{child-component onActionChange=(action (mut childAction))}}
          <div><button disabled={{unless childAction true false}} onclick={{action childishAction}}>Let's do it!</button></div>


          What happens here - you can't pass to action helper something that is not defined when ember renders template. So you need to store action that child-component sends into some variable and call it using some intermediate action of parent component.



          In my example, function returned from child component is stored in childAction property of parent component and childishAction of parent component calls it.



          Hope this helps. But you probably trying to solve some problem in not a right way.






          share|improve this answer























          • Assigning the child function to a property helped. Thank you!
            – Nate Thompson
            Nov 16 '18 at 20:32














          2












          2








          2






          It seems like you have some typos. For example, parentAction is not passed to child component. But if I understood what do you want to achieve right - it is doable, however I can't even imagine why you might need this.



          You can play with my example here. Select is in child component and button is in parent component. When you choose something in select - child component sends one of two functions to parent component. And when you click a button - parent component calls that function.



          Code:



          //child-component.js
          import Ember from 'ember';


          export default Ember.Component.extend({
          line1: "Say Hi!",
          line2: "Say Yeah!",

          changeAction(newAction) {
          switch (newAction) {
          case "1":
          this.onActionChange(this.action1);
          break;

          case "2":
          this.onActionChange(this.action2);
          break;

          default:
          this.onActionChange(undefined);
          break;
          }
          },

          action1: Ember.computed(function(){
          const that = this;
          return function() {
          alert(that.line1);
          }
          }),

          action2: Ember.computed(function(){
          const that = this;
          return function() {
          alert(that.line2);
          }
          })
          });

          //child-component.hbs
          <select onchange={{action changeAction value="target.value"}}>
          <option>Choose something</option>
          <option value="1">Action 1</option>
          <option value="2">Action 2</option>
          </select>

          //parent-component.js
          import Ember from 'ember';

          export default Ember.Component.extend({
          childishAction() {
          if (typeof this.childAction === 'function') {
          this.childAction();
          }
          }
          });

          //parent-component.hbs
          {{child-component onActionChange=(action (mut childAction))}}
          <div><button disabled={{unless childAction true false}} onclick={{action childishAction}}>Let's do it!</button></div>


          What happens here - you can't pass to action helper something that is not defined when ember renders template. So you need to store action that child-component sends into some variable and call it using some intermediate action of parent component.



          In my example, function returned from child component is stored in childAction property of parent component and childishAction of parent component calls it.



          Hope this helps. But you probably trying to solve some problem in not a right way.






          share|improve this answer














          It seems like you have some typos. For example, parentAction is not passed to child component. But if I understood what do you want to achieve right - it is doable, however I can't even imagine why you might need this.



          You can play with my example here. Select is in child component and button is in parent component. When you choose something in select - child component sends one of two functions to parent component. And when you click a button - parent component calls that function.



          Code:



          //child-component.js
          import Ember from 'ember';


          export default Ember.Component.extend({
          line1: "Say Hi!",
          line2: "Say Yeah!",

          changeAction(newAction) {
          switch (newAction) {
          case "1":
          this.onActionChange(this.action1);
          break;

          case "2":
          this.onActionChange(this.action2);
          break;

          default:
          this.onActionChange(undefined);
          break;
          }
          },

          action1: Ember.computed(function(){
          const that = this;
          return function() {
          alert(that.line1);
          }
          }),

          action2: Ember.computed(function(){
          const that = this;
          return function() {
          alert(that.line2);
          }
          })
          });

          //child-component.hbs
          <select onchange={{action changeAction value="target.value"}}>
          <option>Choose something</option>
          <option value="1">Action 1</option>
          <option value="2">Action 2</option>
          </select>

          //parent-component.js
          import Ember from 'ember';

          export default Ember.Component.extend({
          childishAction() {
          if (typeof this.childAction === 'function') {
          this.childAction();
          }
          }
          });

          //parent-component.hbs
          {{child-component onActionChange=(action (mut childAction))}}
          <div><button disabled={{unless childAction true false}} onclick={{action childishAction}}>Let's do it!</button></div>


          What happens here - you can't pass to action helper something that is not defined when ember renders template. So you need to store action that child-component sends into some variable and call it using some intermediate action of parent component.



          In my example, function returned from child component is stored in childAction property of parent component and childishAction of parent component calls it.



          Hope this helps. But you probably trying to solve some problem in not a right way.







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Nov 16 '18 at 20:27

























          answered Nov 16 '18 at 20:21









          Gennady Dogaev

          3,8971818




          3,8971818












          • Assigning the child function to a property helped. Thank you!
            – Nate Thompson
            Nov 16 '18 at 20:32


















          • Assigning the child function to a property helped. Thank you!
            – Nate Thompson
            Nov 16 '18 at 20:32
















          Assigning the child function to a property helped. Thank you!
          – Nate Thompson
          Nov 16 '18 at 20:32




          Assigning the child function to a property helped. Thank you!
          – Nate Thompson
          Nov 16 '18 at 20:32


















          draft saved

          draft discarded




















































          Thanks for contributing an answer to Stack Overflow!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.





          Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


          Please pay close attention to the following guidance:


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53344020%2fember-send-child-components-action-to-a-parent-component%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          How to change which sound is reproduced for terminal bell?

          Title Spacing in Bjornstrup Chapter, Removing Chapter Number From Contents

          Can I use Tabulator js library in my java Spring + Thymeleaf project?