Search code examples
vue.jspolymervue-componentpolymer-2.x

Is it possible to pass data from Polymer component to Vue component?


The below code is what I'd like to do but it currently doesn't work. I'm trying to start building Vue components inside my Polymer app as a way to slowly migrate off Polymer.

I've been able to get a Vue component working inside my Polymer app, but I'm stuck on how to pass data from the Polymer component to the Vue component. Ideally, what I'd like to do is pass a Polymer property into the Vue component like I'm doing with testValue below (although the code below doesn't work)

Any pointers are greatly appreciated, thank you!

<dom-module id="part-input-view">
  <template>
    <style include="part-input-view-styles"></style>
    <div id="vueApp">
      <vue-comp id="test" test$="[[testValue]]"></vue-comp>
    </div>
  </template>

  <script>
    class PartInputView extends Polymer.Element {
      static get is() { return 'part-input-view'; }

      constructor() {
        super();
      }

      static get properties() {
        return {
          testValue: 'This is working!'
        };
      }

      ready() {
        super.ready();
        Vue.component('vue-comp', {
          props: ['test'],
          template: '<div class="vue-comp">{{test}}</div>'
        })
        const el = this.shadowRoot.querySelector('#vueApp')
        let vueApp = new Vue({
          el
        });
      }
    }
  </script>
</dom-module>

Solution

  • Yes, it's possible. Your code would've worked had it not been for your [incorrect] property declaration. You should see this error in the console:

    element-mixin.html:122 Uncaught TypeError: Cannot use 'in' operator to search for 'value' in This is working!
        at propertyDefaults (element-mixin.html:122)
        at HTMLElement._initializeProperties (element-mixin.html:565)
        at new PropertiesChanged (properties-changed.html:175)
        at new PropertyAccessors (property-accessors.html:120)
        at new TemplateStamp (template-stamp.html:126)
        at new PropertyEffects (property-effects.html:1199)
        at new PropertiesMixin (properties-mixin.html:120)
        at new PolymerElement (element-mixin.html:517)
        at new PartInputView (part-input-view.html:17)
        at HTMLElement._stampTemplate (template-stamp.html:473)
    

    In Polymer, string properties with a default value can only be declared like this:

    static get properties() {
      return {
        NAME: {
          type: String,
          value: 'My default value'
        }
      }
    }
    

    There is no shorthand for this. You might've confused the shorthand for the uninitialized property, which would be:

    static get properties() {
      return {
        NAME: String
      }
    }
    

    If you fix that bug, you'll notice your code works...

    class PartInputView extends Polymer.Element {
      static get is() { return 'part-input-view'; }
    
      static get properties() {
        return {
          testValue: {
            type: String,
            value: 'This is working!'
          }
        };
      }
    
      ready() {
        super.ready();
        Vue.component('vue-comp', {
          props: ['test'],
          template: '<div class="vue-comp">{{test}}</div>'
        })
        const el = this.shadowRoot.querySelector('#vueApp')
        let vueApp = new Vue({
          el
        });
      }
    }
    
    customElements.define(PartInputView.is, PartInputView)
    <head>
      <script src="https://unpkg.com/[email protected]"></script>
      <base href="https://cdn.rawgit.com/download/polymer-cdn/2.6.0.2/lib/">
      <script src="webcomponentsjs/webcomponents-loader.js"></script>
      <link rel="import" href="polymer/polymer.html">
    </head>
    <body>
      <part-input-view></part-input-view>
    
      <dom-module id="part-input-view">
        <template>
          <style include="part-input-view-styles"></style>
          <div id="vueApp">
            <vue-comp id="test" test$="[[testValue]]"></vue-comp>
          </div>
        </template>
      </dom-module>
    </body>