addEventListener in TVMLKit

I'm experiencing a lot of grief trying to submit a formTemplate and capture the submitted textField value. I'm used to (in Javascript) being able to say "document.getElementById(`:id`)" and adding a function to be called with an event object passed through. Basically what I'd like to do is this:


formDoc.getElementById(`textField`).addEventListener(`change`, function(event) {
     console.log(event.target.value);
});


the formDoc is my .tvml document that's been returned from my XHR request and I know that's working fine because i've got it in the navigation stack. What I can't get working is the binding of the event listener, but I also can't figure out why when I log the formDoc that's been pushed into the navigation stack, it has no children nodes, it just returns an empty IKDOMDocument.


Can someone set me straight? I know this is a bit all over the map...


Thank you

This doesn't answer the question clearly, I am living the same grief, we don't have the access to the full JS features that we use every day, I am even struggling to select a specific item.

As JFoo pointed out you need to access the keyboard feature to be notified of input changes. Based on your code above, here is a working example:


var keyboard = formDoc.getElementById("textField").getFeature("Keyboard");
keyboard.onTextChange = function() { console.log(keyboard.text) }


When a Document is printed to the console it does not print out the entire node tree. You can examine and change the top most document by turning on the Elements tab in WebInspector. You will need to be running the latest seed of El Capitan on your Mac in order to access this tab.

Unfortunately I still can't get to the <textField> element's "keyboard feature" text value. My code below returns this error in Xcode:


ITML <Error>: undefined is not an object (evaluating 'textField.getFeature') - .../js/Presenter.js


The form template:

  <formTemplate>
    <banner>
      <title>Title</title>
    </banner>
    <textField>Placeholder text</textField>
    <footer>
      <button template="${this.BASEURL}templates/ProcessForm.xml.php">
        <text>Button text</text>
      </button>
    </footer>
  </formTemplate>


And Presenter.js unsuccessfuly tries to get to the <textField> element's value:

  if (templateURL && (event.type == "select")) {
      var formTemplate = ele.parentNode.parentNode; // that gives me <formTemplate> element
      var children = formTemplate.childNodes;
      var textField = children[1]; // that should give me <textField> element
      templateURL = templateURL + "?textFieldValue=" + textField.getFeature("Keyboard").text;
      ......


Any ideas please?

You're close.

Once you have a reference to the text field, you need to get its Keyboard feature and use that to get the textfield content:

var keyboard = textField.getFeature("Keyboard");
keyboard.onTextChange = function(){
     templateURL = templateURL + "?textFieldValue=" + keyboard.text;
}

I'm still getting this message.

ITML <Error>: undefined is not an object (evaluating 'textField.getFeature') - .../js/Presenter.js


😟 Not able to get a value of the TextField.

@DozenEggs: Can you please help us understand how to best get a reference to the text field? Right now I'm using this code below in "Presenter.js" to get to the textField once the user clicks the "Done" button in the view with the form & keyboard, but still get "ITML <Error>: undefined is not an object (evaluating 'textField.getFeature') - .../js/Presenter.js" if I use your line of code:


load: function(event) {
        var self = this,
            ele = event.target,
            templateURL = ele.getAttribute("template"),
            presentation = ele.getAttribute("presentation"),
            videoURL = ele.getAttribute("videoURL");


        if (templateURL && (event.type == "select")) {
            var formTemplate = ele.parentNode.parentNode; // that gives me <formTemplate> element
            var children = formTemplate.childNodes;
            var textField = children[1]; // which is the second element in <formTemplate><banner></banner><textField></textField>...
            var keyboard = textField.getFeature("Keyboard"); // your line of code raises the ITML Error...
            ...........................

In your example, the children variable is a nodeList. To access a node at a specific index, you must use the nodelist's item function: https://developer.mozilla.org/en-US/docs/Web/API/NodeList/item

var children = formTemplate.childNodes;
var textField = children.item(1);

You must use the nodeList's item function to access a node at a specific index: https://developer.mozilla.org/en-US/docs/Web/API/NodeList/item

var children = formTemplate.childNodes;
var textField = children.item(1);

@danielalc: I found the solution by looking into accessing elements by traversing XML DOM:


var formTemplate = ele.parentNode.parentNode; // your formTemplate button
var children = formTemplate.childNodes;
var textField = children.item(1); // replace "1" with the index of "textField" element in your template
var keyboard = textField.getFeature("Keyboard"); // get the textField's Keyboard element
var userValue = keyboard.text; // the value entered by the user on the Apple TV keyboard

Well you coud do something like this:

<formTemplate>
    <banner>
      <title>Title</title>
    </banner>
    <textField id="someID">Placeholder text</textField>
    <footer>
      <button template="${this.BASEURL}templates/ProcessForm.xml.php">
        <text>Button text</text>
      </button>
    </footer>
  </formTemplate
var keyboard = formDoc.getElementById("textField").getFeature("Keyboard"); 
keyboard.onTextChange = function() { console.log(keyboard.text) }

You have to define "id" attribute to access by ID

You could simply do:


var textFields = formTemplate.getElementsByTagName('textField')
if (textFields.length > 0) {
  var formTextField = textFields.item(0);
  var keyboard = textField.getFeature("Keyboard");
  ...

};
addEventListener in TVMLKit
 
 
Q