adaliszk
adaliszk

Reputation: 604

CSS Variable trough Polymer (dynamically loaded) elements

I have multiple custom elements in my projects and I have a problem with css variables. In my parent element I have multiple item element with status classes. I want to manipulate the background and border color using that status classes, but I want to define the values in my parent element but somehow it not want to work.

Here my parent element:

<link rel="import" href="app-task.html" />
<dom-module id="app-task-grid">
<template>
    <style>
        :host {
            display: block; position: absolute; left: 0; top: 0; width: 100%; height: 100%;
            overflow:hidden; background: #eee;

            --column-1-width: 80px;
            --column-3-width: 120px;
            --column-4-width: 180px;
            --column-5-width: 220px;
            --column-6-width: 100px;

            --task-background-color: #eee;
            --task-border-color: #ccc;
        }

        :host table.header {
            position: absolute; top: 0; left: 0; width: 100%; height: 40px; background: #DDD;
        }

        :host table.header th {
            letter-spacing: 2px; font-weight: normal; text-transform: uppercase;
            font-size: 80%; border-left: 1px solid #aaa;

            margin: 0; padding: 0 10px;
        }

        :host th.column1 {
            width: var(--column-1-width);
        }

        :host th.column2 {
            text-align: left;
        }

        :host th.column3 {
            width: var(--column-3-width);
        }

        :host th.column4 {
            width: var(--column-4-width);
        }

        :host th.column5 {
            width: var(--column-5-width);
        }

        :host th.column6 {
            width: var(--column-6-width);
            text-align: left;
        }

        :host th.hide, :host td.hide {
            display: none;
        }

        :host th.show, :host td.show {
            display: table-cell;
        }

        :host table.header .scrollbar {
            width: 20px; border-left: none;
            padding: 0;
        }

        :host .items {

            position: absolute; left: 0; top: 40px; right: 0; bottom: 0;
            overflow:hidden; overflow-y: scroll;

            margin: 0; padding: 0;
        }

        :host .items::-webkit-scrollbar {
            width:22px; border-left: 6px solid #ddd;
            background-color:#ddd;
        } 

        :host .items::-webkit-scrollbar-thumb {
            background-color:#aaa;
            border-left: 6px solid #ddd;
            min-height: 80px;
        }

        .waiting {
            --task-background-color: #e9d32c;
            --task-border-color: #b0a030;
        }

        .assigned {
            --task-background-color: #1b7eee;
            --task-border-color: #1357a4;
        }

        .started {
            --task-background-color: #EF6207;
            --task-border-color: #c05d1d;
        }

        .working {
            --task-background-color: #e99c2c;
            --task-border-color: #c48222;
        }

        .aborted {
            --task-background-color: #E34126;
            --task-border-color: #b72d15;
        }
    </style>

    <table class="header">
        <tr>
            <th class="column1"></th>
            <th class="column2">Column#2</th>
            <th class="column3">Column#3</th>
            <th class="column4">Column#4</th>
            <th class="column5">Column#5</th>
            <th class="column6">Column#6</th>
            <th class="scrollbar"></th>
        </tr>
    </table>

    <div class="items">
        <app-task id="task0" class="waiting"></app-task>
    </div>

</template>
<script>
    Polymer({
        is:"app-task-grid",
        loadItems: function()
        {
            let statuses = ['waiting','assigned','started','working','aborted'];
            for(var i = 1; i<=30; i++)
            {
                let itemStatus = statuses[Math.floor(Math.random()*statuses.length)];

                let itemElement = document.createElement('APP-TASK');
                        itemElement.id = 'task'+i;
                        itemElement.classList.add(itemStatus);

                console.debug( itemElement );

                this.querySelector('.items').appendChild( itemElement );
            }
        }
    });
</script>
</dom-module>

My children element:

<dom-module id="app-task">
<template>
    <style>
        :host {
            display: block; margin: 8px 0; padding: 0;
        }

        :host table {
            width: 100%; height: 80px;

            background-color: var(--task-background-color, #fff);

            border-bottom: 5px solid var(--task-background-color, #fff);
            border-top: 5px solid var(--task-background-color, #fff);

            box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.07),
                        0 1px 5px 0 rgba(0, 0, 0, 0.06),
                        0 3px 1px -2px rgba(0, 0, 0, 0.1);
        }

        :host table td {
            border-left: 1px solid var(--task-border-color, #ccc);
            margin: 0; padding: 0 10px;
        }

        :host td.column1 {
            width: var(--column-1-width);
        }

        :host td.column2 {

        }

        :host td.column3 {
            width: var(--column-3-width);
        }

        :host td.column4 {
            width: var(--column-4-width);
        }

        :host td.column5 {
            width: var(--column-5-width);
        }

        :host td.column6 {
            width: var(--column-6-width);
        }
    </style>

    <table>
        <tr>
            <td class="column1">C#1</td>
            <td class="column2">C#2</td>
            <td class="column3">C#3</td>
            <td class="column4">C#4</td>
            <td class="column5">C#5</td>
            <td class="column6">C#6</td>
        </tr>
    </table>

</template>
<script>
    Polymer({
        is:"app-task"
    });
</script>
</dom-module>

I tried already:

but none of them seems working.

If I define the css variables in the :host then it's working, only not working with classes somehow. Where did made a mistake?


UPDATE#1:

Something weird hapening with the style-scope, if I add the "style-scope app-task-grid" to the parent element for the tasks:

<div class="items">
    <div class="style-scope app-task-grid waiting">
        <app-task id="task1"></app-task>
    </div>
</div>

then if I add a normal css rule like a color its applied in the app-task, but the css variables are not.


UPDATE#2:

As it was mention that this template is working, and I tested it and it is, !But id did not mention that the items are created on the fly and appended to the items. I added almost everything from my code on Plunker: http://plnkr.co/edit/b5XW1w3sEOy4UHc0rdWH?p=preview

Sorry about my mislead, I did not know that the problem source was the dynamic load.

Note: I updated the question with more example.


UPDATE#3:

Thanks to @a1626s and @GünterZöchbauer we found the answer:

My initial code was good and worked from the beginning, I defined the questions badly becasue I did not see what was the problem. So if somebody dynamically load elements inside an element must use Polymer.dom api.

Polymer.dom(this.querySelector('.items')).appendCild(itemElement);

Upvotes: 1

Views: 885

Answers (2)

a1626
a1626

Reputation: 2964

I don't see any problem in your initial code. I copied your code and pasted it in plunker

<style>
    :host {
        display: block;
    }

    .waiting {
        --task-background-color: #e9d32c;
        --task-border-color: #b0a030;
    }

    .assigned {
        --task-background-color: #1b7eee;
        --task-border-color: #1357a4;
    }

    .started {
        --task-background-color: #EF6207;
        --task-border-color: #c05d1d;
    }

    .working {
        --task-background-color: #e99c2c;
        --task-border-color: #c48222;
    }

    .aborted {
        --task-background-color: #E34126;
        --task-border-color: #b72d15;
    }
    </style>

    <div class="items">
        <app-task id="task1" class="waiting"></app-task>
        <app-task id="task2" class="waiting"></app-task>
        <app-task id="task3" class="working"></app-task>
        <app-task id="task4" class="working"></app-task>
        <app-task id="task5" class="assigned"></app-task>
        <app-task id="task6" class="aborted"></app-task>
    </div>

and it seemed to be working fine for me.

As for your new problem replace your javascript method with this method and it should work.

{
  let statuses = ['waiting','assigned','started','working','aborted'];
   for(var i = 1; i<=30; i++)
    {
     let itemStatus = statuses[Math.floor(Math.random()*statuses.length)];

     let itemElement = document.createElement('APP-TASK');
     itemElement.id = 'task'+i;
     itemElement.classList.add(itemStatus);

     console.debug( itemElement );


     Polymer.dom(this.$.items).appendChild(itemElement);

    }
    Polymer.dom.flush();
   }

Also, here is the change that i made in your app-task-grid element

<div class="items" id="items"> //added id attribute to the div tag

The problem being the way you are adding child elements they do not get properly inserted into dom tree of the element. Polymer has documentation on how to work with tree of its elements. You can read more about it here

Upvotes: 2

Andrew Bone
Andrew Bone

Reputation: 7291

Remember that the <style> where the CSS variables are set must have is="custom-style" in the tag.

I've thrown together a very crude snippet to show it.

<script src="https://polygit.org/components/webcomponentsjs/webcomponents-lite.min.js"></script>
<link rel="import" href="https://polygit.org/components/polymer/polymer.html">
<dom-module id="app-task">
  <template>
    <style>
      :host {
        display: block;
        height: 80px;
        margin: 5px;
        background-color: var(--task-background-color, #fff);
        border: 1px solid var(--task-border-color, #ccc);
      }
    </style>
    <div>some stuff...</div>
  </template>
  <script>
    Polymer({
      is: 'app-task'
    });
  </script>
</dom-module>

<!-- Beginning of the 'parent element' -->

<style is="custom-style">
  .waiting {
    --task-background-color: #e9d32c;
    --task-border-color: #b0a030;
  }
  .assigned {
    --task-background-color: #1b7eee;
    --task-border-color: #1357a4;
  }
  .started {
    --task-background-color: #EF6207;
    --task-border-color: #c05d1d;
  }
  .working {
    --task-background-color: #e99c2c;
    --task-border-color: #c48222;
  }
  .aborted {
    --task-background-color: #E34126;
    --task-border-color: #b72d15;
  }
</style>
<div class="items">
  <app-task id="task1" class="waiting"></app-task>
  <app-task id="task2" class="waiting"></app-task>
  <app-task id="task3" class="working"></app-task>
  <app-task id="task4" class="working"></app-task>
  <app-task id="task5" class="assigned"></app-task>
  <app-task id="task6" class="aborted"></app-task>
</div>

Another example with it running through several elements

<script src="https://polygit.org/components/webcomponentsjs/webcomponents-lite.min.js"></script>
<link rel="import" href="https://polygit.org/components/polymer/polymer.html">
<dom-module id="app-task">
  <template>
    <style>
      :host {
        display: block;
        height: 80px;
        margin: 5px;
        background-color: var(--task-background-color, #fff);
        border: 1px solid var(--task-border-color, #ccc);
      }
    </style>
    <div>some stuff...</div>
  </template>
  <script>
    Polymer({
      is: 'app-task'
    });
  </script>
</dom-module>

<!-- Beginning of the 'parent element' -->

<dom-module id="app-task-grid">
  <template>
    <!-- normal styles -->
    <style>
      app-task {
        width: 50%;
        margin: 10px auto;
      }
    </style>
    <!-- custom styles -->
    <style is="custom-style">
      .waiting {
        --task-background-color: #e9d32c;
        --task-border-color: #b0a030;
      }
      .assigned {
        --task-background-color: #1b7eee;
        --task-border-color: #1357a4;
      }
      .started {
        --task-background-color: #EF6207;
        --task-border-color: #c05d1d;
      }
      .working {
        --task-background-color: #e99c2c;
        --task-border-color: #c48222;
      }
      .aborted {
        --task-background-color: #E34126;
        --task-border-color: #b72d15;
      }
    </style>
    <div class="items">
      <app-task id="task1" class="waiting"></app-task>
      <app-task id="task2" class="waiting"></app-task>
      <app-task id="task3" class="working"></app-task>
      <app-task id="task4" class="working"></app-task>
      <app-task id="task5" class="assigned"></app-task>
      <app-task id="task6" class="aborted"></app-task>
    </div>
  </template>
  <script>
    Polymer({
      is: 'app-task-grid'
    });
  </script>
</dom-module>

<!-- And now pushing it to the screen -->

<app-task-grid></app-task-grid>

Upvotes: 0

Related Questions