angular / angular.js

AngularJS - HTML enhanced for web apps!
https://angularjs.org
MIT License
58.79k stars 27.48k forks source link

Tranclusion dupes polymer elements. #12410

Open jacob-robertson opened 9 years ago

jacob-robertson commented 9 years ago

I've noticed an issue with directives that transclude content that contains a paper element, in my case, a paper button. Because transclude clones the content, polymer performs the shadow DOM expansion twice, which results in a paper button inside a paper button.
Initially, the html being transcluded is written as follows:

<paper-button>[content]</paper-button>

Once the html is rendered, before angular is loaded, polymer expands the element in the following way:

<paper-button>
    <paper-ripple/>
    <paper-material>
        [content]
    </paper-material>
</paper-button>

That's fine, but then transclude clones the element and copies it into the destination div, which causes polymer to expand the <paper-button> element again, resulting in the following structure:

<paper-button>
    <paper-ripple/>
    <paper-material>
        <paper-ripple/>
        <paper-material>
            [content]
        </paper-material>
    </paper-material>
</paper-button>

This is clearly not the desired outcome. In my testing, moving an element around the DOM does not cause this to occur, but cloning the element and then inserting the clone into the DOM causes polymer to expand the element all over again. This doesn't seem to be an issue with Polymer but with the way transculsion works, but I'm definitely open to suggestions and curious if there is a viable solution out there. So far the only work-around I've found is to add a prefix to the <paper-button> tag, preventing the initial expansion and then removing it in the transclude function. Painful, I know.

lgalfaso commented 9 years ago

A plunker would be very much appreciated. Any chance this can be related to https://github.com/angular/angular.js/issues/8598#issuecomment-52721168 ?

jacob-robertson commented 9 years ago

I apologize for the delay. After some considerable difficulty getting Polymer working in a plunker, I was not able to reproduce the issue. It still happens quite reliably in the web application that I'm developing, but that's not something I'm able to share, unfortunately. I have gone so far as to copy the relevant scripts and html libraries that I'm using in the app into plunker, and still no issue. So it would appear that this is not an issue with transclusion but with something more specific to my app.

sergeitemkin commented 9 years ago

Hi, I've been able to reproduce the issue on plunker, but it looks like it's a combination of ng-view and ng-transclude directives that's causing it.

Here's the example: http://plnkr.co/edit/YLjTgiXxtIrE7hWs6mFP?p=preview

In the above example, there is a simple transclude directive that just appends the contents to a div:

app.directive('sTransclude', function() {
  return {
    transclude: true,
    template: '<div ng-transclude></div>'
  };
});

Everything seems ok, until you also place the transclude function into one of the views, but it only breaks if you have to navigate to the view and not when it's in the view used by the default route. Refreshing the page seems to fix the issue until you navigate to another route again, but that's harder to demonstrate in plunker.

In the example, stillgoodbutton.html has the exact same code (minus the button text) as badbutton.html. The default route uses stillgoodbutton.html and works fine, but as soon as you use the link to navigate to #/badbutton things go wrong and the button becomes nested.

Also, as an added bonus, putting a <script> tag with a src attribute after the <link href="paper-button.html"/> breaks all three buttons in the example if you're using Chrome. Not sure why that's happening but maybe it's somehow related. You can see an example of this by uncommenting out the <script> tag at the bottom of the <head> section in the example above. The script it's referencing doesn't actually contain any javascript, and from what I've experienced it doesn't matter what, if anything, is in the script - it always breaks transclude as long as it's registered after polymer elements and as long as it uses the src attribute.

Anyway, that's a smaller issue since we can just not register other scripts below polymer element registrations, but I'm curious to know if there's a workaround or a fix for the issue with ng-view and trasnclude.

rochdev commented 9 years ago

I've faced the same problem recently and it looks like it's related to shady DOM being contained in any transcluded content. When using native shadow DOM it seems to work fine. I've setup a repo with both versions at https://github.com/rochdev/polymer-transclude-problem

jshcrowthe commented 9 years ago

+1 to @rochdev's comment.

Interestingly enough it only seems to be an issue in Chrome....

SimonKunz commented 8 years ago

Are there any updates on this issue? I'd love to use some of my custom polymer elements within a new angular 1.x project.

Or are there any workarounds?

Narretz commented 8 years ago

Still a problem in the latest angular and Polymer releases. We probably need someone from the polymer team to collaborate on this for a solution,