polymerpolymer-1.0jsbinpolymer-1.xdom-repeat

Polymer 1.x: Applying iron-media-query inside dom-repeat to determine screen width


Click here for jsBin.

I want to calculate the screen width and assign that result to a number between, say, 0 and 3, for example. I am trying to use iron-media-query to do this.

I expect to see (logged to the console) one of the queries return a value of true and the other three to return false. However, they all return a value of undefined.

What am I doing wrong?

FYI, After I solve this, I plan to add a conditional to the queryResult() method to store the value of index when queryMatches is true.

e.g.
queryResult: function() {
  ...
  if(this.queryMatches) {
    this.set('mediaWidth', index);
  }
  ...
}
http://jsbin.com/kamusivebi/1/edit?html,console,output
<!doctype html>
<head>
  <meta charset="utf-8">
  <base href="https://polygit.org/components/">
  <script src="webcomponentsjs/webcomponents-lite.min.js"></script>
  <link href="polymer/polymer.html" rel="import">
</head>
<body>

<dom-module id="x-element">

<template>
  <style></style>

  <template is="dom-repeat"
            id="page"
            items="[[queries]]"
            >
    <iron-media-query id="query"
                      full
                      query="[[item]]"
                      query-matches="{{queryMatches}}"
                      >
      <span hidden>{{queryResult(index)}}</span>
    </iron-media-query>
  </template>

</template>

<script>
  (function(){
    Polymer({
      is: "x-element",
      properties: {
        queryMatches: Boolean,
        queries: {
          type: Object,
          value: function() {
            return [
              '(max-width:  699px)'                         ,
              '(min-width:  700px) AND (max-width:  899px)' ,
              '(min-width:  900px) AND (max-width: 1124px)' ,
              '(min-width: 1125px)'                         ,
            ];
          },
        },
      },
      queryResult: function(index) {
        this.set('mediaWidth', index);
        console.log('mediaWidth', this.mediaWidth);
        console.log('queryMatches', this.queryMatches);
      },
    });
  })();
</script>

</dom-module>

<x-element></x-element>

</body>

Solution

  • Two problems:

    1. You're incorrectly binding the results of each iron-media-query to a single queryMatches property, so each iteration would overwrite the results of the previous iteration. To correct this, you could bind to a sub-property of the item iterator (e.g., item.queryMatches), which requires changing the type of queries from a String array into an Object array. Then, you could pass item.queryMatches to queryResult().

    2. Your demo is missing the HTML import for <iron-media-query>, so queryMatches would always be undefined.

    Here's a demo with the corrections:

    <head>
      <meta charset="utf-8">
      <base href="https://polygit.org/polymer+:1.7.0/components/">
      <script src="webcomponentsjs/webcomponents-lite.min.js"></script>
      <link href="polymer/polymer.html" rel="import">
      <link href="iron-media-query/iron-media-query.html" rel="import">
    </head>
    <body>
      <dom-module id="x-element">
        <template>
          <template is="dom-repeat"
                    id="page"
                    items="[[queries]]"
                    >
            <iron-media-query id="query"
                              full
                              query="[[item.q]]"
                              query-matches="{{item.queryMatches}}"
                              >
            </iron-media-query>
            <span hidden>[[queryResult(index, item.queryMatches)]]</span>
            <div>[[item.q]]: [[item.queryMatches]]</div>
          </template>
        </template>
    
        <script>
          HTMLImports.whenReady(function() {
            Polymer({
              is: 'x-element',
              properties: {
                queries: {
                  type: Object,
                  value: function() {
                    return [
                      { q: '(max-width:  699px)'                         },
                      { q: '(min-width:  700px) AND (max-width:  899px)' },
                      { q: '(min-width:  900px) AND (max-width: 1124px)' },
                      { q: '(min-width: 1125px)'                         },
                    ];
                  },
                },
              },
              queryResult: function(index, queryMatches) {
                console.log('index', index, 'queryMatches', queryMatches);
              }
            });
          });
        </script>
    
      </dom-module>
    
      <x-element></x-element>
    
    </body>

    codepen