javascripthtmljqueryangular

Angular web component doesn't work along with JQuery


I'm making angular web component to improve another component built on JEE application, but it broke with Jquery.

I have made a minimal test to reproduce the error.

<html>
  <head>
    <script src="./jquery.min.js"></script>
    <script src="./main.js"></script>
  </head>
  <body>
    <app-test></app-test>
    <button id="testBtn">Click</button>
    <script>
      $("#testBtn").click(function () {
        alert("jQuery fonctionne !");
      });
    </script>
  </body>
</html>

If i comment script mains.js, jquery work and if i comment

    <script>
      $("#testBtn").click(function () {
        alert("jQuery fonctionne !");
      });
    </script>

my angular component works, but when the two are loaded together, it throws an error: main.js:4 ERROR TypeError: $ is not a function

I don't know how solve this. I have made a stackblitz minimal reproduction.


Solution

  • the problem is conflict in global scope ($ variable is used by angular, hence the error, using jQuery('#testBtn')... or another alias would work), which means that it's leaking into global namespace.

    Angular shouldn't leak, so you need to load angular code as a module by adding type="module" to script tag to prevent leakage to global scope:

    <script src="./main.js" type="module"></script>
    

    Module-defined variables are scoped to the module unless explicitly attached to the global object. On the other hand, globally-defined variables are available within the module

    Other differences between modules and classic scripts


    demo (by Eliseo)


    As a side note, jQuery allows avoiding global namespace conflict with jQuery.noConflict()

          jQuery.noConflict();
          (function ($) {
            $('#testBtn').click(function () {
              alert('jQuery fonctionne !');
            });
          })(jQuery);
    

    Many JavaScript libraries use $ as a function or variable name, just as jQuery does. In jQuery's case, $ is just an alias for jQuery, so all functionality is available without using $. If you need to use another JavaScript library alongside jQuery, return control of $ back to the other library with a call to $.noConflict(). Old references of $ are saved during jQuery initialization; noConflict() simply restores them.