Honestly this discussion is definitely reaching out of the realm of the
practical and more into the philosophical, but I still think it's an
important one to have. I appreciate the detailed response and apologize
that I'm likely going to keep this thread burning for a bit.
Web Components aren't just about making a *different *platform for building
web apps, it's about making a *better *one. Native support at the browser
level is obviously the lynch pin of that effort, as that's what Web
Components have that nothing else has ever had.
Shadow boundaries are revelatory, but to me the revelation is that they
exist *along-side* the Light DOM, not in place of. The Shadow DOM gives
developers the chance to have cake and eat it too: to build all of the
nasty hacked-together HTML necessary to display things as intentioned
without exposing it to the casual observer.
Again and again I come back to the notion that in a well-designed Web
Components app, *the DOM is the engine of application state*. While you are
correct that shadow boundaries may be crossed at will by a knowledgeable
developer, I believe that packing everything into the Shadow DOM, while
certainly serviceable, is missing out on perhaps one of the most powerful
new opportunities for consideration in this new world. Again I liken Light
DOM to a Public API and Shadow DOM to a Private API.
Developers shouldn't be encouraged to dump more and more beyond the shadow
boundary but instead should be thinking architecturally. A bizarre metaphor
that comes to mind is one of a puppeteer with a marionette, holding a
smaller marionette and so on and so forth. Any strings that the puppeteer
should be able to pull from the top-level of the DOM should be visible to
him. Similarly, diving into the shadow of any given element should yield
the same consideration: Light DOM for control, Shadow DOM for
implementation.
There is much ground left to cover in the determination of best practices
in a Web Components world, but I feel that "giving up" on the shadow
boundary as an architectural choice is going to squander massive potential.
Of course, you are free to entirely disagree with my thinking. However,
something that would be immensely helpful is if you could point me to where
the sharp toys are so I can play with them and cut myself a bit. How would
I go about using Polymer's template binding to construct Light DOM? A few
quick pointers and I'll follow the rabbit hole myself to see if it still
feels right.
Thanks again for the reply, and sorry for the florid prose, I've been
reading too much Game of Thrones this weekend. ;)
On Thursday, March 20, 2014 2:20:49 PM UTC-7, Rob Dodson wrote:
>
> Sorry for the super long response but you've raise a bunch of interesting
> points that we wanted to address :)
>
> The problem here is that it would actually be quite useful to my
>> application if all of those <category-item> elements lived in the Light
>> DOM. I could bind events to individual categories or highlight one based on
>> pushState URL changes, etc
>
>
>
> To answer this question, it’s helpful to ask yourself, “Who owns this set
> of elements?”
>
>
> Scenario 1: The category-list owns the category-items
>
>
> If the category-item elements are owned entirely by the category-list
> element, then you probably want to add these event bindings inside of
> category-list. In this scenario, it’s really the model of category-list
> that is driving the creation, removal, and manipulation of the
> category-item elements. If you need to add a new category-item, you call a
> method on category-list, pass in some data, and the model stamps out the
> templates again.
>
> ex:
>
> var catList = document.querySelector(‘category-list’);
>
> catList.add(dataItem); // this generates a new category-item by updating
> catList’s model
>
> Because category-list owns all of the category-items, it handles the
> responsibility of highlighting a category-item based on pushState URL
> changes.
>
>
> Scenario 2: An outsider owns the category-items
>
>
> This sounds closer to what you’re thinking. You’d like category-items to
> be readily accessible for outside forces to act upon. This means the real
> owner of category-list/items is some parent element. If this is the case,
> then that outside element should be creating and manipulating new
> category-items, not the category-list itself. It will be the job of this
> parent element to watch for pushState changes and highlight the correct
> category-item.
>
> So you can still use Polymer’s template bindings to manipulate your
> category-items, you just wouldn’t do it from *inside* category-list, you’ll
> have to do it from the outside. Which leads to the next question...
>
>
> I feel like the natural end of a "do it in the Shadow DOM" philosophy is
>> my page is just going to end up looking like this:
>> <body>
>> <my-app></my-app>
>> </body>
>
>
> Yes, that would be the end result of trying to use Polymer’s features to
> bind all of the elements in your application together. While a <my-app>
> element might look a little weird—because it’s very different from how we
> typically build web apps—it’s not altogether a bad thing. When you view
> source you will only see <my-app> but if you open the dev tools you should
> be able to inspect the entire application. It might seem scary to put
> things in the Shadow DOM because you think they’re “hidden,” but perhaps a
> better way to think of Shadow DOM is not that things are hidden, but that
> they are *“local.”* So if you open <my-app> in the dev tools you’ll see
> the things that are local to my-app. That might be a few large pieces of
> your application. And if you open any one of those pieces, you’ll see the
> things that are local to it. That actually sounds quite reasonable to me.
>
> Another way to think about it: If you’re writing a program in C++ or Java
> then you’ll always have a main() method that kicks things off. You can
> think of index.html as if it were this main method. When we write web apps
> today, we basically stick all of our markup in index.html, which is kind of
> like sticking all of your code in main(). <my-app> allows you to better
> compartmentalize this code, the same way objects allow you to better
> structure your Java or C++ programs.
>
>
> In the example above, theoretically the "user" of my element could be
>> rendering the page from the server and pre-populating the <category-item>
>> tags without requiring an AJAX call.
>
>
> A <my-app> element could probably work well for client-side rendering, but
> if you need server-side rendering then you’d probably want something that
> more closely resembles the current generation of web apps. If you want to
> add <cateogry-item> elements to a <category-list> using server-side
> technologies then you’d want to use a version of scenario 2 from above.
> Maybe employing a server side templating language. Here’s an example using
> EJS:
>
>
> <category-list>
>
> <% categories.forEach(function(category) { %>
>
> <category-item category=<%= category %>></category-item>
>
> <% }) %>
>
> </category-list>
>
>
> Because this data is coming from the server, there’s no need to generate
> it inside of the Shadow DOM of <category-list>. Just add the elements as if
> you were adding <li>’s to a <ul>.
>
>
> given my category example before, wouldn't it be pretty cool to be able to
>> simply append a new <category-item> element to the <category-list> and that
>> automatically
>> and transparently creates a new category?
>
>
> You can do this, but you’ll want to choose either scenario 1 or scenario 2
> from above. Trying to have it both ways (a list that is generated by a
> template, but also accepts nodes appended at runtime) is going to be tough.
>
>
>
> On Mon, Mar 17, 2014 at 6:29 PM, Michael Bleigh <[email protected]<javascript:>
> > wrote:
>
>> I think this is a complex issue and may become a common point of
>> confusion/frustration for developers as they start to really think about
>> web components for application architecture. Light DOM and Shadow DOM, to
>> me at least, seem to more or less cleanly map to public and private APIs.
>> Things in the Light DOM can and should be touched, manipulated, added.
>> Things in the Shadow DOM are implementation details.
>>
>> This encourages some actually quite interesting ideas around application
>> structure. For instance, given my category example before, wouldn't it be
>> pretty cool to be able to simply append a new <category-item> element to
>> the <category-list> and that automatically and transparently creates a
>> new category?
>>
>> If an element serves little purpose but to wrap and expose a collection
>> of sub-elements which could each be addressed individually, forcing the
>> user to reach into the Shadow DOM seems like a mistaken approach. I'd just
>> like to start some discussion around this. A colleague of mine indicated
>> that in the <polymer-element> definition you could just add a "lightdom"
>> attribute to make <template> work on the Light DOM. That doesn't seem to be
>> true in recent releases, was it ever?
>>
>> On Thursday, March 13, 2014 11:35:28 PM UTC-7, Michael Bleigh wrote:
>>>
>>> I guess because I feel like the natural end of a "do it in the Shadow
>>> DOM" philosophy is my page is just going to end up looking like this:
>>>
>>> <body>
>>> <my-app></my-app>
>>> </body>
>>>
>>> In the example above, theoretically the "user" of my element could be
>>> rendering the page from the server and pre-populating the <category-item>
>>> tags without requiring an AJAX call. If something like this is the case
>>> (maybe AJAX, maybe server-injected) then other parts of the app may be
>>> looking for/depend on events from those <category-item> elements.
>>>
>>> To me the Light DOM is a kind of Public API, so it makes sense to
>>> populate it with semantic, useful elements that your consumers can use.
>>> Does that make sense?
>>>
>>>
>>> On Thu, Mar 13, 2014 at 10:43 PM, Scott Miles
>>> <[email protected]<javascript:>
>>> > wrote:
>>>
>>>> It would be helpful if you could explain in more detail why you want
>>>> your example elements to exist in light DOM.
>>>>
>>>> >> I could bind events to individual categories or highlight one based
>>>> on pushState URL changes, etc. I might even be able to alter attributes of
>>>> the individual category and save them back.
>>>>
>>>> I believe this is all dramatically easier to do in Shadow DOM, so hence
>>>> my confusion.
>>>>
>>>> FWIW, we like to suggest that the light DOM is the province of the user
>>>> of your element. Your element emitting or modifying it's own light DOM is
>>>> mostly an anti-pattern.
>>>>
>>>>
>>>> On Thu, Mar 13, 2014 at 10:04 PM, Michael Bleigh
>>>> <[email protected]<javascript:>
>>>> > wrote:
>>>>
>>>>> To me, the promise of Polymer is to use the DOM as representative an
>>>>> engine of application state. To that end, one area that I'm a bit unclear
>>>>> about is what to do when I want to use template and mdv semantics to
>>>>> create
>>>>> things in the Light DOM. Let me give an example...
>>>>>
>>>>> Let's say I have a sidebar like in Google Groups that is listing
>>>>> categories. I would probably construct an element like <category-list>
>>>>> and
>>>>> perhaps also a <category-item> that would be able to use AJAX to fetch
>>>>> the
>>>>> list of categories and then display them. This is easy enough with Shadow
>>>>> DOM:
>>>>>
>>>>> <template>
>>>>> <core-ajax url="http://some.url" auto response="{{categories}}"></
>>>>> core-ajax>
>>>>> <template repeat="{{category in categories}}">
>>>>> <category-item category="{{category}}" on-click="{{openCategory}}"
>>>>> ></category-item>
>>>>> </template>
>>>>> </template>
>>>>>
>>>>> So far so good. The problem here is that it would actually be quite
>>>>> useful to my application if all of those <category-item> elements lived
>>>>> in
>>>>> the Light DOM. I could bind events to individual categories or highlight
>>>>> one based on pushState URL changes, etc. I might even be able to alter
>>>>> attributes of the individual category and save them back.
>>>>>
>>>>> Hiding all of the children in the Shadow seems like a less-than-ideal
>>>>> situation, but I don't know of another way to do it without manually
>>>>> instantiating each node and using appendChild (and therefore losing all
>>>>> benefits of MDV and data binding).
>>>>>
>>>>> Is there a convention for this? What should the right pattern be here?
>>>>>
>>>>> Follow Polymer on Google+: plus.google.com/107187849809354688692
>>>>> ---
>>>>> You received this message because you are subscribed to the Google
>>>>> Groups "Polymer" group.
>>>>> To unsubscribe from this group and stop receiving emails from it, send
>>>>> an email to [email protected] <javascript:>.
>>>>>
>>>>> To view this discussion on the web visit https://groups.google.com/d/
>>>>> msgid/polymer-dev/c1b45f02-d3e6-4028-a905-998dbcce548c%
>>>>> 40googlegroups.com<https://groups.google.com/d/msgid/polymer-dev/c1b45f02-d3e6-4028-a905-998dbcce548c%40googlegroups.com?utm_medium=email&utm_source=footer>
>>>>> .
>>>>> For more options, visit https://groups.google.com/d/optout.
>>>>>
>>>>
>>>>
>>> Follow Polymer on Google+: plus.google.com/107187849809354688692
>> ---
>> You received this message because you are subscribed to the Google Groups
>> "Polymer" group.
>> To unsubscribe from this group and stop receiving emails from it, send an
>> email to [email protected] <javascript:>.
>> To view this discussion on the web visit
>> https://groups.google.com/d/msgid/polymer-dev/1f907118-5451-42da-86c7-317820196b0c%40googlegroups.com<https://groups.google.com/d/msgid/polymer-dev/1f907118-5451-42da-86c7-317820196b0c%40googlegroups.com?utm_medium=email&utm_source=footer>
>> .
>>
>> For more options, visit https://groups.google.com/d/optout.
>>
>
>
Follow Polymer on Google+: plus.google.com/107187849809354688692
---
You received this message because you are subscribed to the Google Groups
"Polymer" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/polymer-dev/75462e3a-1893-421a-982c-748fe1c8ad4a%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.