4

I'm trying to learn Polymer 2.0 but am stuck with the problem of getting an element from a different Shadow Dom. This worked in Polymer 1 but no longer in Polymer 2.0. What is the correct way of writing this? It just tells me that the targetText = Null.

Thanks for your help!

This is a MWE: Polymer WC 1:

<dom-module id="sc-navdrawer">
<template>
<style is="custom-style">
p {
  font-weight: bold;
}
.changed {
  color: red;
}
</style>
<p>Some text in normal p tag</p>
<div id="test" class="htmltextcontent" inner-h-t-m-l="{{inputText}}"></div>
</template>

<script>
    Polymer({
        is: 'sc-navdrawer',
        properties: {
          inputText: {
            type: String,
            value: "<p>Some innerhtml text in p tags</p>"
          }
        }
    });

</script>
</dom-module>

Polymer WC 2:

<dom-module id="sc-testpage">
<template>

<button onclick="{{changeColor}}">Click here to change color</button>
</template>

<script>
    Polymer({
        is: 'sc-testpage',
        changeColor: function() {
          var targetText = document.getElementById("test");
          console.log(targetText);
          targetText.classList.add("changed");
        }
    });

</script>
</dom-module>
Vims
  • 157
  • 1
  • 8
  • Are these two Elements in anyway related to each other ? Meaning that they have a child parent relation ? – Niklas Aug 03 '17 at 07:19

3 Answers3

4

Well first thing that I see is you use document.getElementById("test"); and if you say this worked you have used Shady Dom.
Polymer 2 forces you to use Shadow Dom so this command should be replaced by Polymer.dom(this.root).querySelector("#test"). Because Shadow Dom encapsulates your Component you cant access its content with the document Object
But this should not fix your Problem. This Encapsulation means you can´t access the Content of a WebComponent so you cannot access an element with id:xyz from another Component. Have a look at these links they will explain to you how shadowDom works:
1. https://www.html5rocks.com/en/tutorials/webcomponents/shadowdom/
2. https://developer.mozilla.org/en-US/docs/Web/Web_Components/Shadow_DOM
3. https://glazkov.com/2011/01/14/what-the-heck-is-shadow-dom/

Pascal L.
  • 1,261
  • 9
  • 21
  • 1
    Thanks. Yes, this is indeed the problem. Thanks for the links; I will read through them. I also noticed that I cannot access the element from within the same WC either. – Vims Aug 03 '17 at 12:22
  • Thanks. You put me on the right track. I still have to get used to this but I got it working! – Vims Aug 03 '17 at 15:53
  • Awesome Polymer is strange at the very beginning but it becomes very powerful once you fully understand it ;-) – Pascal L. Aug 03 '17 at 16:39
0
  1. Instead of using getElementById you should be using Automatic node finding This works if your two Elements have a child parent relation to each other.
  2. I also believe instead of using a onclick on your button in WC 2, you should be using a on-tap. This is the recommended way in the Polymer documentation.

  3. Further on, I do not really understand why you are using two way data binding on your onclick attribute. I might be missing something but your code should work perfectly fine with a normal function call.

    <dom-module id="sc-testpage">
       <template>
         <button on-tap="changeColor">Click here to change color</button>
       </template>
    
       <script>
         Polymer({
           is: 'sc-testpage',
    
           changeColor: function() {
             var targetText = this.$.sc-navdrawer.$.test;
             console.log(targetText);
             targetText.classList.add("changed");
           }
         });
    
        </script>
    </dom-module>
    
Niklas
  • 1,142
  • 16
  • 33
  • Thank you for your answer. Indeed, 2-way binding is not necessary and also not onclick, but I made a very quick MWE to show the problem. I tried your suggestion but that did not work: not with both elements having the same parent and not with sc-navdrawer being the parent of sc-testpage or visa versa. Besides, I think in your code it would have to say `this.$.scNavdrawer.$.test` instead? In any case, it always returns targetText as Null. I think this is something that has changed in Polymer 2. – Vims Aug 03 '17 at 10:12
  • 1
    Actually Point 1. is wrong at least the part about the child parent thing. This did only work with Polymer 1 and shady dom. – Pascal L. Aug 03 '17 at 16:44
0

Try using paper-input and setting it's value:

<paper-input id="test" label="input" value="{{inputText}}"></paper-input>

Then you can access the variable like this:

var targetText = this.$.inputText;

(this should work with other elements other than paper-input)

tal weissler
  • 177
  • 1
  • 9