Bill Riley
Bill Riley

Reputation: 97

Polymer 2.0 and passing an attribute to children

I'm playing around with Web Components through Polymer 2.0.

The end HTML I want to write looks like this:

<card size="small">
  <card-header>
    // Markup
  </card-header>
  <card-body>
    // Markup
  </card-body>
  <card-footer>
    // Markup
  </card-footer>
</card>

As you can see, I'm passing size to the top level component. I intend to listen to the width of these cards, and reduce the padding on the header, body, and footer, when they get to smaller sizes, basically responsive elements.

What I cannot figure out how to do is get the attribute value of size to pass down to the card-header, card-body, and card-footer polymer declarations.

Here's how I'm defining card:

<link rel="import" href="card-header.html">
  <dom-module id="card">
      <template>
        <style>
          // Style things
        </style>

        <slot></slot>
      </template>
      <script>
    Polymer({
      is: 'card',

      properties: {
        size: {
          type: String,
          value: "medium",
          observer: '_observeSize'
        },
      },

      _observeSize: function () {
        const sizes = {
          tiny: "1em",
          small: "2em",
          medium: "3em",
          large: "6em"
        };

        if (this.size == "tiny") {
          this.customStyle['--padding-x'] = sizes.tiny;
          this.customStyle['--padding-y'] = sizes.tiny;
        } else if (this.size == "small") {
          this.customStyle['--padding-x'] = sizes.small;
          this.customStyle['--padding-y'] = sizes.small;
        } else if (this.size == "medium") {
          this.customStyle['--padding-x'] = sizes.medium;
          this.customStyle['--padding-y'] = sizes.medium;
        } else if (this.size == "large") {
          this.customStyle['--padding-x'] = sizes.large;
          this.customStyle['--padding-y'] = sizes.large;
        } else {
          this.customStyle['--padding-x'] = sizes.medium;
          this.customStyle['--padding-y'] = sizes.medium;
        }

        this.updateStyles();
      },

      _responsiveObserver: function () { 
        // Update this.size based on width of this element.
      }

    });
  </script>
</dom-module>

And here's how I'm defining card-header

<dom-module id="card-header">
  <template>
      <style>
        // Style
      </style>
    <slot></slot>

  </template>

  <script>
    Polymer({
      is: 'card-header',

      properties: {
        size: {
          type: String,
        }
      },

      ready: function () {
        console.log(this.size);
        // console.log(hostValue::size); ???? something like this ????
      }
    });
  </script>
</dom-module>

TL;DR: How do I get the attribute value of a parent node, or pass the value down to the specific child node (card-header or card-body or card-footer) without updating the attributes in the DOM with Polymer?

Upvotes: 1

Views: 944

Answers (1)

Bill Riley
Bill Riley

Reputation: 97

Solution

There's a few ways to solve this, but I realized I was putting what I needed to in the <slot></slot>, so I could do the padding logic at the card level then handle in a CSS variable.

  _observeSize: function () {
    // const and if else blocks still exist, untouched. Since they set the customStyle object on this element...

    var children = this.querySelectorAll('card-header, card-body, card-footer');

    children.forEach(function (child) {
      child.style = this.customStyle;
    });

    this.updateStyles();
  },

Upvotes: 1

Related Questions