Polymer 1.0 paper-drawer-panel not rendering well with Blaze


#1

Hi,

Related to the icons not loading I have used the ‘WebComponentsReady’ event to delay rendering of the entire template.
This, however creates another issue while rendering

paper-drawer-panel
        paper-header-panel(drawer)

See her for the code without the WebComponentsReady Defer:

<paper-drawer-panel style="touch-action: auto;" class="x-scope paper-drawer-panel-0">
   <iron-media-query id="mq" class="style-scope paper-drawer-panel">
   </iron-media-query>
   <iron-selector attr-for-selected="id" activate-event="" class="left-drawer transition style-scope paper-drawer-panel">
      <div id="main" class="style-scope paper-drawer-panel" style="left:256px;right:;">
         <div id="scrim" class="style-scope paper-drawer-panel"></div>
      </div>
      <div id="drawer" class="style-scope paper-drawer-panel" style="width:256px;">
         <paper-header-panel drawer="" mode="standard" class="x-scope paper-header-panel-0">
            <paper-toolbar class="has-shadow x-scope paper-toolbar-0" role="toolbar">
               <div id="topBar" class="center horizontal layout toolbar-tools style-scope paper-toolbar">
                  <div>Application</div>
               </div>
               <div id="middleBar" class="center horizontal layout toolbar-tools style-scope paper-toolbar">
               </div>
               <div id="bottomBar" class="center horizontal layout toolbar-tools style-scope paper-toolbar">
               </div>
            </paper-toolbar>
            <div id="mainContainer" class="flex style-scope paper-header-panel">
               <paper-input id="searchInput" label="Search" class="x-scope paper-input-0">
                  <paper-input-container class="style-scope paper-input x-scope paper-input-container-0">
                     <span>
                     </span>
                     <div class="floated-label-placeholder style-scope paper-input-container">&nbsp;</div>
                     <span>
                     </span>
                     <template is="dom-if" class="style-scope paper-input-container"></template>
                     <div class="input-content style-scope paper-input-container">
                        <label class="style-scope paper-input" id="paper-input-label-16">Search</label><input is="iron-input" id="input" class="style-scope paper-input" autocomplete="off" placeholder="" aria-describedby="" aria-labelledby="paper-input-label-16">
                        <template is="dom-if" class="style-scope paper-input"></template>
                        <template is="dom-if" class="style-scope paper-input"></template>
                     </div>
                     <div class="underline style-scope paper-input-container">
                        <div class="unfocused-line fit style-scope paper-input-container"></div>
                        <div class="focused-line fit style-scope paper-input-container"></div>
                     </div>
                     <div class="add-on-content style-scope paper-input-container">
                     </div>
                  </paper-input-container>
               </paper-input>
               <div>
                  <paper-menu role="menu" tabindex="0" class="x-scope paper-menu-0">
                     <div class="content style-scope paper-menu">
                        <paper-item role="listitem" class="x-scope paper-item-0">
                           <iron-icon icon="inbox" item-icon="" class="x-scope iron-icon-0">
                              <iron-meta id="meta" type="iconset" class="style-scope iron-icon"></iron-meta>
                           </iron-icon>
                           Inbox
                        </paper-item>
                     </div>
                  </paper-menu>
               </div>
            </div>
         </paper-header-panel>
      </div>
   </iron-selector>
</paper-drawer-panel>

Note that the is within the container DIV#drawer.

When I run with deferred option the paper-header-panel is NOT rendered within the Drawer div:

<paper-drawer-panel style="touch-action: auto;" class="x-scope paper-drawer-panel-0">
   <iron-media-query id="mq" class="style-scope paper-drawer-panel">
   </iron-media-query>
   <iron-selector attr-for-selected="id" activate-event="" class="left-drawer transition style-scope paper-drawer-panel">
      <div id="main" class="style-scope paper-drawer-panel" style="left:256px;right:;">
         <div id="scrim" class="style-scope paper-drawer-panel"></div>
      </div>
      <div id="drawer" class="style-scope paper-drawer-panel" style="width:256px;">
      </div>
   </iron-selector>
   <paper-header-panel mode="standard" class="has-shadow x-scope paper-header-panel-0" drawer="">
      <div id="mainContainer" class="flex style-scope paper-header-panel">
      </div>
      <paper-toolbar role="toolbar" class="x-scope paper-toolbar-0">
         <div id="topBar" class="center horizontal layout toolbar-tools style-scope paper-toolbar">
         </div>
         <div id="middleBar" class="center horizontal layout toolbar-tools style-scope paper-toolbar">
         </div>
         <div id="bottomBar" class="center horizontal layout toolbar-tools style-scope paper-toolbar">
         </div>
         <div>Application</div>
      </paper-toolbar>
      <paper-input id="searchInput" label="Search a podcast" class="x-scope paper-input-0">
         <paper-input-container class="style-scope paper-input x-scope paper-input-container-0">
            <span>
            </span>
            <div class="floated-label-placeholder style-scope paper-input-container">&nbsp;</div>
            <span>
            </span>
            <template is="dom-if" class="style-scope paper-input-container"></template>
            <div class="input-content style-scope paper-input-container">
               <label class="style-scope paper-input" id="paper-input-label-387">Search a podcast</label><input is="iron-input" id="input" class="style-scope paper-input" autocomplete="off" placeholder="" aria-describedby="" aria-labelledby="paper-input-label-387">
               <template is="dom-if" class="style-scope paper-input"></template>
               <template is="dom-if" class="style-scope paper-input"></template>
            </div>
            <div class="underline style-scope paper-input-container">
               <div class="unfocused-line fit style-scope paper-input-container"></div>
               <div class="focused-line fit style-scope paper-input-container"></div>
            </div>
            <div class="add-on-content style-scope paper-input-container">
            </div>
         </paper-input-container>
      </paper-input>
      <div>
         <paper-menu role="menu" tabindex="0" class="x-scope paper-menu-0">
            <div class="content style-scope paper-menu">
            </div>
            <paper-item role="listitem" class="x-scope paper-item-0">
               <iron-icon icon="inbox" item-icon="" class="x-scope iron-icon-0">
                  <svg viewBox="0 0 24 24" preserveAspectRatio="xMidYMid meet" class="style-scope iron-icon" style="pointer-events: none; display: block; width: 100%; height: 100%;">
                     <g class="style-scope iron-icon">
                        <path d="M19 3H4.99c-1.1 0-1.98.9-1.98 2L3 19c0 1.1.89 2 1.99 2H19c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 12h-4c0 1.66-1.34 3-3 3s-3-1.34-3-3H4.99V5H19v10zm-3-5h-2V7h-4v3H8l4 4 4-4z" class="style-scope iron-icon"></path>
                     </g>
                  </svg>
                  <iron-meta id="meta" type="iconset" class="style-scope iron-icon"></iron-meta>
               </iron-icon>
               Inbox
            </paper-item>
         </paper-menu>
      </div>
   </paper-header-panel>
</paper-drawer-panel>

I am not sure where the issue lies. Blaze makes the Polymer function break that moves child elements in their wrappers.

Ideally I would not use the WebComponentsReady because the icon issue, but now it is one issue or another.

Can anybody verify this issue?

The WebCOmponentsReady deffered can be done like this: https://github.com/loneleeandroo/meteor-polymerize/blob/master/polymerize-client.coffee

screenshots of the rendering issue; Polymer 1.0 and iron router or flow router


#2

Yes, I’m getting same issues and with <paper-toolbar> and even with <paper-button>
Content is not in topBar as it should, but placed on same level with it.


Same goes to paper-button and paper-material inside of it.
I have to remove paper-material inside button ( no shadows ) to make it work.


#3

Please dont copy that practise with words defer, it is not defering, it is re-rendering.
So you try to insert something into already active polymer component and when Blaze optimized DOM handling fight with Polymer shadow DOM, no one wins, ever.

If you really want to defer, do not render a piece of Polymer till WebComponentsReady was thrown.
So the reactive variable is nice there, but default operation in Template should be to not render till it is true. So wrap whole Polymer part in {{#if isPolymerReady… or however you want to name your handler.

And then let us know the results.


#4

I was trying to use {{#if webComponentsReady with polymer with no help. Since using iron-router it rerender single page, but webComponentsReady called once. Router.go(‘anypage’) and Router.go(‘home’) page not rendered, just displayed white screen.


#5

Tested, working as a charm

<head>
  <title>Poly test</title>
  <script src="/components/webcomponentsjs/webcomponents.min.js"></script>
  <link rel="import" href="/components/iron-icons/iron-icons.html">
  <link rel="import" href="/components/iron-icon/iron-icon.html">
  <link rel="import" href="/components/paper-item/paper-icon-item.html">
  <link rel="import" href="/components/paper-item/paper-item.html">
</head>

<body>
  {{> hello}}
</body>

<template name="hello">
    <h4>Polymer test</h4>
      {{#if polymerReady}}
        <paper-icon-item>
          <iron-icon icon="inbox" item-icon></iron-icon> Inbox
        </paper-icon-item>
        <paper-icon-item>
          <iron-icon icon="send" item-icon></iron-icon> Outbox
        </paper-icon-item>
        <paper-icon-item>
          <iron-icon icon="delete" item-icon></iron-icon> Trash
        </paper-icon-item>
        <paper-icon-item>
          <iron-icon icon="report" item-icon></iron-icon> Spam
        </paper-icon-item>
        {{else}}
          Still loading
        {{/if}}
</template>

And JS

if (Meteor.isClient) {
  Session.set('isPolyRdy', false);

  Template.hello.helpers({
    polymerReady: function() {return Session.get('isPolyRdy');}
  });
  window.addEventListener( 'WebComponentsReady' , function() {
      Session.set('isPolyRdy', true);
  });
}

So please stop complaining about not working frameworks.


#6

You can’t expect me to put Ready helpers everywhere to display Icons for Chrome only.
That doesn’t make sense.


#7

I thought we actually replaced the Blaze render function on startup with a function that called the reference of it when webComponentsReady.
Of course I am not entirely sure if Meteor.startup really runs as first in line.
And the breaking of the scaffolds like paper-drawer etc points out that it Polymer does seem to load before and Blaze messes up the rendering.

Wrapping up the icons worked, but when you wrap up paper-drawer-panel with the drawer and main structure, it still breaks.


#8

or you can try to bend iron-router’s waitOn function

but that still just solve load, not that re-rendering various parts later touching polymer element content which should be left alone :smiley:
good night from Europe


#9

I’ve got the same problem. I think it happens when you render dom inside of a polymer element using blaze.

If WebComponentsReady has not fired, the dom is rendered normally, then when it triggers, the polymer element initializes appropriately.

If WebComponenetsReady has fired, it seems like the polymer element initializes without the inner dom. This causes the initialization to fail. Afterward, Blaze inserts the html, but it is not done correctly because Polymer now has the Polymer.dom to do it. This causes things to render incorrectly.

I haven’t yet found a solution to this, but I think one of the following approaches might work.

  • Get Blaze to use the Polymer.dom function to do the insert
  • Use the render event that Blaze triggers to call Polymer’s distributeContent function to have polymer reinitialize
  • Somehow delay polymer’s initialization? (maybe use the render function to change the tag type…? though thats messy)

Let me know what you think


#10

Kind off…I did not add any Blaze templating to my example. Just printing a scaffold of Polymer elements (paper-drawer, paper-panel etc) within a Blaze template.
But no special Spacebars stuff inside.
It just goes awry…or even better said" it creates a kerfuffle"


#11

So, if you enable shadow dom as the default:

window.Polymer = window.Polymer || {};
window.Polymer.dom = 'shadow';

it works in chrome…but not anything else (except opera)


#12

You’re not using iron:router. It’s fake example. It works on single page, once you load it, but when you navigate anywhere, on other template, that contains complex paper element which template have <content> selector, it breaks.


#13

Router / no router, I dont see difference.
You should not manipulate with <content></content> after it is rendered.
There is API in Polymer to interact between elements and such.

So in case of scaffold, break it to few elements and wire them together using blaze, or render it as 1 big element and use polymer to do logic.


#14

Try it yourself GITHUB: PolymerTest with iron:router, 2 pages with paper-drawer-panel


#15

First time page rendered, it calls logged as
Template.name.rendered
paper-drawer-panel created
paper-drawer-panel ready
paper-drawer-panel attached

Using Route.go() to switch page, we got wrong order:
paper-drawer-panel created
paper-drawer-panel ready
paper-drawer-panel attached
Template.name.rendered

Polymer calls create/ready/attached in process of Blaze._materializeDOM and Template is not yet rendered, so <content> not found. And after paper-drawer-panel attached to DOM, Template content added on same level of DOM.

Blaze.Polymer.created (paper-drawer-panel.html:374)
Polymer.Base._addFeature._invokeBehavior (polymer-micro.html:283)
Polymer.Base._addFeature._doBehavior (polymer-micro.html:278)
Polymer.Base.createdCallback (polymer-micro.html:108)
materializeTag (materializer.js:99)
materializeDOMInner (materializer.js:54)
Blaze._materializeDOM (materializer.js:33)
doMaterialize (view.js:343)
Tracker.nonreactive (tracker.js:560)
doRender (view.js:341)
(anonymous function) (view.js:191)
Template._withTemplateInstanceFunc (template.js:437)
(anonymous function) (view.js:190)
Blaze._withCurrentView (view.js:523)
DynamicTemplate:materialize (view.js:189)
Tracker.Computation._compute (tracker.js:294)
Tracker.Computation._recompute (tracker.js:313)
Tracker._runFlush (tracker.js:452)
onGlobalMessage (setimmediate.js:102)


#16

I dont have time to look into it now, but I fast checked Google Map element and it is using Mutation Observer to react on DOM changes. But I was using it only in 0.5, mby it does not work so well now.


#18

It is deferring. The Blaze.Render function is moved inside a Tracker.autorun. The render function is only called if WebComponentsReady has been fired. So when Tracker.autorun runs for the first time, nothing happens. When WebComponentsReady is fired, the reactive-var changes, Tracker.autorun runs again and then the render function is called for the first time.


#19

You can see the fix I made here to make Polymer work correctly when Blaze re-renders: Polymer 1.0 and iron router or flow router