0

I'm trying to retrieve properties on various elements within a text that is loaded through inner-h-t-m-l but I fail to get just one specific element.

Here is my code:

<template>

<iron-ajax
      auto
      url="[[some/path/url.html]]"
      handle-as="text"
      last-response="{{inputText}}"></iron-ajax>

<div class="textcontent" inner-h-t-m-l="{{inputText}}"></div>
</template>
<script>
    Polymer({
      is: 'text-page',

      ready: function() {
        var test = document.getElementsByClassName("author");
        console.log(test);
      }
    });
</script>

So I have two questions about this:

  1. Is this the best way to load an html page into a Polymer element?
  2. The output of the console.log is an array that looks like this:
HTMLCollection[0]
0: span.author
1: span.author
2: span.author
length: 3
__proto__: HTMLCollection

This is correct, there are 3 elements with class-name "author". But when I do the same thing with console.log(test[0]) in order to get just the first one, I get "undefined" as output. How do I get just the first one, and more importantly, the value of that span?

Vims
  • 157
  • 1
  • 8

1 Answers1

1
  1. Yes, personally I think this is the best way to load HTML into a Polymer element unless you can use HTML import as normal way to do this.

  2. With getElementsByClassName You are getting an HTML collection and you can't access directly the value of these elements. You can use different methods to get it as an array like Array.from or a for...of loop. Another solution could be getting them as an Array with the simple this.querySelectorAll().

Clarification here (StackOverflow answer) and here (Medium article).

const html = `<span class="author">test</span><span class="author">another</span>`
addEventListener('WebComponentsReady', function() {

  Polymer({
    is: 'x-example',
    properties: {
      html: {
        type: String,
        value: html
      }
    },

    ready: function() {
      // 1° solution
      const test = this.getElementsByClassName('author');
      const first = Array.from(test)[0];
      console.log('First element innerText --->', first.innerText);

      // Or you can simply loop on the array
      Array.from(test).forEach(item => console.log(item.innerText));

      // 2° solution
      const test2 = this.querySelectorAll('.author');
      test2.forEach(item => console.log(item.innerText));
    }
  });
});
body {
  font-family: sans-serif;
}
<base href="https://polygit.org/components/">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link href="polymer/polymer.html" rel="import">

<dom-module id="x-example">
  <template>
    <style>
      :host {
        display: block;
      }
    </style>

    <h1>polyfiddle</h1>
    <div inner-H-T-M-L="[[html]]">
    </div>
  </template>
</dom-module>

<x-example></x-example>
LasaleFamine
  • 613
  • 6
  • 12
  • If I use `Array.from` it gives me back an empty array. If I do `console.log(test.length)` in the above code it also give me back `0`. – Vims Apr 27 '17 at 08:23
  • Here is a working example (though without `iron-ajax`), open up the console to see the results: https://jsfiddle.net/uq34vk2z/ – LasaleFamine Apr 27 '17 at 08:54
  • Thank you! This worked without the iron-ajax but when I added the iron-ajax if failed. After some searching I found that it must be because the function is called before the text is loaded so `first` was `undefined`. So I added an `if (first !== undefined)` and then it worked just fine. – Vims Apr 28 '17 at 06:10
  • I spoke too soon. Looking a bit further I noticed that it did not get the information from the imported HTML file but from a child-element. When I removed that, it again gives first as undefined. – Vims Apr 28 '17 at 06:53
  • 1
    Yeah, the problem seems to be that you are not waiting for the element to be attached. You can use an observer for this. Here is a working example with the observer: http://jsfiddle.net/6t64j81d/. I'm emulating the `iron-ajax` with the `ready` callback of the Polymer lifecycle. I hope it helps! – LasaleFamine Apr 28 '17 at 16:07