Angularjs - Декорирование контроллеров

Я пытаюсь настроить декоратор для моих контроллеров. Мое намерение состоит в том, чтобы ввести некоторое общее поведение для всех контроллеров в моем приложении.

Я настроил его на работу в Angular 1.2.x, но есть некоторые критические изменения, начиная с версии 1.3.x, которые нарушают код. Теперь появляется ошибка "контроллер не является функцией".

Ниже приведен код для декоратора:

angular.module('myApp', ['ng'], function($provide) {
    $provide.decorator('$controller', function($delegate) {

        return function(constructor, locals) {

                //Custom behaviour code

                return $delegate(constructor, locals);
            }
        })
    });

Angular 1.2.x - http://jsfiddle.net/3v17w364/2/ (работает)
Angular 1.4.x - http://jsfiddle.net/tncquyxo/2/ (сломано)

2 ответа

Решение

В модулях Angular 1.4.x есть метод декоратора, $provide.decorator больше не нужен.

Для API-приложений для исправления обезьян всегда предпочтительнее использовать arguments вместо того, чтобы перечислять их явно, вероятность того, что он сломается, намного меньше.

angular.module('myApp', ['ng']).decorator('$controller', function ($delegate) {
    return function (constructor, locals) {
        var controller = $delegate.apply(null, arguments);

        return angular.extend(function () {
            locals.$scope.common = ...;
            return controller();
        }, controller);
    };
});

Отвечая на мой собственный вопрос.

Пришлось копаться в исходном коде Angular, чтобы выяснить, что происходит.

Экземпляр $controller создается с использованием приведенного ниже кода. Исправление лежало в параметре "позже". Это должно быть установлено в true.

    return function(expression, locals, later, ident) {
      // PRIVATE API:
      //   param `later` --- indicates that the controller's constructor is invoked at a later time.
      //                     If true, $controller will allocate the object with the correct
      //                     prototype chain, but will not invoke the controller until a returned
      //                     callback is invoked.

Выше взято из: https://ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular.js

Обновлен код провайдера:

angular.module('myApp', ['ng'], function($provide) {
    $provide.decorator('$controller', function($delegate) {

 return function(constructor, locals) {

            //Custom behaviour code

            return $delegate(constructor, locals, true);
        }
    })
});

Обновленная скрипка: http://jsfiddle.net/v3067u98/1/

Другие вопросы по тегам