0

I have a strange situation (you can read about the context here. I'm not sure that the answer to this question will answer the question in the link, hence two questions.), where I'd like to modify an AngularJS service after the framework has already been loaded. Here's some code we'd like to do:

<script>
document.onload = function () {
    angular.module('common')
        .config(function ($provide) {
            $provide.factory("$exceptionHandler", function () {
                return function (exception) {
                    throw exception;
                };
            });
        });
}
</script>

This works fine when it's not wrapped in a document.onload. But when it's put in an onload, it doesn't seem to have any effect. How can I modify a service in a document.onload?

For what it's worth, I'm on angular 1.2.

georgeawg
  • 48,608
  • 13
  • 72
  • 95
Daniel Kaplan
  • 62,768
  • 50
  • 234
  • 356
  • Why do you need to wrap it in a `document.onload` function? As long as you load this script after you've loaded the angular script and you've defined the `CSSRedesign.common` module, I don't see why you'd need to wait until the document has loaded. But, perhaps I'm missing something that doesn't allow you to control the order in which the scripts load. – David Meza Aug 09 '18 at 20:51
  • @DavidMeza this has to do with TestCafe and how it's able to modify angular code. Check out the link when you have time. – Daniel Kaplan Aug 09 '18 at 20:53
  • I think that what you want you can achieve using `$provide.decorator`, you might want to take a look at the [documentation](https://docs.angularjs.org/guide/decorators) – Luiz Carlos Aug 09 '18 at 21:01
  • Have you already tried defining this as a factory, rather than put it in a config block? My thought is you can lazy load module components after the application has already been bootstrapped, but you can't change the configuration... So instead of `.config()` you can try `.module('common').factory('$exceptionHandler', ...)` – David Meza Aug 09 '18 at 21:19
  • @DavidMeza that didn't work. It has no noticeable effect. – Daniel Kaplan Aug 09 '18 at 21:25

1 Answers1

2

This worked when we tried it:

<script>
    window.onload = function () {
         angular.element(document.body).injector().invoke(function($log) {
             $log.error = function(message) {
                 throw new Error(message)
             };
         });
    }
</script>
Daniel Kaplan
  • 62,768
  • 50
  • 234
  • 356
  • 1
    Nice, I've made a [fiddle](https://jsfiddle.net/3ydbLve6/) to help him with this solution. I've wrapped in a setTimeout to simulate the lazy load and also added the `$rootScope` as dependency of the `invoke` function so once the value change you can call `$rootScope.$evalAsync()` to trigger a digest and update the value immediately. – Luiz Carlos Aug 09 '18 at 21:51