Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accessing the parent context of a web component being either DOM or Shadow DOM

Context:

I am carrying out tests about web component composition in different contexts. Particularly I am trying to relate several web component by getting access to one of them from another one by a searching process within the DOM / Shadow DOM of the involved components.

Problem:

Let's suppose we have a web component named x-foo requiring to access another one x-randgen. The latter component exposes business methods used by the former. In order to avoid a tightly coupled communication between both components I would like to use a discovery mechanism in x-foo to access x-randgen through a searching process across DOM and Shadow DOM models. In particular I identify two possible scenarios. Either both x-foo and x-randgen instantiated are in the global context (index.html) or they both appear within another template, say x-bar. The problem is that the searching process should be implemented differently in each case. Following I show a pseudocode with my approach summarizing, in essence, my question. (The global example can be found here: http://jsbin.com/qokif/1/)

    Polymer('x-foo', {
       ...
       getRandGen: function () {
          if (<<x-foo & x-randgen are in the global context>>)
             return document.querySelector('x-randgen');
          else if (<<x-foo & x-randgen are in a template>>)
             return <<the x-randgen tag within the template>>;
       }
    });

Question:

I would appreciate if someone could reformulate the snippet above in proper terms according to the Polymer technology.

like image 837
Javier Vélez Avatar asked Jan 10 '23 12:01

Javier Vélez


2 Answers

You could write your problem function like this:

    getRandGen: function () {
      var root = this;
      while (root.parentNode) {
        root = root.parentNode;
      }
      return root.querySelector('x-randgen');
    }

http://jsbin.com/xufewi/1/edit

Other solutions can be made using monostate pattern (rare) or a proper controller (common).

The monostate idea is that a particular element expresses a conduit to a shared-state (i.e. the max value). Wherever you need access to the shared-state, you simply create one of the accessor elements.

The controller idea is that the element bubbles an event requesting the randgen utility. Some ancestor (the controller) handles the event and provides the resource. This is a type of dependency management that's great for design flexibility.

http://jsbin.com/tudow/1/edit

like image 160
Scott Miles Avatar answered Jan 30 '23 15:01

Scott Miles


Two bugs in your jsbin. The first is that you want domReady, not ready because you call getRandGen() inside, which queries the DOM. Even that is a bit brittle though because it depends on the x-randgen element existing at the time that your x-foo's domReady event fires (so it wouldn't work if x-randgen is in a conditional template e.g.

The second issue is that document.querySelector('x-randgen') won't find an <x-randgen> inside of a ShadowDOM.

A bit of terminology clarification here. The "template context" and "global context" ideas aren't quite right. Polymer elements instantiate their <template>s inside of their shadow roots, which establish a shadow dom. The shadow dom is an abstraction for isolating components, so that they're less likely to interfere with the rest of the page, and the page is less likely to interfere with them. It is possible to reach across the shadow dom boundary, but just be aware that you may be reaching into the implementation details of other components.

All that to say that if you don't care what x-randgen you get a hold of, even if it's within some totally unrelated component, this should work: document.querySelector('x-randgen') || document.querySelector('body /deep/ x-randgen'). JSBin: http://jsbin.com/goqikire/1/edit

Ideally though you'd have a better idea of where the x-randgen will be relative to your x-foo, or as I suggested above the component responsible for both the x-randgen and the x-foo can explicitly make them aware of each other.

like image 20
Peter Burns Avatar answered Jan 30 '23 15:01

Peter Burns