10

Using a 3rd party js library in my .net core asp angular app. The library applies it's logic in the $(document).ready method. So im having an issue where the libraries aren't applying correctly on a angular route change because the $(document).ready method doesn't fire.

I've referenced the external js library in my angular-cli scripts section.

I opened the 3rd party js file and added a method to it that calls the same logic that they are calling in the document ready. Im just struggling to find a way to call that method from my angular typescript component.

I've created a simple cut down js file to test it out and simplify the problem. I have the following Tester.js which is referenced in my -angular-cli.json under the scripts tag:

(function ($) {
    "use strict";

    $(document).ready(function () {        
        CallMe();
    });

    function CallMe(){
         console.log('HEY I GOT CALLED');
    }

 })(jQuery);

Im wanting to be able to call the CallMe() method when from inside a ts component file. The CallMe() gets fired once as expected on the document.ready event but I need to work out how to call this ad hoc from within my ts scripts.

Any ideas?

poke
  • 369,085
  • 72
  • 557
  • 602
Matt
  • 3,305
  • 11
  • 54
  • 98
  • 1
    I think the js you are including gets called after the ready event is triggered by the browser. So the event must be registered even before the view is initialised. Try executing the library inside the constructor of the root component. It should register the event before the DOM is constructed. – Damodharan J Jul 01 '18 at 12:38
  • Open an issue on the lib or better: Fork and propose a fix to export the function as desired – maxime1992 Jul 02 '18 at 19:07
  • Mixing Angular and jQuery is never a good idea. Look for a different library or consider implementing it yourself inside Angular direclty. – poke Jul 02 '18 at 19:36

1 Answers1

4

Step 1

Check if the external library is available on npm. If so you may be able to import the desired function rather than altering a vendored file.

For example, it may provide an API such that:
YourTsComponent.ts

const CallMe = require('library').CallMe
// or
import { CallMe } from 'library'

// on route change
CallMe()

If something like that is available, great, otherwise...

Step 2

Confirm your theory with a global (attach CallMe to window temporarily). If your theory is correct, you should be able to get the desired behavior by calling this global variable on route change.

Tester.js

(function($) {
  "use strict";

  $(document).ready(function() {
    CallMe();
  });

  function CallMe() {
    console.log('HEY I GOT CALLED');
  }

  // TODO - remove (test only)
  window._CallMe = CallMe
})(jQuery);

YourTsComponent.ts

// on route change
window._CallMe()

If that doesn't work, you must reevaluate your theory.

but if it does ...

Step 3

Convert the vendored library to a module that can be consumed by your app. Your mileage may vary based on what (if any) module system you are using. For example, if you are using require.js:

Tester.js

(function(factory) {
  if (typeof define === 'function' && define.amd) {
    // AMD
    define(['jquery'], factory);
  } else if (typeof exports === 'object') {
    // CommonJS
    factory(require('jquery'));
  } else {
    // Browser globals
    factory(jQuery);
  }
}(function($) {
  "use strict";

  function CallMe() {
    console.log('HEY I GOT CALLED');
  }

  $(document).ready(function() {
    CallMe();
  });

  return CallMe
}));

YourTsComponent.ts

const CallMe = require('/path/to/tester.js')

// on route change
CallMe()

If you're not keen on re-writing a vendored library

You may consider overriding .ready's default behavior so that it may be retriggered. There Are a few answers here if you want to go this route, but be warned, overriding default jQuery behavior is probably much more error prone than editing a single vendored file.

Damon
  • 4,216
  • 2
  • 17
  • 27