Re render a component from another component Ember












0















I'm trying to re-render a specific component when another component is clicked. When the user clicks the particular button component, a variable in sessionStorage changes, which is used by another component to display data. Upon click I want that specific component to re-render itself. I have seen Ember Re-render component and Ember Rerendering component within component, but they don't seem to be working in my case. Here are my files:



templates/components/buttons/button-cancel.hbs



{{#each-in metaData as |module definition|}}
{{#if (eq definition.name "cancel_button") }}
<button class={{definition.css_class}} {{action "changeToAccounts"}}> Accounts </button>
{{/if}}
{{/each-in}}
{{yield}}


components/buttons/button-cancel.js



import Component from '@ember/component';
import MD from "../../utils/metadata";

export default Component.extend({
init: function() {
this._super(...arguments);
this.metaData = MD.create().getMetaViewStuff("Leads", "record", "buttons");
// console.log(this.metaData);
},
actions: {
changeToAccounts: function() {
sessionStorage.setItem('module', "Accounts");
}
}

});


templates/components/panels/list-panel.hbs



{{buttons/button-save}} <!--This button is same as button-cancel-->
{{buttons/button-cancel}}
{{field-list-headers}}
{{yield}}


components/field-list-headers (the component that needs re-rendering)



import Component from '@ember/component';
import MD from "../utils/metadata"

export default Component.extend({
init: function(){
this._super(...arguments);
this.metaData = MD.create().getMetaViewStuff(sessionStorage.getItem('module'), "list", "panels")
}
});


function getMetaViewStuff



  getMetaViewStuff: function(module, submodule, item, i18n) {
if (this.modules[module]["views"][submodule]["meta"] !== undefined && this.modules[module]["views"][submodule]["meta"][item] !== undefined) {
let meta = this.modules[module]["views"][submodule]["meta"][item];
return meta;
}
return false;
}









share|improve this question



























    0















    I'm trying to re-render a specific component when another component is clicked. When the user clicks the particular button component, a variable in sessionStorage changes, which is used by another component to display data. Upon click I want that specific component to re-render itself. I have seen Ember Re-render component and Ember Rerendering component within component, but they don't seem to be working in my case. Here are my files:



    templates/components/buttons/button-cancel.hbs



    {{#each-in metaData as |module definition|}}
    {{#if (eq definition.name "cancel_button") }}
    <button class={{definition.css_class}} {{action "changeToAccounts"}}> Accounts </button>
    {{/if}}
    {{/each-in}}
    {{yield}}


    components/buttons/button-cancel.js



    import Component from '@ember/component';
    import MD from "../../utils/metadata";

    export default Component.extend({
    init: function() {
    this._super(...arguments);
    this.metaData = MD.create().getMetaViewStuff("Leads", "record", "buttons");
    // console.log(this.metaData);
    },
    actions: {
    changeToAccounts: function() {
    sessionStorage.setItem('module', "Accounts");
    }
    }

    });


    templates/components/panels/list-panel.hbs



    {{buttons/button-save}} <!--This button is same as button-cancel-->
    {{buttons/button-cancel}}
    {{field-list-headers}}
    {{yield}}


    components/field-list-headers (the component that needs re-rendering)



    import Component from '@ember/component';
    import MD from "../utils/metadata"

    export default Component.extend({
    init: function(){
    this._super(...arguments);
    this.metaData = MD.create().getMetaViewStuff(sessionStorage.getItem('module'), "list", "panels")
    }
    });


    function getMetaViewStuff



      getMetaViewStuff: function(module, submodule, item, i18n) {
    if (this.modules[module]["views"][submodule]["meta"] !== undefined && this.modules[module]["views"][submodule]["meta"][item] !== undefined) {
    let meta = this.modules[module]["views"][submodule]["meta"][item];
    return meta;
    }
    return false;
    }









    share|improve this question

























      0












      0








      0








      I'm trying to re-render a specific component when another component is clicked. When the user clicks the particular button component, a variable in sessionStorage changes, which is used by another component to display data. Upon click I want that specific component to re-render itself. I have seen Ember Re-render component and Ember Rerendering component within component, but they don't seem to be working in my case. Here are my files:



      templates/components/buttons/button-cancel.hbs



      {{#each-in metaData as |module definition|}}
      {{#if (eq definition.name "cancel_button") }}
      <button class={{definition.css_class}} {{action "changeToAccounts"}}> Accounts </button>
      {{/if}}
      {{/each-in}}
      {{yield}}


      components/buttons/button-cancel.js



      import Component from '@ember/component';
      import MD from "../../utils/metadata";

      export default Component.extend({
      init: function() {
      this._super(...arguments);
      this.metaData = MD.create().getMetaViewStuff("Leads", "record", "buttons");
      // console.log(this.metaData);
      },
      actions: {
      changeToAccounts: function() {
      sessionStorage.setItem('module', "Accounts");
      }
      }

      });


      templates/components/panels/list-panel.hbs



      {{buttons/button-save}} <!--This button is same as button-cancel-->
      {{buttons/button-cancel}}
      {{field-list-headers}}
      {{yield}}


      components/field-list-headers (the component that needs re-rendering)



      import Component from '@ember/component';
      import MD from "../utils/metadata"

      export default Component.extend({
      init: function(){
      this._super(...arguments);
      this.metaData = MD.create().getMetaViewStuff(sessionStorage.getItem('module'), "list", "panels")
      }
      });


      function getMetaViewStuff



        getMetaViewStuff: function(module, submodule, item, i18n) {
      if (this.modules[module]["views"][submodule]["meta"] !== undefined && this.modules[module]["views"][submodule]["meta"][item] !== undefined) {
      let meta = this.modules[module]["views"][submodule]["meta"][item];
      return meta;
      }
      return false;
      }









      share|improve this question














      I'm trying to re-render a specific component when another component is clicked. When the user clicks the particular button component, a variable in sessionStorage changes, which is used by another component to display data. Upon click I want that specific component to re-render itself. I have seen Ember Re-render component and Ember Rerendering component within component, but they don't seem to be working in my case. Here are my files:



      templates/components/buttons/button-cancel.hbs



      {{#each-in metaData as |module definition|}}
      {{#if (eq definition.name "cancel_button") }}
      <button class={{definition.css_class}} {{action "changeToAccounts"}}> Accounts </button>
      {{/if}}
      {{/each-in}}
      {{yield}}


      components/buttons/button-cancel.js



      import Component from '@ember/component';
      import MD from "../../utils/metadata";

      export default Component.extend({
      init: function() {
      this._super(...arguments);
      this.metaData = MD.create().getMetaViewStuff("Leads", "record", "buttons");
      // console.log(this.metaData);
      },
      actions: {
      changeToAccounts: function() {
      sessionStorage.setItem('module', "Accounts");
      }
      }

      });


      templates/components/panels/list-panel.hbs



      {{buttons/button-save}} <!--This button is same as button-cancel-->
      {{buttons/button-cancel}}
      {{field-list-headers}}
      {{yield}}


      components/field-list-headers (the component that needs re-rendering)



      import Component from '@ember/component';
      import MD from "../utils/metadata"

      export default Component.extend({
      init: function(){
      this._super(...arguments);
      this.metaData = MD.create().getMetaViewStuff(sessionStorage.getItem('module'), "list", "panels")
      }
      });


      function getMetaViewStuff



        getMetaViewStuff: function(module, submodule, item, i18n) {
      if (this.modules[module]["views"][submodule]["meta"] !== undefined && this.modules[module]["views"][submodule]["meta"][item] !== undefined) {
      let meta = this.modules[module]["views"][submodule]["meta"][item];
      return meta;
      }
      return false;
      }






      javascript ember.js






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 16 '18 at 12:20









      noobdevnoobdev

      666




      666
























          1 Answer
          1






          active

          oldest

          votes


















          1














          My recommendation would be to share the same property via a service and to use this service to update local storage and cache the value on said service. I've provided an example that uses a service to share a value amongst two components (I couldn't use local storage in the twiddle).



          So let's assume we want to show a list of programming languages either as a table or as an ordered list. We have two components, the reusable mode-changer button for toggling the mode and the programming-languages component for actually rendering the list, who both interact with the shared mode-service.:



          export default Ember.Service.extend({
          init(){
          this._super(...arguments);
          //actually read from local storage here and set default on null
          this.set('mode', 'list');
          },
          toggleMode(){
          let newValue = this.get('mode') === 'list' ? 'table' : 'list';
          //actually store to local storage here before caching on the service
          this.set('mode', newValue);
          }
          });


          Imagine this template showing both components:



          {{programming-languages languages=languages}}
          {{mode-changer}}


          The mode-changer injects the mode-service, with which it derives the logical button text and toggle the mode-service's mode property via toggleMode:



          export default Ember.Component.extend({
          modeService: inject(),
          buttonText: computed('modeService.mode', function(){
          let mode = this.get('modeService.mode');
          return mode === 'list' ? "Change to table" : "Change to list";
          }),
          actions: {
          toggleMode(){
          let modeService = this.get('modeService');
          modeService.toggleMode();
          }
          }
          });


          component of mode-changer:



          <button onclick={{action 'toggleMode'}}>{{buttonText}}</button>


          The programming-languages component bases it's rendering mode off of modeService.mode via a computed property:



          export default Ember.Component.extend({
          modeService: inject(),
          renderList: computed('modeService.mode', function(){
          let mode = this.get('modeService.mode');
          return mode === 'list';
          })
          });


          so that changes to the modeService.mode will cause the computed property to invalidate and trigger a render of the component.



          {{#if renderList}}
          <ol>
          {{#each languages as |language|}}
          <li>{{language}}</li>
          {{/each}}
          </ol>
          {{else}}
          <table>
          <th>Language</th>
          {{#each languages as |language|}}
          <tr>{{language}}</tr>
          {{/each}}
          </table>
          {{/if}}


          In Ember, service's are singletons so such sharing is appropriate in many cases. To me, this is much better than any other solution that actually stores/retrieves references to the component itself and invokes its render function.






          share|improve this answer
























          • Love the detailed explanation, thanks!

            – noobdev
            Nov 19 '18 at 5:23











          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%2f53337816%2fre-render-a-component-from-another-component-ember%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









          1














          My recommendation would be to share the same property via a service and to use this service to update local storage and cache the value on said service. I've provided an example that uses a service to share a value amongst two components (I couldn't use local storage in the twiddle).



          So let's assume we want to show a list of programming languages either as a table or as an ordered list. We have two components, the reusable mode-changer button for toggling the mode and the programming-languages component for actually rendering the list, who both interact with the shared mode-service.:



          export default Ember.Service.extend({
          init(){
          this._super(...arguments);
          //actually read from local storage here and set default on null
          this.set('mode', 'list');
          },
          toggleMode(){
          let newValue = this.get('mode') === 'list' ? 'table' : 'list';
          //actually store to local storage here before caching on the service
          this.set('mode', newValue);
          }
          });


          Imagine this template showing both components:



          {{programming-languages languages=languages}}
          {{mode-changer}}


          The mode-changer injects the mode-service, with which it derives the logical button text and toggle the mode-service's mode property via toggleMode:



          export default Ember.Component.extend({
          modeService: inject(),
          buttonText: computed('modeService.mode', function(){
          let mode = this.get('modeService.mode');
          return mode === 'list' ? "Change to table" : "Change to list";
          }),
          actions: {
          toggleMode(){
          let modeService = this.get('modeService');
          modeService.toggleMode();
          }
          }
          });


          component of mode-changer:



          <button onclick={{action 'toggleMode'}}>{{buttonText}}</button>


          The programming-languages component bases it's rendering mode off of modeService.mode via a computed property:



          export default Ember.Component.extend({
          modeService: inject(),
          renderList: computed('modeService.mode', function(){
          let mode = this.get('modeService.mode');
          return mode === 'list';
          })
          });


          so that changes to the modeService.mode will cause the computed property to invalidate and trigger a render of the component.



          {{#if renderList}}
          <ol>
          {{#each languages as |language|}}
          <li>{{language}}</li>
          {{/each}}
          </ol>
          {{else}}
          <table>
          <th>Language</th>
          {{#each languages as |language|}}
          <tr>{{language}}</tr>
          {{/each}}
          </table>
          {{/if}}


          In Ember, service's are singletons so such sharing is appropriate in many cases. To me, this is much better than any other solution that actually stores/retrieves references to the component itself and invokes its render function.






          share|improve this answer
























          • Love the detailed explanation, thanks!

            – noobdev
            Nov 19 '18 at 5:23
















          1














          My recommendation would be to share the same property via a service and to use this service to update local storage and cache the value on said service. I've provided an example that uses a service to share a value amongst two components (I couldn't use local storage in the twiddle).



          So let's assume we want to show a list of programming languages either as a table or as an ordered list. We have two components, the reusable mode-changer button for toggling the mode and the programming-languages component for actually rendering the list, who both interact with the shared mode-service.:



          export default Ember.Service.extend({
          init(){
          this._super(...arguments);
          //actually read from local storage here and set default on null
          this.set('mode', 'list');
          },
          toggleMode(){
          let newValue = this.get('mode') === 'list' ? 'table' : 'list';
          //actually store to local storage here before caching on the service
          this.set('mode', newValue);
          }
          });


          Imagine this template showing both components:



          {{programming-languages languages=languages}}
          {{mode-changer}}


          The mode-changer injects the mode-service, with which it derives the logical button text and toggle the mode-service's mode property via toggleMode:



          export default Ember.Component.extend({
          modeService: inject(),
          buttonText: computed('modeService.mode', function(){
          let mode = this.get('modeService.mode');
          return mode === 'list' ? "Change to table" : "Change to list";
          }),
          actions: {
          toggleMode(){
          let modeService = this.get('modeService');
          modeService.toggleMode();
          }
          }
          });


          component of mode-changer:



          <button onclick={{action 'toggleMode'}}>{{buttonText}}</button>


          The programming-languages component bases it's rendering mode off of modeService.mode via a computed property:



          export default Ember.Component.extend({
          modeService: inject(),
          renderList: computed('modeService.mode', function(){
          let mode = this.get('modeService.mode');
          return mode === 'list';
          })
          });


          so that changes to the modeService.mode will cause the computed property to invalidate and trigger a render of the component.



          {{#if renderList}}
          <ol>
          {{#each languages as |language|}}
          <li>{{language}}</li>
          {{/each}}
          </ol>
          {{else}}
          <table>
          <th>Language</th>
          {{#each languages as |language|}}
          <tr>{{language}}</tr>
          {{/each}}
          </table>
          {{/if}}


          In Ember, service's are singletons so such sharing is appropriate in many cases. To me, this is much better than any other solution that actually stores/retrieves references to the component itself and invokes its render function.






          share|improve this answer
























          • Love the detailed explanation, thanks!

            – noobdev
            Nov 19 '18 at 5:23














          1












          1








          1







          My recommendation would be to share the same property via a service and to use this service to update local storage and cache the value on said service. I've provided an example that uses a service to share a value amongst two components (I couldn't use local storage in the twiddle).



          So let's assume we want to show a list of programming languages either as a table or as an ordered list. We have two components, the reusable mode-changer button for toggling the mode and the programming-languages component for actually rendering the list, who both interact with the shared mode-service.:



          export default Ember.Service.extend({
          init(){
          this._super(...arguments);
          //actually read from local storage here and set default on null
          this.set('mode', 'list');
          },
          toggleMode(){
          let newValue = this.get('mode') === 'list' ? 'table' : 'list';
          //actually store to local storage here before caching on the service
          this.set('mode', newValue);
          }
          });


          Imagine this template showing both components:



          {{programming-languages languages=languages}}
          {{mode-changer}}


          The mode-changer injects the mode-service, with which it derives the logical button text and toggle the mode-service's mode property via toggleMode:



          export default Ember.Component.extend({
          modeService: inject(),
          buttonText: computed('modeService.mode', function(){
          let mode = this.get('modeService.mode');
          return mode === 'list' ? "Change to table" : "Change to list";
          }),
          actions: {
          toggleMode(){
          let modeService = this.get('modeService');
          modeService.toggleMode();
          }
          }
          });


          component of mode-changer:



          <button onclick={{action 'toggleMode'}}>{{buttonText}}</button>


          The programming-languages component bases it's rendering mode off of modeService.mode via a computed property:



          export default Ember.Component.extend({
          modeService: inject(),
          renderList: computed('modeService.mode', function(){
          let mode = this.get('modeService.mode');
          return mode === 'list';
          })
          });


          so that changes to the modeService.mode will cause the computed property to invalidate and trigger a render of the component.



          {{#if renderList}}
          <ol>
          {{#each languages as |language|}}
          <li>{{language}}</li>
          {{/each}}
          </ol>
          {{else}}
          <table>
          <th>Language</th>
          {{#each languages as |language|}}
          <tr>{{language}}</tr>
          {{/each}}
          </table>
          {{/if}}


          In Ember, service's are singletons so such sharing is appropriate in many cases. To me, this is much better than any other solution that actually stores/retrieves references to the component itself and invokes its render function.






          share|improve this answer













          My recommendation would be to share the same property via a service and to use this service to update local storage and cache the value on said service. I've provided an example that uses a service to share a value amongst two components (I couldn't use local storage in the twiddle).



          So let's assume we want to show a list of programming languages either as a table or as an ordered list. We have two components, the reusable mode-changer button for toggling the mode and the programming-languages component for actually rendering the list, who both interact with the shared mode-service.:



          export default Ember.Service.extend({
          init(){
          this._super(...arguments);
          //actually read from local storage here and set default on null
          this.set('mode', 'list');
          },
          toggleMode(){
          let newValue = this.get('mode') === 'list' ? 'table' : 'list';
          //actually store to local storage here before caching on the service
          this.set('mode', newValue);
          }
          });


          Imagine this template showing both components:



          {{programming-languages languages=languages}}
          {{mode-changer}}


          The mode-changer injects the mode-service, with which it derives the logical button text and toggle the mode-service's mode property via toggleMode:



          export default Ember.Component.extend({
          modeService: inject(),
          buttonText: computed('modeService.mode', function(){
          let mode = this.get('modeService.mode');
          return mode === 'list' ? "Change to table" : "Change to list";
          }),
          actions: {
          toggleMode(){
          let modeService = this.get('modeService');
          modeService.toggleMode();
          }
          }
          });


          component of mode-changer:



          <button onclick={{action 'toggleMode'}}>{{buttonText}}</button>


          The programming-languages component bases it's rendering mode off of modeService.mode via a computed property:



          export default Ember.Component.extend({
          modeService: inject(),
          renderList: computed('modeService.mode', function(){
          let mode = this.get('modeService.mode');
          return mode === 'list';
          })
          });


          so that changes to the modeService.mode will cause the computed property to invalidate and trigger a render of the component.



          {{#if renderList}}
          <ol>
          {{#each languages as |language|}}
          <li>{{language}}</li>
          {{/each}}
          </ol>
          {{else}}
          <table>
          <th>Language</th>
          {{#each languages as |language|}}
          <tr>{{language}}</tr>
          {{/each}}
          </table>
          {{/if}}


          In Ember, service's are singletons so such sharing is appropriate in many cases. To me, this is much better than any other solution that actually stores/retrieves references to the component itself and invokes its render function.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Nov 16 '18 at 13:27









          mistahenrymistahenry

          5,66931829




          5,66931829













          • Love the detailed explanation, thanks!

            – noobdev
            Nov 19 '18 at 5:23



















          • Love the detailed explanation, thanks!

            – noobdev
            Nov 19 '18 at 5:23

















          Love the detailed explanation, thanks!

          – noobdev
          Nov 19 '18 at 5:23





          Love the detailed explanation, thanks!

          – noobdev
          Nov 19 '18 at 5:23


















          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.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53337816%2fre-render-a-component-from-another-component-ember%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







          這個網誌中的熱門文章

          Xamarin.form Move up view when keyboard appear

          Post-Redirect-Get with Spring WebFlux and Thymeleaf

          Anylogic : not able to use stopDelay()