Search code examples
jqueryember.jsjquery-steps

Emberjs nested components jquery on initialization


I keep running into problems with nested components in EmberJS with component initialization. I am trying to use jquery.steps (http://www.jquery-steps.com/) to create a wizard.

I have a wizard component, and I want to have each step as a component which can have actions to change the view for the wizard step. However, after initializing jquery.steps, the view is not changing in the wizard. It seems that the actions are not being detected either (is it because jquery.steps has a property called actions too?)

I expect the value of {{temp}} to change in the view depending on the radio button that was selected. This works if I do not instantiate $().steps in the parent component, but stops working if I do instantiate jquery.steps. What could be going on here? And how do I get it to work? I tried using Ember.run in various ways to execute loadSteps() to no avail.

wizard.js

import Ember from 'ember';

export default Ember.Component.extend({
  temp: null,

  didInsertElement: function () {
    this._super();
    this.loadSteps();
  },
  loadSteps: function () {
    this.$().steps({
      headerTag: "h3",
      bodyTag: "section",
      transitionEffect: "slideLeft",
      autoFocus: true
    });
  },

  actions: {
    addByHandSelected: function () {
      this.set('temp', true);
    },
    setupSheetSelected: function () {
      this.set('temp', false);
      //TODO: show file input
    },
    removeStep: function (step) {
      this.$().steps("remove", step);
    },
    addStep: function (step) {
      this.$().steps("add", step);
    },
  }
});

wizard.hbs

{{creation-method-wizard-step addByHandSelected='addByHandSelected' setupSheetSelected='setupSheetSelected'}}
{{label-size-wizard-step}}

creation-method-wizard-step.js

import Ember from 'ember';

export default Ember.Component.extend({
  tagName:'',
  temp: true,
  actions: {
    addByHandSelected: function () {
      this.set('temp',false);
    },
    setupSheetSelected: function () {
      this.set('temp',true);
    }
  }
});

creation-method-wizard-step.hbs

<h3>Creation Method</h3>
<section>
<div class="radio">
{{#radio-button  value="hand" name='creationMethod' groupValue=creationMethod changed="addByHandSelected"}}Enter By Hand{{/radio-button}}
</div>
    <div class="radio">
      {{#radio-button value="setupSheet" name='creationMethod' groupValue=creationMethod changed="setupSheetSelected"}}Use Setup
          Sheet{{/radio-button}}
    </div>
    Temp is {{temp}}
</section>

Solution

  • This occurs due to the changes happening to the dom from jquery steps. As a result it breaks the two way binding. One solution could be to send the action to a parent component that is not modified by jquery steps initialization and handles the two way binding of data. Otherwise you will have to manually update the dom. Also here is a similar issue related to refreshing a component using a library that modified the dom structure .

    A rough example of these concepts can be found in the following example,

    https://emberjs.jsbin.com/jegizusowo/1/edit?html,js,output

    js

    App.StepsWizardComponent = Em.Component.extend({
      temp: null,
    
      didInsertElement: function () {
        this._super();
       var self = this;
        Ember.run.scheduleOnce('afterRender', this, function() {
        self.loadSteps();
      });
      },
      loadSteps: function () {
        this.$(".wizard-step").steps({
          headerTag: "h3",
          bodyTag: "section",
          transitionEffect: "slideLeft",
          autoFocus: true
        });
      },
    
      actions: {
        addByHandSelected: function () {
          console.log("addbyhand1");
          this.set('temp', true);
        },
        setupSheetSelected: function () {
          console.log("setupsheet1");
          this.set('temp', false);
          //TODO: show file input
        },
        removeStep: function (step) {
          this.$().steps("remove", step);
        },
        addStep: function (step) {
          this.$().steps("add", step);
        },
      }
    
    });
    
    App.CreationMethodWizardStepComponent = Em.Component.extend({
      classNames:["wizard-step"],
    //   tagName:'',
      temp: true,
      actions: {
        addByHandSelected: function () {
          console.log("addbyhand2");
          console.log(this.get("temp"));
          this.set('temp',false);
          this.$("#temp-val").text(this.get("temp"));
          this.get("parentView").send("addByHandSelected");
        },
        setupSheetSelected: function () {
          console.log("setupsheet2");
          console.log(this.get("temp"));
          this.set('temp',true);
          this.$("#temp-val").text(this.get("temp"));
    
     this.get("parentView").send("setupSheetSelected");
        }
      }
    });