Let Me Tink About It
Let Me Tink About It

Reputation: 16112

Working demo of state management in Polymer 2.x using Mixins

Here, I'm trying to build a working demo to implement the code contained in this blog article written by @CaptainCodeman — Managing State in Polymer 2.0 - Beyond Parent / Child Binding Share state between separated DOM elements without Redux.

I'm getting the following errors.

run.plnkr.co/:5 GET https://cdn.rawgit.com/download/polymer-cdn/2.0.0/lib/webcomponentsjs/webcomponents-lite.min.js

run.plnkr.co/:1 GET https://polygit.org/polymer+v2.0.0/shadycss+webcomponents+1.0.0/components/my-options.html 500 ()

run.plnkr.co/:1 GET https://polygit.org/polymer+v2.0.0/shadycss+webcomponents+1.0.0/components/shared-styles.html 500 ()

my-view2.html:26
Uncaught ReferenceError:
MyOptionsMixin is not defined at my-view2.html:26

Does anyone have a working demo of this?

my-options.html
<link rel="import" href="../bower_components/polymer/polymer-element.html">
<link rel="import" href="../bower_components/paper-checkbox/paper-checkbox.html">

<dom-module id="my-options">
  <template>
    <style>
      :host {
        display: block;
        padding: 16px;
      }
      h3, p {
        margin: 8px 0;
      }
    </style>
    <h3>Options</h3>
    <p>
      <paper-checkbox checked="{{ options.subscribe }}">Send Notifications</paper-checkbox>
    </p>
  </template>

  <script>
    (function() {

      let optionsInstance = null;

      class MyOptions extends Polymer.Element {
        static get is() { return 'my-options'; }

        static get properties() {
          return {
            options: {
              type: Object,
              value: () => ({
                subscribe: false
              })
            },
            subscribers: {
              type: Array,
              value: () => []
            }
          }
        }

        static get observers() {
          return [
            'optionsChanged(options.*)'
          ]
        }

        constructor() {
          super();

          if (!optionsInstance) optionsInstance = this;
        }

        register(subscriber) {
          this.subscribers.push(subscriber);
          subscriber.options = this.options;
          subscriber.notifyPath('options');
        }

        unregister(subscriber) {
          var i = this.subscribers.indexOf(subscriber);
          if (i > -1) this.subscribers.splice(i, 1)
        }

        optionsChanged(change) {
          for(var i = 0; i < this.subscribers.length; i++) {
            this.subscribers[i].notifyPath(change.path);
          }
        }
      }

      window.customElements.define(MyOptions.is, MyOptions);

      MyOptionsMixin = (superClass) => {
        return class extends superClass {
          static get properties() {
            return {
              options: {
                type: Object
              }
            }
          }

          connectedCallback() {
            super.connectedCallback();
            optionsInstance.register(this);
          }

          disconnectedCallback() {
            super.disconnectedCallback();
            optionsInstance.unregister(this);
          }
        }
      }
    }());
  </script>
</dom-module>
my-view2.html
<link rel="import" href="../bower_components/polymer/polymer-element.html">

<link rel="import" href="my-options.html">
<link rel="import" href="shared-styles.html">

<dom-module id="my-view2">
  <template>
    <style include="shared-styles">
      :host {
        display: block;
        padding: 10px;
      }
    </style>

    <div class="card">
      <div class="circle">2</div>
      <h1>View Two</h1>
      <p>Ea duis bonorum nec, falli paulo aliquid ei eum.</p>
      <p>Id nam odio natum malorum, tibique copiosae expetenda mel ea.Detracto suavitate repudiandae no eum. Id adhuc minim soluta nam.Id nam odio natum malorum, tibique copiosae expetenda mel ea.</p>

      <p>Send notifications option is: <b>[[ options.subscribe ]]</b></p>
    </div>
  </template>

  <script>
    class MyView2 extends MyOptionsMixin(Polymer.Element) {
      static get is() { return 'my-view2'; }
    }

    window.customElements.define(MyView2.is, MyView2);
  </script>
</dom-module>

Edit: Working Demo (accepted answer forked and edited)

Upvotes: 1

Views: 395

Answers (1)

tony19
tony19

Reputation: 138266

working plunker


run.plnkr.co/:5 GET https://cdn.rawgit.com/download/polymer-cdn/2.0.0/lib/webcomponentsjs/webcomponents-lite.min.js

Your <script> tag imports a non-existent file:

https://cdn.rawgit.com/download/polymer-cdn/2.0.0/lib/webcomponentsjs/webcomponents-lite.min.js

I would use the same polygit.org URL that was used in the rest of the Plunker:

https://polygit.org/polymer+v2.0.0/shadycss+webcomponents+1.0.0/components/

Also, the script name no longer includes min. The actual filename is webcomponents-lite.js. The <script> tag should look like this:

<script src="https://polygit.org/polymer+v2.0.0/shadycss+webcomponents+1.0.0/components/webcomponentsjs/webcomponents-lite.js"></script>

run.plnkr.co/:1 GET https://polygit.org/polymer+v2.0.0/shadycss+webcomponents+1.0.0/components/my-options.html 500 ()

run.plnkr.co/:1 GET https://polygit.org/polymer+v2.0.0/shadycss+webcomponents+1.0.0/components/shared-styles.html 500 ()

my-view2.html sets <base href> to polygit.org, and then tries to import my-options.html and shared-styles.html, both of which only exist in the Plunker sandbox:

<!-- my-view2.html -->
<base href="https://polygit.org/polymer+v2.0.0/shadycss+webcomponents+1.0.0/components/">
<link rel="import" href="polymer/polymer-element.html">

<link rel="import" href="my-options.html"> <!-- https://polygit.org/polymer+v2.0.0/shadycss+webcomponents+1.0.0/components/my-options.html -->
<link rel="import" href="shared-styles.html"> <!-- https://polygit.org/polymer+v2.0.0/shadycss+webcomponents+1.0.0/components/shared-styles.html -->

The only file imported here that needs to come from polygit.org is polymer-element.html, so you could remove the <base> tag and move the URL prefix to that import:

<link rel="import" href="https://polygit.org/polymer+v2.0.0/shadycss+webcomponents+1.0.0/components/polymer/polymer-element.html">

my-view2.html:26 Uncaught ReferenceError: MyOptionsMixin is not defined at my-view2.html:26

my-view2 does not declare/instantiate my-options, so the script that defines MyOptionsMixin is never executed. You could resolve this simply by declaring it in my-view2's template:

 <dom-module id="my-view2">
    <template>
      <my-options></my-options>
    </template>
    ...
 </dom-module>

Upvotes: 1

Related Questions