15

I believe I've set everything up correctly, but I'm getting an odd issue with Webpack.

Consider this simple app.ts file:

'use strict';

import $ = require('jquery');
import 'jquery-ui';

$(function() {
    $( "#sortable" ).sortable();
});

Everything compiles fine, but when the site is run it complains that the Uncaught TypeError: $(...).sortable is not a function. (sortable is a jQuery UI function).

Everything works fine when I instead link to a CDN hosted version of jQuery and jQuery UI, but it doesn't work when I use JS modules and Webpack. Why is this?

Why is the jQueryUI function sortable() not recognized?

3
  • Can you include the tslint.json? It is still unclear why you think that they are being compiled in that order. Commented Jul 5, 2017 at 17:30
  • Consider showing that in your question. Also include how you are compiling the code (TypeScript version and flags if you have any). Commented Jul 5, 2017 at 17:45
  • Do you use System.JS to load CommonJS modules ? See: stackoverflow.com/questions/44929021/… If you use this order no longer becomes important the System.import resolves the require. Commented Jul 5, 2017 at 19:01

3 Answers 3

32

The problem is that jQuery UI normally automatically pulls in the components it needs (which is why it works when it's linked via a CDN), but that doesn't work when it's imported as a module (like with Webpack).

Thankfully as of jQuery UI 1.11 you can manually pull in any extra components you need like so:

'use strict';

import $ = require('jquery');

require('jquery-ui');
require('jquery-ui/ui/widgets/sortable');
require('jquery-ui/ui/disable-selection');

etc.

Here's some official documentation explaining this further.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you, I spent an hour trying to make jquery-ui works with TS and apparently this was the actual issue.
4

you use incorrect ES6 import syntax, but it still wouldn't work if it was right. sortable is not recognized because $ isn't avaliable inside jquery-ui module.

This solution isn't optimized because you import whole jquery-ui.

npm install --save jquery-ui-bundle

index.js

'use strict';

import 'jquery-ui-bundle';

$(function() {
    $( "#sortable" ).sortable();
});

webpack

  plugins: [
      new webpack.ProvidePlugin({
          $: 'jquery',
          jQuery: 'jquery',
          'window.jQuery': 'jquery',
          'window.$': 'jquery'
      })
  ]

2 Comments

jquery-ui-bundle does not seems to be maintained by the jquery-ui team. Furthermore the advantages of importing modules with webpack are not present when importing a complete bundle.
Yes, it's the easiest, but not the best way.
3

This answer is merely a summary of two helpfull other answers : Answer 1, Answer 2

First, better to know that jquery-ui-dist and jquery-ui-bundle are not maintained by the jquery-ui team. So you will probably want to avoid using it. Nevertheless, from jquery-ui version 1.11 you can require/import AMD, and from version 1.12 you can use the official package with npm.

Solution 1 :
The preferred way to go is then to import part of jquery-ui such as :

import 'jquery-ui/ui/widgets/draggable';

The only drawback is that if you previously used import 'jquery-ui', you now have to import each modules you want to use specifically. But this is better as it will only bundle the imports you really need.

Check the 1.11 AMD support documentation and the 1.12 npm documentation on their site.

Solution 2 :
But, if for any reason you want to use a single global jquery-ui import, you will have to adapt your webpack config:

First, ensure webpack knows about the jquery aliases :

...
plugins: [
    new webpack.ProvidePlugin({
      '$':'jquery',
      'jQuery':'jquery',
      'window.jQuery':'jquery',
      'global.jQuery': 'jquery'
    }),
...

Then, help webpack resolving the jquery-ui js location :

resolve : {
    alias: {
      // bind version of jquery-ui
      "jquery-ui": "jquery-ui/jquery-ui.js",      
      // bind to modules;
      modules: path.join(__dirname, "node_modules"),

Then, ensure the jquery-ui is loaded as soon as possible (maybe during startup ?)

var $ = require("jquery"),
        require("jquery-ui");

If you want to use a theme with jquery-ui, you will have to setup the css-loader and file-loader accordingly. (Don't forget to install those loaders):

module: {
    loaders: [
      { test: /\.css$/, loader: "style!css" },
      { test: /\.(jpe?g|png|gif)$/i, loader:"file" },

And below you imports of jquery and jquery-ui just add :

import 'modules/jquery-ui/themes/black-tie/jquery-ui.css';
import 'modules/jquery-ui/themes/black-tie/jquery-ui.theme.css';

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.