crazypeter
crazypeter

Reputation: 1449

Polymer: Wrap <paper-item> in own element

I want to create my own <menu-item> element to remove some boilerplate code. I wrapped <paper-icon-item> in my own element in the following way:

<link rel="import" href="bower_components/polymer/polymer.html">
<link rel="import" href="bower_components/paper-item/paper-icon-item.html">

<dom-module id="menu-item">
  <template>
    <paper-icon-item>
      <iron-icon icon="[[icon]]" item-icon></iron-icon>
      <content></content>
    </paper-icon-item>
  </template>
</dom-module>

<script>
  Polymer({
    is: "menu-item",
    properties: {
      icon: { type: String }
    }
  });
</script>

The problem when using my <menu-item> is, however, that it behaves differently as to writing the template code directly in the HTML file. I suspect that the item is missing some interaction capabilities with the menu to function properly, but I can't figure it out. I tried using behaviors Polymer.IronControlState and Polymer.IronButtonState just like the paper item does, but no luck.

What am I missing to make my <menu-item> behave like a regular <paper-item>?

Upvotes: 2

Views: 414

Answers (1)

Ajinkya
Ajinkya

Reputation: 846

Answer

Following code is largely copied from the paper-icon-item.html.

<link rel="import" href="bower_components/polymer/polymer.html">
<link rel="import" href="bower_components/iron-behaviors/iron-control-state.html">
<link rel="import" href="bower_components/iron-behaviors/iron-button-state.html">
<link rel="import" href="bower_components/iron-flex-layout/iron-flex-layout.html">
<link rel="import" href="bower_components/paper-styles/typography.html">
<link rel="import" href="bower_components/paper-styles/color.html">
<link rel="import" href="bower_components/paper-styles/default-theme.html">
<link rel="import" href="bower_components/paper-item/paper-item-behavior.html">
<link rel="import" href="bower_components/paper-item/paper-item-shared-styles.html">
<link rel="import" href="bower_components/iron-icon/iron-icon.html">
<link rel="import" href="bower_components/iron-icons/iron-icons.html">

<dom-module id="menu-item">
  <template>
    <style include="paper-item-shared-styles"></style>
    <style>
      :host {
        @apply(--layout-horizontal);
        @apply(--layout-center);
        @apply(--paper-font-subhead);

        @apply(--paper-item);
        @apply(--paper-icon-item);
      }

      .content-icon {
        width: var(--paper-item-icon-width, 56px);
        @apply(--layout-horizontal);
        @apply(--layout-center);
      }
    </style>

    <div id="contentIcon" class="content-icon">
      <iron-icon icon="{{ico}}" item-icon></iron-icon>
    </div>
    <content></content>
  </template>

  <script>
    Polymer({
      is: 'menu-item',

      properties: {
        ico: {
          type: String,
          value: "icons:stars"
        }
      },

      behaviors: [
        Polymer.PaperItemBehavior
      ]
    });
  </script>
</dom-module>

On Extending Elements

I think the simplest way of changing the template of an element is by just copying it, modifying the template and its name. This approach is not without problems, it becomes very difficult to keep the new element up to date with changes in the original one. I am really craving for a better solution!.

On Using Behaviors

You should try to avoid consuming both an element and a behavior used by that element at the same time, you might get into trouble. For example the reason your menu-item doesn't look proper is because the paper-item inside it doesn't acquire the attribute focused. The paper-item doesn't acquire that particular attribute is because its parent element menu-item has the focus, menu-item has the focus because both menu-item and paper-item have tabindex="0" set on them. Why do both these elements have it set on them?, it is because of Polymer.IronControlStateBehavior in both of them.

Upvotes: 1

Related Questions