how to dynamically append an element to dom-if in Polymer?
Asked Answered
H

2

4

My goal is to append an element to existing dom-if dynamically. Problem is that after appending I can see appended element in the DOM three but it never reacts on condition and stays always hidden.

<template>
    <template id="domif" is="dom-if" if="[[condition]]" restamp></template>
</template>

ready() {
    var el = document.createElement("input");
    Polymer.dom(this.$.domif).appendChild(el);
    Polymer.dom.flush();
}

Exploring DOM with hardcoded dom-if and input shows that <input /> element is actually not a child of dom-if but lives next to it..

<template>
    <template is="dom-if" if="[[condition]]" restamp>
       <input />
    </template>
</template>

That gave me a clue that I probably should append my element next to dom-if... But now the biggest question is how to say to dom-if that appended element should be rendered if condition is satisfied. Any ideas?

Hickox answered 7/12, 2015 at 15:58 Comment(2)
What about using hidden instead of dom-if?Dogoodism
@Günter Zöchbauer, had thought about it but I need to actually remove it and not just hide. Somehow iron-form validation of some hidden elements fails. I had this issue when used dom-if without restamp flag. Restamp solved the problem.Hickox
K
2

How about adding a span in your dom-if and appending it to that span?

Update after some comments : We need to use this.async for the item to be found. Using the ready-event only works when the condition is true initially. So you could append the element in a conditionChanged-observer - this is a working example :

<dom-module id='my-element1'>
  <template>
    <template is="dom-if" if="[[condition]]" restamp>
      <span id="appendHere"></span>
    </template>
  </template>
</dom-module>

<script>
  Polymer({
    is: 'my-element1',
    properties: {
      condition: {
        type: Boolean,
        observer: "_conditionChanged"
      }
    },
    _conditionChanged: function(newVal) {
      if (newVal) {
        this.async(function() {
          var el = document.createElement("input");
          Polymer.dom(this.$$("#appendHere")).appendChild(el);
          Polymer.dom.flush();
        });
      }
    }
  });
</script>

Try it here : http://plnkr.co/edit/1IIeM3gSjHIIZ5xpZKa1?p=preview .

A side-effect of using dom-if in this case is that after setting the condition to false, the element disappears completely and gets added on the next condition-change again. So every change before setting the condition to false gets lost. You could work around it by putting the added element somewhere hidden when the condition changes and getting it back later, but I don't think this is a good idea, if the following is an alternative :

The Polymer-team recommends using dom-if only if there is no other way, like hiding the element. So, if it is possible you also could do something like this (condition has to be true to hide the element) :

<dom-module id='my-element1'>
  <template>
    <span id="appendHere" hidden$="[[condition]]"></span>
  </template>
</dom-module>

<script>
  Polymer({
    is: 'my-element1',
    properties: {
      condition: Boolean
    },
    ready: function() {
        var el = document.createElement("input");
        Polymer.dom(this.$.appendHere).appendChild(el);
        Polymer.dom.flush();
    }
  });
</script>

Try it here : http://plnkr.co/edit/mCtwqmqtCPaLOUveOqWS?p=preview

Karl answered 7/12, 2015 at 16:4 Comment(6)
It gives an error: Uncaught DOMException: Failed to execute 'appendChild' on 'Node': Only one element on document allowed.Hickox
And I don't know why but i cannot access the span by native document.getElementByID or by this.$.appendHere... probably it sits in shadow domHickox
related question #34139218Hickox
You might be able to use something like this.$$('#appendHere') to find the element. this.$.<someId> only works for nodes that are static within the template, i.e. they're not added by a dom-if/dom-repeat or otherwise dynamically added.Isaacson
this.$$('#appendHere') and document.getElementById('appendHere') couldn't find it inside a ready() function.... Should I use another lifecycle function for that?? func attached() ?Hickox
FYI : I deleted my last 3 comments and updated my answer ;) I will add some plnkr-code there now.Karl
P
0

The template element itself will not be added to the DOM, this is the reason you can't access it using querySelector or getElementXxx

Proceeds answered 7/12, 2015 at 17:32 Comment(2)
does it mean that I can not add element to a dom-if dynamically?Hickox
I think you can only add to content of the dom-if, and only while condition is true. I'm also not sure whether your dynamically added elements are retained when condition is changed to falseDogoodism

© 2022 - 2024 — McMap. All rights reserved.