Conflict between Angular and prototype.js in a tapestry app

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

Conflict between Angular and prototype.js in a tapestry app

Pratik Patel [C]
Hello all,

I have a tapestry application to which I want to add some distribution
generated from an Angular app. So far, I am able to use Angular
distribution in a .tml page and the page is rendered fine.

Now, I want to add an existing tapestry component (a layout) to this new
page. The problem is that when I add this component, I start getting errors
because of conflict between Angular and prototype.js. They both have
"bind()" method and the method from prototype.js "wins" over the other one
and I get an error from Angular's js code which tries to use bind() method.

As such, I am not using any prototype.js functionality in my new page but
still the prototype library is loaded as it is part of tapestry core. I am
thinking that disabling prototype on this new page would avoid conflict.
After lot of exploration I found that I can probably
use JAVASCRIPT_INFRASTRUCTURE_PROVIDER as mentioned here
http://tapestry.apache.org/current/apidocs/org/apache/
tapestry5/SymbolConstants.html#JAVASCRIPT_INFRASTRUCTURE_PROVIDER

This will allow me to switch from prototype to jQuery. However, I want to
apply this change only on one page. Other pages of the app should still be
using prototype.js. Is that possible to achieve? Is it possible to have
more than one  JavaScriptModuleConfigurations (
http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/javascript/JavaScriptModuleConfiguration.html
)
and then apply them selectively so that one page has configuration without
prototype and all others have the one with prototype? I am using tapestry
5.3.8 and I can upgrade to 5.4.x if it is possible to achieve what is
mentioned above?

Or is there any other way to achieve this? Is it possible to somehow
prevent prototype from being loaded for a specific tapestry page? I would
really appreciate any help on this issue as it is very crucial for us.

Thanks,
Pratik
Reply | Threaded
Open this post in threaded view
|

Re: Conflict between Angular and prototype.js in a tapestry app

Thiago H de Paula Figueiredo
On Fri, Jan 5, 2018 at 7:19 PM, Pratik Patel <[hidden email]> wrote:

> Hello all,
>

Hello!

Short answer: there's no built-in way of having just one page having one
infrastructure which is different from the others.

Something you can try to do is to write a MarkupRendererFilter which
removes the <script> elements added by Tapestry if the requested page is
the one you want with Angular and contribute it with the "after:*"
constraint to the MarkupRenderer service. If it doesn't work, try with
"before:*". For finding script elements, I recommend the tapestry-xpath
library, which allows you to query Tapestry DOM elements using XPath.

The contribution part, a method which would be included in your AppModule,
would look like this:

public void contributeMarkupRenderer(
            final OrderedConfiguration<MarkupRendererFilter> config) {
    config.addInstance("SpecificPageJSRemoverMarkupRendererFilter",
SpecificPageJSRemoverMarkupRendererFilter.class, "after:*");
}

And the MarkupRendererFilter implentation:
public class SpecificPageJSRemoverMarkupRendererFilter implements
MarkupRendererFilter {

    public void renderMarkup(MarkupWriter writer, MarkupRenderer renderer) {
                renderer.renderMarkup(writer);
                if (thisIsTheSpecialPage) {
                     Document document = writer.getDocumet(); // This is
the rendered HTML in the form of a tree of Element instances
                     // Use tapestry-xpath to find the <script> elements
                     // call element.remove() on them.
                }
            }
}

Please let me know whether this works.


>
> I have a tapestry application to which I want to add some distribution
> generated from an Angular app. So far, I am able to use Angular
> distribution in a .tml page and the page is rendered fine.
>
> Now, I want to add an existing tapestry component (a layout) to this new
> page. The problem is that when I add this component, I start getting errors
> because of conflict between Angular and prototype.js. They both have
> "bind()" method and the method from prototype.js "wins" over the other one
> and I get an error from Angular's js code which tries to use bind() method.
>
> As such, I am not using any prototype.js functionality in my new page but
> still the prototype library is loaded as it is part of tapestry core. I am
> thinking that disabling prototype on this new page would avoid conflict.
> After lot of exploration I found that I can probably
> use JAVASCRIPT_INFRASTRUCTURE_PROVIDER as mentioned here
> http://tapestry.apache.org/current/apidocs/org/apache/
> tapestry5/SymbolConstants.html#JAVASCRIPT_INFRASTRUCTURE_PROVIDER
>
> This will allow me to switch from prototype to jQuery. However, I want to
> apply this change only on one page. Other pages of the app should still be
> using prototype.js. Is that possible to achieve? Is it possible to have
> more than one  JavaScriptModuleConfigurations (
> http://tapestry.apache.org/current/apidocs/org/apache/
> tapestry5/services/javascript/JavaScriptModuleConfiguration.html
> )
> and then apply them selectively so that one page has configuration without
> prototype and all others have the one with prototype? I am using tapestry
> 5.3.8 and I can upgrade to 5.4.x if it is possible to achieve what is
> mentioned above?
>
> Or is there any other way to achieve this? Is it possible to somehow
> prevent prototype from being loaded for a specific tapestry page? I would
> really appreciate any help on this issue as it is very crucial for us.
>
> Thanks,
> Pratik
>



--
Thiago