0

Using the polymer-cli tool, and the shopping cart boilerplate as a starting point, I made a simple mock-up to illustrate the use case.

Assume your index.html file includes "test-app.html" and the matching tag

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">

  <title>My App</title>

  <link rel="shortcut icon" sizes="32x32" href="/images/app-icon-32.png">

  <meta name="theme-color" content="#fff">
  <link rel="manifest" href="/manifest.json">

  <script>

    // setup Polymer options
    window.Polymer = {lazyRegister: true, dom: 'shadow'};

    // load webcomponents polyfills
    (function() {
      if ('registerElement' in document
          && 'import' in document.createElement('link')
          && 'content' in document.createElement('template')) {
        // browser has web components
      } else {
        // polyfill web components
        var e = document.createElement('script');
        e.src = '/bower_components/webcomponentsjs/webcomponents-lite.min.js';
        document.head.appendChild(e);
      }
    })();

    // load pre-caching service worker
    if ('serviceWorker' in navigator) {
      window.addEventListener('load', function() {
        navigator.serviceWorker.register('/service-worker.js');
      });
    }

  </script>

  <!-- <link rel="import" href="/src/bewi-app.html"> -->
  <link rel="import" href="/src/test-app.html">

  <style>

    body {
      margin: 0;
      font-family: 'Roboto', 'Noto', sans-serif;
      line-height: 1.5;
      min-height: 100vh;
      background-color: #eee;
    }

  </style>

</head>
<body>
  <span id="browser-sync-binding"></span>

  <test-app id="test"></test-app>

</body>
</html>

Now, assume test-app.html containing the following (again a mere simplified copy of my-app.html):

<link rel="import" href="../bower_components/polymer/polymer.html">
<link rel="import" href="../bower_components/app-route/app-location.html">
<link rel="import" href="../bower_components/app-route/app-route.html">
<link rel="import" href="test-element.html">

<dom-module id="test-app">

  <template>

    <app-location route="{{route}}"></app-location>
    <app-route
        route="{{route}}"
        pattern="/:page"
        data="{{routeData}}"
        tail="{{subroute}}"></app-route>

        test-element is loaded bellow
        <test-element></test-element>
    <div>
    </div>
  </template>

  <script>

    Polymer({

      is: 'test-app',

      properties: {

        page: {
          type: String,
          reflectToAttribute: true,
          observer: '_pageChanged'
        },
        baseUrl: {
          type: String,
          value: '/'
        },
        siteUrl: {
          type: String,
          value: 'http://fqdn.local'
        }
      },

      observers: [
        '_routePageChanged(routeData.page)'
      ],

      _routePageChanged: function(page) {
        this.page = page || 'view1';
      },

      _pageChanged: function(page) {
        // load page import on demand.
        this.importHref(
          this.resolveUrl('my-' + page + '.html'), null, null, true);
      }

    });

  </script>

</dom-module>

Now, the test-element.html

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

<dom-module id="test-element">
  <template>
    <div> I am a test </div>
  </template>

  <script>
  (function() {
    'use strict';

    Polymer({
      is: 'test-element',
      ready: function() {
        console.log('READY');
        console.log('find #test using document.querySelector', document.querySelector('#test')); // OK
        console.log('find #test .siteUrl using document.querySelector', document.querySelector('#test').siteUrl); // undefined
        console.log('find #test .siteUrl using Polymer.dom', Polymer.dom(document.querySelector('#test')).siteUrl); // undefined
        console.log('find #test .siteUrl using Polymer.dom().node', Polymer.dom(document.querySelector('#test')).node.siteUrl); // undefined
        console.log('find #test .siteUrl using Polymer.dom().properties', Polymer.dom(document.querySelector('#test')).node.properties); // {object} but, I'm guessing not the computed values of the properties

        // So, how may I access the #test app's "siteUrl" property from within a custom element?
      }
    });
  })();
  </script>
</dom-module>

So, the real question is, how may test-element access the property "siteUrl" in the main app? I'm planning to make this variable readOnly, and access it from other custom elements. I'ld prefer this approach VS passing the siteUrl as an attribute to the test-element element..

What do you think?

rud
  • 59
  • 7
  • 1
    I'm almost sure that the `app-location` element provide it for you. – Jp_ Jun 30 '16 at 19:18
  • This is just an example to access a dummy property. The idea is to have several specific readOnly properties readable from within my custom elements... – rud Jun 30 '16 at 20:38
  • I may not be understanding your question very well, because it seams that the solution you suggested is perfect for the situation "passing the siteUrl as an attribute to the test-elemet element", this is the Polymer way. You'll accomplish the readOnly requirement surrounding the variable with square brackets, like this `[[siteUrl]]`. I suggest you to read [Property change notification and two-way binding](https://www.polymer-project.org/1.0/docs/devguide/data-binding#property-notification) from the Polymer documentation. – Jp_ Jul 01 '16 at 14:30
  • I think you are right. I might be desperately trying to make Polymer do things it wasn't intended to. My main idea is to share the content of an "env" object to all my Polymer elements, so that I do not need to pass a variable as attributes from the main app down to deep-nested elements.. Hmmm, maybe I should rather do something like: properties: { apiUrl: { type: String, value: function() { return _env.apiUrl } } } – rud Jul 04 '16 at 10:47

1 Answers1

1

The right way to pass information through elements is using the Data Binding system, i.e. "passing the siteUrl as an attribute to the test-elemet element"

You'll accomplish the Read Only requirement surrounding the variable with square brackets, like this [[siteUrl]] as described in Property change notification and two-way binding.

You can set a variable in a global environment as you said like

<script>
  var myGlobalVar = 'is accessible in any element'

  Polymer({

    is: 'test-app',

    // ...

  });

</script>

and you can access it in every element.

BUT, global variables are not recommended as you may know. References about why in the links below.

Community
  • 1
  • 1
Jp_
  • 5,973
  • 4
  • 25
  • 36