1

I’m having some difficulties when using the data binding system to keep two arrays with a one-to-many relationship in sync.

The basic app idea is that I need to edit photos. Each photo may be present inside many slots.

Objective

Given two array of models: [Photo 1, Photo 2, ...] and [Slot 1, Slot 2, ...].

With the relationship: A Photo belongs to many Slots.

photos = [{id: 1}, {id: 2}, ...]

slots  = [{photoId: 1}, {photoId: 1}, {photoId: 2}, ...]

I want propagate changes from the Photo rendered inside a Slot.

Question

How do i propagate changes from a model (that will be rendered inside a slot and selected by the slot.photoId) to the photo inside the original photos array?

Relevant Code

<template items="{{spread.slots}}" as="slot" is="dom-repeat">
  <paper-input value="binding for photo.width selected from [[slot.photoId]]"> </paper-input>
</template>

Possibilities Considered

  • Change the data model (to which one?)
  • Use array-selector (how?)
  • Manually store and compute association outside binding system (using this solution for now)

The same problem is described in the snippet:

Polymer({
  is: 'demo-element',
  properties: {
    project: {
      type: Object,
      value: () => {
        return {
          photos: [
            {id: 1, src: 'http://lorempixel.com/200/100/cats/1', width: 200 },
            {id: 2, src: 'http://lorempixel.com/200/100/cats/2', width: 100}
          ],
          spreads: [{

            slots: [{
              number: 1,
              photoId: 1
            },{
              number: 2,
              photoId: 1
            }, {
              number: 3,
              photoId: 2
            }]

          }]
        };
      }      
    }
  }
});
<!DOCTYPE html><html><head>
<script src="http://static.jsbin.com/js/vendor/traceur.js"></script>
  <meta charset="utf-8">
  <meta description="Polymer 1.0 Template"> 
  <base href="http://polygit.org/components/">
  <script src="webcomponentsjs/webcomponents-lite.min.js"></script>

  <link rel="import" href="polymer/polymer.html" />
  <link rel="import" href="paper-input/paper-input.html" />
  <link rel="import" href="paper-material/paper-material.html" />
<style> paper-material {padding: 1em;}</style>
</head>
<body>
  
  <demo-element></demo-element>

  <dom-module id="demo-element">
    <template>
      <paper-material>
      <h2>2 Photos</h2>
      <template is="dom-repeat" items="{{project.photos}}" as="photo">
        <span> 
          
          Photo [[photo.id]] 
          <img src$="{{photo.src}}" 
               style="width: [[photo.width]]px;" />
        
        </span>
      
      </template></paper-material>
      <br />
      <paper-material>
      <template items="{{project.spreads}}" as="spread" is="dom-repeat">
        <h2>1 Spread </h2>
        <h4>3 Slots. Photo 1 used twice, Photo 2 used once. Need to edit photo.width!</h4>
        <template items="{{spread.slots}}" as="slot" is="dom-repeat">
          <div>
            <p>
              The slot {{slot.number}} 
              has photoId: {{slot.photoId}} <br /><br />


  How to data bind photo.width for the photo of this slot?
              <paper-input label="binding for width property of photo of slot [[slot.number]] with id [[slot.photoId]]"></paper-input>



            </p>
          </div>

        </template>
      </template></paper-material>

    </template>
  </dom-module>
</body>
</html>
Pickachu
  • 86
  • 2
  • 7
  • Use `{{}}` for two way binding `[[]]` is used for one way binding in Polymer – a1626 Jun 15 '16 at 18:24
  • 1
    If i understand correct your `photo` model will have property `width` and you want to change it using `paper-input`. If that is so then bind `{{photo.width}}` to `value` of `paper-input` – a1626 Jun 15 '16 at 18:28
  • 1
    I think you're missing the association bit here. The photo that i'm currently editing is the one with the id equivalent to the slot.photoId property. I can just use the {{photo.width}} binding to do that, but how do I select the correct photo with the equivalent slot.photoId in first place? – Pickachu Jun 15 '16 at 19:19
  • you can use a js function and pass it `slot.photoId` and return photo from it. something like `[[getPhoto(slot.photoId)]]` – a1626 Jun 15 '16 at 19:32
  • 1
    yep, i have considered this possibility. this would cause it to be a one-way binding, not two way binding, so the user would not be able to edit the photo.width property (like i want in the snippet). Something like `{{getPhoto(slot.photoId).width}}` would do the trick, but i think it does not work and even if it did would be a very underperformant solution :D. – Pickachu Jun 15 '16 at 19:36
  • 2
    Try this have `photoId` or something unique as the id of paper-input and listen to the `changed` event of the paper-input and then update the width based on the value from js – a1626 Jun 15 '16 at 19:44
  • 1
    Yea, i'm currently using a solution like that. A function that monitor all changes in photos and propagates it to the rest of the app. But it's really slow, and im searching for a better solution. Thanks for the fast answers! – Pickachu Jun 15 '16 at 21:35

0 Answers0