90
votes

Simple question, I hope.

I want to run a script when the Angular2 equivalent of $document.ready() is fired. What is the best way to achieve this?

I've tried putting the script at the end of index.html, but as I found out, this doesn't work! I take it that it has to go in some kind of component declaration?

Is it possible to run load the script from a .js file?

EDIT - Code:

I've got the following js and css plugins injected into my application (from the Foundry html theme).

    <link href="css/themify-icons.css" rel="stylesheet" type="text/css" media="all" />
    <link href="css/bootstrap.css" rel="stylesheet" type="text/css" media="all" />
    ...


    <script src="js/jquery.min.js"></script>
    <script src="js/bootstrap.min.js"></script>
    <script src="js/flexslider.min.js"></script>
    ...
    <script src="js/scripts.js"></script> //This initiates all the plugins

As noted, the scripts.js 'instantiates' the whole thing, and thus is needed to be run after Angular is ready. script.js

Got it working:

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

@Component({
  selector: 'home',
  templateUrl: './components/home/home.html'
})
export class HomeCmp implements AfterViewInit {


    ngAfterViewInit() {
       //Copy in all the js code from the script.js. Typescript will complain but it works just fine
    }
6
after some hours of research, I still got the same issue. > Module not found: Error: Can't resolve '@types/jquery' I installed it with npm install --save -D @types/jquery, then when i try to import it in the Module (due to the fact that i got a Message from the toolbox that it doesn't know $ from jQuery) in my Component.ts it says my first message ! I hope my explanations are corrects Thanks again for all the help this community gave to me ! btw : This is my first real message so I hope to write a good one - Alexandre Saison

6 Answers

37
votes

You can fire an event yourself in ngOnInit() of your Angular root component and then listen for this event outside of Angular.

This is Dart code (I don't know TypeScript) but should't be to hard to translate

@Component(selector: 'app-element')
@View(
    templateUrl: 'app_element.html',
)
class AppElement implements OnInit {
  ElementRef elementRef;
  AppElement(this.elementRef);

  void ngOnInit() {
    DOM.dispatchEvent(elementRef.nativeElement, new CustomEvent('angular-ready'));
  }
}
66
votes

Copying the answer from Chris:

Got it working:

import {AfterViewInit} from 'angular2/core';    

export class HomeCmp implements AfterViewInit {    

    ngAfterViewInit() {
       //Copy in all the js code from the script.js. Typescript will complain but it works just fine
    }
17
votes

I went with this solution so I didn't have to include my custom js code within the component other than the jQuery $.getScript function.

Note: Has a dependency on jQuery. So you will need jQuery and jQuery typings.

I have found this is a good way to get around custom or vendor js files that do not have typings available that way TypeScript doesn't scream at you when you go to start your app.

import { Component,AfterViewInit} from '@angular/core'

@Component({
  selector: 'ssContent',
  templateUrl: 'app/content/content.html',
})
export class ContentComponent implements AfterViewInit  {

  ngAfterViewInit(){
    $.getScript('../js/myjsfile.js');
  }
}

Update Actually in my scenario the OnInit lifecycle event worked better because it prevented the script from loading after the views were loaded, which was the case with ngAfterViewInit, and that cause the view to show incorrect element positions prior to the script loading.

ngOnInit() {
    $.getScript('../js/mimity.js');
  }
6
votes

the accepted answer is not correct, and it makes no sens to accept it considering the question

ngAfterViewInit will trigger when the DOM is ready

whine ngOnInit will trigger when the page component is only starting to be created

4
votes

In order to use jQuery inside Angular only declare the $ as following: declare var $: any;

0
votes

In your main.ts file bootstrap after DOMContentLoaded so angular will load when DOM is fully loaded.

import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';

import { AppModule } from './app/app.module';
import { environment } from './environments/environment';

if (environment.production) {
  enableProdMode();
}



document.addEventListener('DOMContentLoaded', () => {
  platformBrowserDynamic().bootstrapModule(AppModule)
  .catch(err => console.log(err));
});