15
    import {Component, ElementRef, OnInit} from 'angular2/core';
    declare var jQuery:any;
    @Component({
      selector: 'jquery-integration',
      templateUrl: './components/jquery-integration/jquery-integration.html'
    })
    export class JqueryIntegration implements OnInit {
      elementRef: ElementRef;
      constructor(elementRef: ElementRef) {
        this.elementRef = elementRef;
      }
      ngOnInit() {
        jQuery(this.elementRef.nativeElement).draggable({
        containment:'#draggable-parent'
      });
    }
  }

Can jQuery be used with TypeScript in Angular2 like the above? How do I use jQuery with JavaScript in Angular2?

Subodh Ghulaxe
  • 18,333
  • 14
  • 83
  • 102
  • 2
    It is advisable to avoid using jQuery with Angular. http://stackoverflow.com/questions/14994391/thinking-in-angularjs-if-i-have-a-jquery-background?rq=1 – Jay Welsh Jan 28 '16 at 06:11
  • 1
    @Jay That link corresponds to Angular1.. isn't Angular2 also avoid jQuery? do you have any reference to that? – Pankaj Parkar Jan 28 '16 at 07:07
  • It might help http://www.code-sample.com/2016/07/use-jquery-with-angular-2.html – Anil Singh Jul 13 '16 at 07:30
  • @jay why? that doesn't make any sense. there's nothing wrong with using jquery and angular 2 together. they do totally different things. – user428517 Sep 14 '16 at 22:39
  • Check out this link, It worked for me http://stackoverflow.com/a/42295505/7532440 – AmanDeepSharma Feb 20 '17 at 04:12
  • 1
    Possible duplicate of [How to use jQuery with Angular2?](https://stackoverflow.com/questions/30623825/how-to-use-jquery-with-angular2) – trungk18 Jul 03 '17 at 05:34

7 Answers7

21

In my opinion: if you do it right and if you keep it minimal, you should go with that.

  1. Install jQuery Typings in project: tsd install jQuery
  2. Load jQuery with script tag ( or other loaders... )
  3. Wrap any jQuery plugin with Angular 2 Directive

Example:

@Directive({
  selector: "[sm-dropdown]"
})
export class SMDropdown {
  constructor(el: ElementRef) {
    jQuery(el.nativeElement).dropdown();
  }
}

Consider this Plunker:

https://plnkr.co/edit/MMNWGh?p=preview

Don't:

  • Don't use it for DOM manipulation, there is Angular way...
  • Don't use it for AJAX calls, there is Angular way...
  • Don't use it for animation, ngAnimation is coming...
Vlado Tesanovic
  • 6,369
  • 2
  • 20
  • 31
  • I'm curious can you expand on the no DOM manipulation? I'm coming from an angular 1 background but i'm aware no DOM manipulation in controllers etc and don't do things angular can do. However in angular 1 at least there are legitimate things angular can't do that you can with jQuery. – ste2425 Jan 28 '16 at 08:05
  • 1
    You have Angular directives that add Styles, Classes and etc, like *ngStyle, *ngClass... You can show and hide things with *ngIf, *ngSwitch... You can control DOM with native js from Angular with ElementRef and Rendered classes. jQuery often reshape DOM, and i assume you want to have control over your html ( for bindings... ). Best practice is, if you need to include jQuery library, is to wrap it in Directive ( as i write you before ) and to append that directive on element in html ( Angular style ). In that case, you will divide responsibilities and make code more readable . – Vlado Tesanovic Jan 28 '16 at 11:51
  • 1
    Looks like really good approach. But i have noticed one issue. If use this with *ngFor. Last item do not initialize jquery plugin. Issue wasfixed by usin ngAfterContentInit() in this directive – Ssss Mar 27 '16 at 12:27
  • @VladoTesanovic can this example apply for other vanila js plugins? – angry kiwi Feb 15 '17 at 08:04
7

Once you have the JQuery typescript library installed, reference it in this way

///<reference path="../typings/jquery/jquery.d.ts" />

Then make the necessary imports

import {Component, AfterViewInit} from 'angular2/core';

Now write the class

@Component({
  selector: 'my-app',
  templateUrl: 'app/html/app.component.html'
})

export class AppComponent implements AfterViewInit {
  ngAfterViewInit() {
    // Your jQuery code goes here
    $('#here').text("HALLO! ^_^");
  }
}
いちにち
  • 417
  • 6
  • 16
  • Hi, can I add reference of jquery.d.ts in any other way like using 'imports' instead of using '///' ? Please suggest. – Shiv Oct 25 '16 at 08:10
7

What I do to solve this issue:

For library doesn't support @types/ and library need to load when document loaded (mean libraries need to add in script tag of document)

  1. Run npm install jquery --save
  2. Add js/css files in scripts or styles of angular-cli.json like

    "scripts": ["../node_modules/path to file", "./assets/path to file"]

For library supported @types/, just run npm install @types/jquery --save-dev

To use the library, add declare var jQuery: any; before annotation @Directive or @Component want to use the lib

P/S: I use angular-cli with webpack in my project, maybe different with systemjs

TDD
  • 161
  • 3
  • 7
  • `declare var $: JQueryStatic` is already the last line of `jquery.d.ts` – Martin Schneider Nov 25 '16 at 15:05
  • something's missing, what is the library required for @types to install? and where in tsconfig does the types go? can you please add these details? – Ayyash Nov 25 '16 at 17:21
  • I found this https://angular.io/docs/ts/latest/guide/typescript-configuration.html – Ayyash Nov 25 '16 at 17:32
  • @Ayyash If library doesn't have @types, just install them by `npm install jquery --save`, add js/css files in `scripts` or `styles` of `angular-cli.json` like `"scripts":["../node_modules/path to file", "./assets/path to file" ]`. In anywhere you want to use it, just add `declare var jQuery: any;` before annotation `@Directive` or `@Component` – TDD Nov 26 '16 at 02:17
2

You must tell where you can find your jQuery typeScript definition. This can be done in a typings.d.ts file where you put your typings like this :

///<reference path="../typings/jquery/jquery.d.ts" />

Or you can install typings via node and let your configuration load it automatically. This is what angular-cli do.

After that, to use jQuery with Angular2 you must understand a fondamental mechanism. Angular2 has it's own dom representation and jQuery manipulates this dom. That's why people say's "Don't use jQuery with Angular2". It's not right. Angular2 come with a solution for this problem. It calls it ControlValueAccessor. The goal of this, is to alert angular when your jQuery plugin modifies the DOM and also let angular notify your plugin when it modify the DOM too.

Let me explain this through an example of date picker calendar.

import { Directive, ElementRef, OnInit, AfterViewInit, Input, forwardRef, OnDestroy } from '@angular/core';
import { Moment } from 'moment';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';


const DATE_PICKER_VALUE_ACCESSOR = {
  provide: NG_VALUE_ACCESSOR,
  useExisting: forwardRef(() => FnCalendarDirective),
  multi: true,

};

@Directive({
  selector: '[fn-calendar]',
  providers: [DATE_PICKER_VALUE_ACCESSOR],
})
export class FnCalendarDirective implements OnInit, AfterViewInit, ControlValueAccessor, OnDestroy {


  @Input() format: string = 'DD/MM/YYYY HH:mm';
  @Input() showClose: boolean = true;
  @Input() sideBySide: boolean = false;
  @Input() ngModel;

  private onTouched = () => { };
  private onChange: (value: string) => void = () => { };

  constructor(private el: ElementRef) {
  }

  ngOnInit() {

  }

  ngAfterViewInit() {
    $(this.el.nativeElement).datetimepicker({
      locale: 'fr',
      sideBySide: this.sideBySide,
      format: this.format,
      showClose: this.showClose,
      icons: {
        time: 'fa fa-clock-o',
        date: 'fa fa-calendar',
        up: 'fa fa-chevron-up',
        down: 'fa fa-chevron-down',
        previous: 'fa fa-chevron-left',
        next: 'fa fa-chevron-right',
        today: 'fa fa-bullseye',
        clear: 'fa fa-trash',
        close: 'fa fa-times'
      },
    }).on('dp.change', event => {
      let date: Moment = (<Moment>(<any>event).date);
      if (date) {
        let value = date.format(this.format);
        this.onChange(value);
      }
    });
    this.writeValue(this.ngModel);
  }

  writeValue(date: string) {
    $(this.el.nativeElement).datetimepicker().data('DateTimePicker').date(date);
  }

  registerOnChange(fn: any) {
    this.onChange = fn;
  }

  registerOnTouched(fn: any) {
    this.onTouched = fn;
  }

  ngOnDestroy() {
    $(this.el.nativeElement).datetimepicker().data('DateTimePicker').destroy();
  }
}

Important things here, are writeValue method that let Angular2 notify your jquery plugin that a change is producing. And registerOnChange, that let you notify Angular2 that your plugin make a change to the DOM.

In conclusion, the key to use jQuery, is to wrap your jQuery plugin inside directive and to implement a CustomValueAccesor to handle communication between your plugin and Angular2.

To find typings, you can use DefinitlyTyped GitHub which is a repository of typings definition from lot of js library.

  [1]: http://blog.thoughtram.io/angular/2016/07/27/custom-form-controls-in-angular-2.html
Scandinave
  • 1,388
  • 1
  • 17
  • 41
1

You should not tie Angular component with jQuery at any price

  1. Load jQuery with <script> tag.
  2. Add jQuery document ready handler.

  $('document').ready((function($) {

      return function() {

        // DOM is ready and $ is a reference to jQuery

        // It's time to things done using $

      };

  })(jQuery));

Pros:

  • Angular component is free from jQuery dependency.
  • Easier to test such a component, maintain and re-use.
  • jQuery code is isolated.

However, if you need to use the jQuery inside the components use services or directives.

If you have a problems with loading a partial views use jQuery event handler on document node and jQuery window load handler.

John Smith
  • 1,091
  • 9
  • 17
0

we can use like as follow:

var jq=require('./jquery.min.js');
.....
export class AppComponent{
  ngOnInit(){
   jq();
   console.log($('body'))  // show:[body, prevObject: r.fn.init[1]]
                           //ok!normal operation!
  }
}
0

Quickest and dirtiest way to do it:

(<any>window).$('.alert')
Leo Moura
  • 61
  • 1
  • 4