SpartaSixZero
SpartaSixZero

Reputation: 2431

Can't find element using UI hash in Marionette Layout

I'm not sure why I can't get the button element using my UI hash. This is what my Layout looks like:

Layout: App.Base.Objects.BaseLayout.extend({

   // Rest of the code left out for brevity
   ui: {
      btnSave: "#btnSave"
   },

   events: {
      "click @ui.btnSave": "onSave"
   },

   onInitialize: function () {
        this.listenTo(App.vent, "DisableSaveButton", function(val) {
            this.disableSaveButton(val);
        },this);
   },

   disableSaveButton: function () {
        this.ui.btnSave.prop("disabled",val).toggleClass("ui-state-disabled",val);
   },

   onSave: function () {
        alert("saved!");
   } 
})

In VS2013, when my breakpoint hits the line inside disableSaveButton method, I entered $("#btnSave") into the Watch window and I was able to get the element back. I could tell because it had a length of 1. From this, I know the button is rendered. However, if I enter this.ui.btnSave into the Watch window, I would get an element with length of 0.

My BaseLayout object is basically a custom object extended from Marionette.Layout

Marionette version: 1.8.8

Any ideas why I can't find the button element using this.ui.btnSave?

Thanks in advance!

Upvotes: 4

Views: 960

Answers (1)

SpartaSixZero
SpartaSixZero

Reputation: 2431

Got some help from a coworker and the issue might be because the element is out of scope. Basically, inside the Layout object, 'this' does not contain the element. We were able replace 'this.ui.btnSave' with '$("#btnSave",this.buttonset.el)' and that works fine. buttonset is the region that actually contains the html element.

This seems like an inconsistency because even though the ui hash didn't work, the click event utilizing the ui hash did work.

UPDATE 6/3/2015: Another coworker of mine provided a better solution. Basically, in my Layout I use a display function to display my view. It looks something like this:

 Layout: App.Base.Objects.BaseLayout.extend({
      // Rest of the code left out for brevity
      display: function() {
           $(this.buttonset.el).html(_.template($("#buttonset-view").html(), {"viewType": viewType}));
      }
 })

Basically, I'm saying to set the html of my region, which is this.buttonset.el, to my template's html. As of now, my layout doesn't know any of the elements inside the region. It just contains a region which displays the elements. So there is some sort of disconnect between my layout and the elements in my region.

The correct solution, as opposed to my earlier workaround, is to simply add the following line of code at the end:

this.bindUIElements();

From Marionette Annotated Source:

This method binds the elements specified in the “ui” hash inside the view’s code with the associated jQuery selectors.

So this final code looks like this:

Layout: App.Base.Objects.BaseLayout.extend({
          // Rest of the code left out for brevity
          display: function() {
               $(this.buttonset.el).html(_.template($("#buttonset-view").html(), {"viewType": viewType}));
               this.bindUIElements();
         }
})

With this, I was able to finally able to retrieve my element using this.ui.btnSave.

Upvotes: 3

Related Questions