Diëgo
Diëgo

Reputation: 103

No communication between custom Polymer components

I've written a single custom Polymer component that has multiple smaller custom components designed to one specific step of an entire process. The elements are supposed to request specific input parameters and each step builds upon the previous steps. The final component contains the results retrieved from an API that accepts the input gathered from the first steps.

My problem is that I can't get info from one component to the next. I have this issue in practically every component I use, so I suspect the way I want to do it is the problem.

The first problem is that I need to retrieve a list of possibilities from the API, and display this list in a dropdown in multiple child components. I put this list in a Polymer property, but the auto binding does not fire and the data change is not properly propagated down to the child components (if at all). I define a few iron-ajax elements that fetch the data OK, and have a template with child components that need the output of these iron-ajax elements.

<template>
    <iron-ajax auto url="{{typesURL}}" handle-as="json"
      on-response="handleTypesResponse"></iron-ajax>
    <!-- more iron-ajax elements -->

    <section id="activities">
      <template is="dom-repeat" items="{{activities}}" as="activity">
        <my-activity activity="{{activity}}"
                      types="{{types}}" />
      </template>
    </section>
    <!-- more classic html elements -->
</template>

My url is straightforward and it casts into an Array just fine, but the template in activities is not reloaded and edited if I add an item to the activity array. How could I accomplish this?

A second issue that I'm facing is getting the 'result' of a component. I have a form where I want the user to specify times. For this, I'm using paper-time-picker. When choosing a time however, and returning to the underlying web component, the time is not changed. This is the code that defines the dialog:

<paper-dialog id="timeDialog" modal class="paper-time-picker-dialog" entry-animation="scale-up-animation" exit-animation="fade-out-animation">
  <h2>Start time <span>{{activity.name}}</span></h2>
  <paper-time-picker id="startTimePicker"></paper-time-picker>
  <div class="buttons">
    <paper-button dialog-dismiss>Cancel</paper-button>
    <paper-button dialog-confirm autofocus on-tap="confirmTime">OK</paper-button>
  </div>
</paper-dialog>

And these functions defined below the Polymer properties both show and retrieve the dialog and result:

  showAttachedDialog: function (id) {
    var button = this.$$(id);
    if (!button.hasAttribute('data-dialog')) {
      return;
    }

    var dialogId = '#' + button.getAttribute('data-dialog');
    var dialog = this.$$(dialogId);
    if (dialog) {
      dialog.open();
    }
  },
  confirmTime: function () {
    this.activity['time'] = this.$$('#timePicker').time;
    this.notifyPath('activity.time', this.activity.time);

    console.log(this.activity);
    console.log("time activity: " + this.activity.time);
  },

The console output turns up empty (as in 'time activity: '). Does anyone see what I'm doing wrong? Do ask for more information if you require any to see what I may be missing here. Thank you.

Upvotes: 3

Views: 396

Answers (1)

user656449
user656449

Reputation: 3032

regarding activities thingy - you should use Polymer's push, pop etc, see https://www.polymer-project.org/1.0/docs/devguide/templates.html#dom-repeat. Or manualy invoke notifyPath. This works:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>xxz</title>
    <script src="./bower_components/webcomponentsjs/webcomponents.js"></script>

    <link rel="import" href="./bower_components/polymer/polymer.html">


    <link rel="import" href="bower_components/paper-time-picker/paper-time-picker.html">
    <link rel="import" href="bower_components/paper-input/paper-input.html">
    <link rel="import" href="bower_components/paper-button/paper-button.html">
    <link rel="import" href="bower_components/paper-dialog/paper-dialog.html">
    <link rel="import" href="bower_components/neon-animation/animations/scale-up-animation.html">
    <link rel="import" href="bower_components/neon-animation/animations/fade-out-animation.html">

    <dom-module id="my-activity">
        <style>
            :host{
                display: block;
            }
        </style>
        <template>
            Activity <span>{{activity.name}}</span>
            <paper-button on-click=showAttachedDialog>Time dialog <span>{{activity.time}}</span></paper-button>

            <paper-dialog id="timeDialog" modal class="paper-time-picker-dialog" entry-animation="scale-up-animation" exit-animation="fade-out-animation">
                <h2>Activity name <span>{{activity.name}}</span></h2>

                <!-- from https://github.com/bendavis78/paper-time-picker -->
                <paper-time-picker id="startTimePicker"></paper-time-picker>
                <!--unfortunately  paper-time-picker is not a iron-input (is="iron-input") so you can't jut bind to its value-->
                <!--start time: <paper-input id="time" value="{{activity.time}}"></paper-input>-->

                <div class="buttons">
                    <paper-button dialog-dismiss>Cancel</paper-button>
                    <paper-button dialog-confirm autofocus on-tap="confirmTime">OK</paper-button>
                </div>
            </paper-dialog>
        </template>
        <script>
            HTMLImports.whenReady(function () {
                Polymer({
                    is: "my-activity",
                    activity: Object,
                    listeners: {
                        'startTimePicker.time-changed': '_onTimeChanged'
                    },

                    //this is not needed if time is copied in confirmTime
                    _onTimeChanged: function(){
                        if (this.activity) {//first event is fired before activity is set
                            console.log("time activity: " + this.activity.time+' startTimePicker.time='+ this.$.startTimePicker.time);
                            this.activity.time = this.$.startTimePicker.time;
                        }
                    },

                    showAttachedDialog: function (event /*id*/) {
//                        that's I can't comprehend
//                        var button = this.$$(id);
//                        if (!button.hasAttribute('data-dialog')) {
//                            return;
//                        }
//
//                        var dialogId = '#' + button.getAttribute('data-dialog');
//                        var dialog = this.$$(dialogId);
//                        if (dialog) {
//                            dialog.open();
//                        }
                        this.$.timeDialog.open();
                    },
                    confirmTime: function () {
//                        this.activity['time'] = this.$$('#timePicker').time;
//                        this.notifyPath('activity.time', this.activity.time);

                        this.activity.time = this.$.startTimePicker.time;
                        console.log("time activity: " + this.activity.time+' startTimePicker.time='+ this.$.startTimePicker.time);

                    }
                })

            });
        </script>
    </dom-module>

    <dom-module id="my-element">
        <template>

            <paper-button on-click=handleTypesResponse>Kinda call ajax</paper-button>

            <section>
                <template is="dom-repeat" items="{{activities}}" as="activity">
                    <my-activity activity="{{activity}}" />
                </template>
            </section>

        </template>
        <script>
            HTMLImports.whenReady(function () {
                Polymer({
                    is: "my-element",

                    handleTypesResponse: function () {
                        this.splice('activities', 0, 3);
                        for (var i = 0; i < 10; i++) {
                            console.log('i=' + i);
                            this.push('activities', {name: 'name'+i, time: new Date()});

                        }
                    },

                    ready: function() {
                        this.activities = [];
                        this.push('activities', {name: 'name XXX', time: new Date()});
                        this.push('activities', {name: 'name YY', time: new Date()});
                        this.push('activities', {name: 'name ZZ', time: new Date()});
                    }
                });
            });
        </script>

    </dom-module>


</head>
<body>

<my-element></my-element>


</body>
</html>

Upvotes: 0

Related Questions