简体   繁体   中英

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.

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 (ie 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

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 eg

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') 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM