1

How do I get the value of a DOM element from an encapsulated JavaScript object? This does not work. I get nothing as in undefined. I thought the page wasn't rendering and thus couldn't be seen, but I put it in the .ready function and I continue to get undefined.

$(document).ready(function() {
  GetLoans = {
    myModal: function() {
      return document.querySelector("#myModal")
    },
    myModalBody: function() {
      return document.querySelector(".modal-body")
    },
    getNewLoans: function() {
      var xhr;
      xhr = new XMLHttpRequest();
      var url = "/api/books";
      xhr.open("GET", url, true);
      xhr.responseType = 'json';
      xhr.send(null); //or your data
      xhr.onreadystatechange = function() {
          if (xhr.readyState == 4 && (xhr.status == 200)) {
            var result = xhr.response;
            for (var key in result) {
              if (result.hasOwnProperty(key)) {
                //console.log(result[key].patron_id);
                this.myModalBody.innerHTML = result[key].patron_id;
              }
            }
          }
        }
        // var serverResponse = xhr.responseText;
        // this.myModalBody.innerHTML = serverResponse;
    },
    bindUIActions: function() {
      // this.myModalBody.addEventListener("click", this.getNewLoans(), false);

    },
    init: function() {
      this.getNewLoans();
      //this.bindUIActions();

    }
  };
  GetLoans.init();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!-- Modal -->
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
  <div class="modal-dialog" role="document">
    <div class="modal-content">
      <div class="modal-header">
        <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span>
        </button>
        <h4 class="modal-title" id="myModalLabel">Modal title</h4>
      </div>
      <div class="modal-body">
        ...
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
        <button type="button" class="btn btn-primary">Save changes</button>
      </div>
    </div>
  </div>
</div>
Uncaught TypeError: Cannot set property 'innerHTML' of undefined
    at XMLHttpRequest.xhr.onreadystatechange

No jQuery please (yes, I know I am using the Document.Ready function.)

Barmar
  • 741,623
  • 53
  • 500
  • 612
johnny
  • 19,272
  • 52
  • 157
  • 259
  • You do it exactly as without any modules?! – Bergi Feb 07 '17 at 22:31
  • Notice that `myModalBody` is a method of your module, but you are not calling it. – Bergi Feb 07 '17 at 22:34
  • 1
    `this.myModalBody.addEventListener("click", this.getNewLoans(), false);` should be `this.myModalBody.addEventListener("click", this.getNewLoans.bind(this), false);` – Barmar Feb 07 '17 at 22:42

1 Answers1

1

First, the this object that you are referencing is not bound to your module correctly. Remove the reference to this from your invocations because the functions where you are using it are in the same scope as the functions that they need to access.

You do have module methods to get DOM references:

myModalBody: function() {
  return document.querySelector(".modal-body")
}

myModal: function() {
  return document.querySelector("#myModal")
}

But, you are not actually invoking these methods when you write:

this.myModalBody.innerHTML = result[key].patron_id;

You need to write:

myModalBody().innerHTML = result[key].patron_id;

So that the function gets invoked and the return value of the function is used.

Without the invocation parenthesis, you are looking for a property of the myModalBody function/object called innerHTML that doesn't exist.

Also, in your event wiring code, you have:

 this.myModalBody.addEventListener("click", this.getNewLoans(), false);

Which should not include the parenthesis because it will invoke the method immediately causing the event handler to be the result of the AJAX call (which is most-likely not a function, right?). Try:

 myModalBody.addEventListener("click", getNewLoans, false);

$(document).ready(function() {
  GetLoans = {
    myModal: function() {
      return document.querySelector("#myModal")
    },
    myModalBody: function() {
      return document.querySelector(".modal-body")
    },
    getNewLoans: function() {
      var xhr;
      xhr = new XMLHttpRequest();
      var url = "/api/books";
      xhr.open("GET", url, true);
      xhr.responseType = 'json';
      xhr.send(null); //or your data
      xhr.onreadystatechange = function() {
          if (xhr.readyState == 4 && (xhr.status == 200)) {
            var result = xhr.response;
            for (var key in result) {
              if (result.hasOwnProperty(key)) {
                //console.log(result[key].patron_id);
                myModalBody().innerHTML = result[key].patron_id;
              }
            }
          }
        }
        var serverResponse = xhr.responseText;
        myModalBody().innerHTML = serverResponse;
    },
    bindUIActions: function() {
      myModalBody().addEventListener("click", getNewLoans, false);

    },
    init: function() {
      this.getNewLoans();
      //this.bindUIActions();

    }
  };
  GetLoans.init();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!-- Modal -->
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
  <div class="modal-dialog" role="document">
    <div class="modal-content">
      <div class="modal-header">
        <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span>
        </button>
        <h4 class="modal-title" id="myModalLabel">Modal title</h4>
      </div>
      <div class="modal-body">
        ...
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
        <button type="button" class="btn btn-primary">Save changes</button>
      </div>
    </div>
  </div>
</div>
Scott Marcus
  • 64,069
  • 6
  • 49
  • 71