3

In Polymer, alone, without combining with Meteor, you can pass an object to a polymer web component by simply passing it to an attribute. I've been successful at doing this. Here we're passing "state" from the iteration directly into the custom polymer web component called state-card.

<template repeat="{{state in states}}">
 <state-card class="state-card" stateObj={{state}}></state-card>
</template>

However, in my project, I am combining Polymer and Meteor.
Polymer's templates and Meteor's blaze templates can't be mixed ... so, this is blaze with just a custom Polymer web component. I could not pass the "state" object in Meteor with blaze #each loop in a meteor template. As a work-a-round I found I could only pass the individual properties as text strings like so ...

<template name="inbox">
    <div class="content" flex>
        {{#each states}}
            <state-card class="state-card" name={{name}} status={{status}} displayType={{displaytype}}></state-card>
        {{/each}}
    </div>
</template>

to accomplish the above, here is a snippet from the custom Polymer web component with an attribute like so ...

<polymer-element name="state-card" attributes="name status displayType" on-click="cardClicked">
    <template>
    ...
    </template>
</polymer-element>

What I "really" want to do is just pass in the object directly to the polymer web component like so ... but, sadly this just won't work

<template name="inbox">
    <div class="content" flex>
        {{#each states}}
            <state-card class="state-card" stateObj={{this}}></state-card>
        {{/each}}
    </div>
</template>

Ideally, I should be able to accept the object with an attribute like so ...

<polymer-element name="state-card" attributes="stateObj" on-click="cardClicked">
    <template>
    ...
 </template>
</polymer-element>

This SO question/answer is "very" similar to my issue, but, the answer didn't work because I have the Meteor blaze template complication ...

Similar SO question/answer

I "really" don't want to stick with my work-a-round ... even though it works.

I've read elsewhere on SO that in a blaze #each iteration you can access the object literal like so ...

{{#each humans}}
  {{this}}
{{/each}}

But, I couldn't make this work. I would be very appreciative of any help and guidance. I understand what I'm trying to do, combine Polymer and Meteor is somewhat problematic, but, I've seen it done and I've made a lot of progress. I'm just stumbling at this point. Thanks!!!

Community
  • 1
  • 1

1 Answers1

4

When setting an attribute on a custom polymer element, polymer attempts to detect the type and and cast the property as such when setting the values on your elements prototype - so numbers are numbers and strings are strings, etc. Things become a little more difficult when you are not setting this attribute from within another polymer element - like trying to set it using blaze (and any other non-polymer engine, I'd imagine).

Polymer ends up running .toString() on your object literal which produces "[object Object]" which is of little use. Luckily, polymer lets you pass objects in as double quoted JSON strings from the outside world, like the result of JSON.stringify(something).

The most straightforward, but not as elegant approach is to create a stringify helper and use it to set the attribute.

Template.registerHelper('stringify', function(obj) {
  return JSON.stringify(obj);
});

{{#each things}}
  <my-component something={{stringify this}}></my-component>
{{/each}}

OR

Template.registerHelper('stringThis', function() {
  return JSON.stringify(this);
});

{{#each things}}
  <my-component something={{stringThis}}></my-component>
{{/each}}

Another option could be to override the toString method at some level in your application. Using meteor's document transforms or the collection-helpers package you could add a toString method that just returns JSON.stringify(this) - if you are iterating over cursors.

It's tough to just override Object.prototype.toString and do the same though. You'll get circular reference errors, but it looks like there are a couple libraries and methods to decycle objects before passing it (this) to JSON.stringify. I haven't tried this, but seems like it would work.

Either way, if the attribute is set to JSON, it will be available as an actual object within your polymer element. You can even setup observers on nested properties within that object!

Bottom line - there doesn't seem to be a perfect way yet, so stringify objects for now. Hope that helps!

Greg Neiheisel
  • 590
  • 4
  • 12
  • UI.registerHelper is old syntax, it's Template.registerHelper now. – Dave Mar 26 '15 at 13:53
  • Thank you Greg so much!!! Reading your response I realize that I had seen "parts" of your answer here and there on other SO posts but did not put the whole concept together as you've done. I got the stringify concept to function. However, inside the custom Polymer element I get the stringified JSON object, but, how do I get it to bind to an HTML element inside the Polymer element. For example, if my Polymer element had the attribute: attributes="stateObj" and the element's template has
    {{stateObj.name}}
    it doesn't seem to get converted to an object. Again, many, many thanks!
    – Chris Russi Mar 26 '15 at 14:28
  • @ChrisRussi try initializing stateObj to an empty object in your element constructor. You can probably use the publish object (rather than declaratively in attributes), or in the created callback. Not positive, but worth a shot – Greg Neiheisel Mar 26 '15 at 15:36
  • @Greg ... Ah right!, I actually did that at one point and then removed it. I know exactly what you're saying. I will try it when I get home this evening. I am so grateful for your responses. I've been working hard to 1) Learn Meteor 2) learn Polymer 3) Combine the two ... it's increases the level of effort indeed. I have a hunch this will do the trick. Thanks Greg! – Chris Russi Mar 26 '15 at 16:44
  • @Greg ... AWESOME! It is functioning now. I added: Polymer('state-card',{ stateObj: {}, ... and that did the trick. I am very grateful to you for your help. Now, I recall where I've seen you ... on the original Differential polymer-demo video ... you guys are amazing. – Chris Russi Mar 27 '15 at 01:49