Различия по шкале AngularJS между 1.0.x и 1.2.x

Начиная с выпуска следующего стабильного AngularJS, я переношу свое приложение с версии 1.0.8 на 1.2.

В AngularJS 1.0.8 можно было создать изолированную область для таких директив, как follow. Затем директива будет использовать свою собственную функцию test() вместо функции контроллера test().

HTML

<my-dialog property="something">
    <button ng-click="test()">Load Test</button>
    Check out the test: "{{ testMessage }}"
</my-dialog>

Javascript

  .controller('Ctrl', function(scope) {
    scope.test = function () {
       scope.testMessage = 'CTRL Test loaded! Whooops.';
    }
  })

  .directive('myDialog', function() {
    return {
      restrict: 'E',
      scope: {
          property: '='
      },
      link: function(scope) {
          scope.test = function () {
            scope.testMessage = 'Isolated Test loaded. Yes!';
          }
      }
    };

В AngularJS 1.2 это поведение больше не работает. Нажатие кнопки запускает функцию управления test().

См. это сравнение jsFiddle:

Что именно имеет изменения и как я могу воспроизвести старое поведение?

Примечание

Я понял, что могу разместить шаблон директив внутри дополнительного HTML файла или скомпилировать его как строку, чтобы заставить ее работать (jsFiddle), но в моем случае это слишком много, так как шаблон исправлен и разбиение HTML на несколько частичных файлов HTML - это проблема.

ИЗМЕНИТЬ

@elclanr answer отлично работает, когда нет других свойств для совместного использования. Я обновил jsFiddle, чтобы передать какое-то произвольное свойство. Как мне теперь идти?

Ответ 1

Похоже, что это предполагаемый результат взломанного изменения: github.com/ angular/angular.js/commit/... Который был вытащен в 1.2.0 (после rc3) (https://github.com/angular/angular.js/blob/master/CHANGELOG.md - см. Первое изменение прерывания для компиляции 1.2.0 - $):

Исправлена ​​проблема с изоляцией, протекающей по всему месту в других директивах одного и того же элемента.

Изолировать область теперь доступна только для директивы изоляции, которая запросила ее и ее шаблон.

Директива non-isolate не должна обладать изолированной областью директивы изоляции для одного и того же элемента, вместо этого они получат исходную область (которая является родительской областью только что созданной области выделения).

Также ознакомьтесь с этим обсуждением: github.com/angular/angular.js/issues/4889

Примечательно: "Область изоляции применяется только к шаблону, но не к разметке, которая не была внесена директивой. До того, как 1.2 изолировать области, была ошибка, вызвавшая такой утечек. Точка изоляции что он применяется только к директиве, которая ее объявила, а не к другим директивам или разметке." (из tbosch)

До 1.2.0 все, что находится на одном и том же элементе DOM, разделяет ту же область. Итак, 1.2.0 существенно изменяет порядок работы директив с областями выделения.

Ответ 2

Настройка scope: true должна решить проблему. http://jsfiddle.net/rug3J/1. Я бы также посоветовал следовать соглашению и называть его scope, а не $scope, когда он не был вложен:

.directive('myDialog', function() {
  return {
    restrict: 'E',
    scope: true,
    link: function(scope) {
      scope.test = function () {
        scope.testMessage = 'Isolated Test loaded. Yes!';
      }
    }
  };

Ответ 3

Чтобы объединить обычную разметку с конкретными шаблонами и функциями директивы, нужно использовать опцию transclude, например:

Смотрите: jsFiddle

HTML

<div ng-app="myApp">
    <div ng-controller="Ctrl">
        <my-directive property="{{ something }}">
            <p>{{ text }}</p>
        </my-directive>
    </div>
</div>

Javascript

.controller('Ctrl', ['$scope', function($scope) {
    $scope.text = 'This is a controllers text.';
    $scope.something = 'This is another controllers text.';
}])
.directive('myDirective', function() {
    return {
        restrict: 'E',
        transclude: true,
        template: '<button ng-click="test()">Fire directives function</button><div ng-transclude></div><p>{{ property }}</p>',
        scope: {
            property: '@'
        },
        link: function(scope) {
            scope.test = function () {
                scope.property = 'Loaded directives text.';
            }
        }
    };
});

Это отлично работает для меня сейчас, но следует отметить, что нельзя переопределять существующие свойства области.