I'm using Webpack to build an Angular 1.4 project. The project makes use of several jQuery plugins, which are wrapped into angular directives. Those directives internally use angular.element
, probably implying that angular.element is the real jQuery, not jqLite.
I want angular to auto-detect jQuery and use it instead of jqLite. I tried to require jquery locally in my entry point module app.js
: require('jquery')
and to expose jQuery globally with require(expose?$!expose?jQuery!jquery)
.
Still, whatever I do, angular.element
refers to jqLite.
My research resulted in several findings:
window.angular
, so I don't need to expose
it with Webpack: Does Angular assign itself to `window.angular` globally, when loaded as CommonJS module?. require('jquery')
in it. I'm not 100% sure, but looks like Angular doesn't access jQuery
from global namespace directly, instead, it tries to access window.jQuery
in bindJQuery
function, so this approach doesn't help: Expose jQuery to real Window object with Webpack.imports-loader
seems unfit: Angular wants window.jQuery
, not just jQuery
.expose-loader
, jquery makes it to the window object. My problem was that Babel hoists all of its imports to the top of module in the resulting code. Hence, although require(expose?jquery!jquery)
was before import angular from "angular"
in source files, in bundle require("angular")
is at the top of the file, before jquery, so by the time Angular is imported, jquery is not yet available. I wonder, how to use Webpack loaders with ECMA6 import syntax.import
syntax instead of require
syntax with jquery: import "jquery"
or import $ from "jquery"
, not require(jquery)
: (Petr Averyanov: How to use Webpack loaders syntax ( imports/exports/expose) with ECMAScript 6 imports?). jquery source code is wrapped with a special wrapper, which idenitifies how jquery is required (with AMD/require, CommonJS or globally with <script>
statement). Based on that it sets a special argument noGlobal
for jquery fabric and either creates window.jQuery
or not, based on the value of noGlobal
. As of jquery 2.2.4, upon import "jquery"
noGlobal === true
and window.jQuery
is not created. IIRC, some older versions of jquery didn't recognize import
as CommonJS import and added import
ed jquery to global namespace, which allowed angular to use it.Details: here's my app.js
:
'use strict'; require("expose?$!expose?jQuery!jquery"); require("metisMenu/dist/metisMenu"); require("expose?_!lodash"); require("expose?angular!angular"); import angular from "angular"; import "angular-animate"; import "angular-messages"; import "angular-resource"; import "angular-sanitize"; import "angular-ui-router"; import "bootstrap/dist/css/bootstrap.css"; import "font-awesome/css/font-awesome.css"; import "angular-bootstrap"; require("../assets/styles/style.scss"); require("../assets/fonts/pe-icon-7-stroke/css/pe-icon-7-stroke.css"); // Import all html files to put them in $templateCache // If you need to use lazy loading, you will probably need // to remove these two lines and explicitly require htmls const templates = require.context(__dirname, true, /\.html$/); templates.keys().forEach(templates); import HomeModule from "home/home.module"; import UniverseDirectives from "../components/directives"; angular.module("Universe", [ "ngAnimate", "ngMessages", "ngResource", "ngSanitize", "ui.router", "ui.bootstrap", HomeModule.name, UniverseDirectives.name, ]) .config(function($urlRouterProvider, $locationProvider, $stateProvider){ // $urlRouterProvider.otherwise('/'); // $locationProvider.html5Mode(true); $stateProvider .state('test', { url: "/test", template: "This is a test" }); });
You can import OnInit from Angular Core. import { Component, OnInit} from '@angular/core'; Then, you need to implement ngOnInit Lifecycle Hook. You can write jQuery code inside the method ngOnInit whether DOM is ready or not, as you would in traditional web application development.
The angular. element() Function in AngularJS is used to initialize DOM element or HTML string as an jQuery element. If jQuery is available angular. element can be either used as an alias for the jQuery function or it can be used as a function to wrap the element or string in Angular's jqlite.
jqLite is a tiny, API-compatible subset of jQuery that allows AngularJS to manipulate the DOM in a cross-browser compatible way. jqLite implements only the most commonly needed functionality with the goal of having a very small footprint. To use jQuery , simply ensure it is loaded before the angular. js file.
A complete, yet simple, starter for AngularJS using Webpack. This workflow serves as a starting point for building AngularJS (1. x) applications using Webpack 2.
Got this answer from john-reilly:
The mysterious case of webpack angular and jquery
bob-sponge's answer is not quite right - the Provide plugin is actually doing a text replacement on modules it processes, so we need to provide window.jQuery
(which is what angular is looking for) and not just jQuery
.
In your
webpack.config.js
you need to add the following entry to your plugins:
new webpack.ProvidePlugin({ "window.jQuery": "jquery" }),
This uses the webpack ProvidePlugin and, at the point of webpackification (© 2016 John Reilly) all references in the code to window.jQuery will be replaced with a reference to the webpack module that contains jQuery. So when you look at the bundled file you'll see that the code that checks the
window
object forjQuery
has become this:
jQuery = isUndefined(jqName) ? __webpack_provided_window_dot_jQuery : // use jQuery (if present) !jqName ? undefined : // use jqLite window[jqName]; // use jQuery specified by `ngJq`
That's right; webpack is providing Angular with jQuery whilst still not placing a
jQuery
variable onto thewindow
. Neat huh?
Apparently you still need to use the commonJs require for angular in the ES6 example.
import $ from "jquery" window.$ = $; window.jQuery = $; var angular = require("angular");
below is the original answer
I want to purpose a easier solution. Just make jQuery a window global so that angular can recognize it:
var $ = require("jquery") window.$ = $; window.jQuery = $; var angular = require("angular");
or in your case (OUT DATED):
import $ from "jquery" window.$ = $; window.jQuery = $; import angular from "angular";
I hope this helps :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With