Область видимости не связана с добавлением нового элемента на этапе компиляции

В приведенном ниже коде я пытаюсь добавить кнопку на этапе компиляции и назначил ng-click методу из области. Во время фазы связывания через отладку я обнаружил, что "compiledEle" содержит кнопку, а затем ng-click не вызывает метод области.

angular.module("app", [])
        .controller("ctrl1", function($scope){
            $scope.myModelObj = {
                name: 'Ratnesh',
                value: 100
            };
        })
        .directive("dirOne",function($compile){
            return {
                restrict: 'E',
                scope: {
                    myModel : "="
                },
                compile: function(ele){
                    ele.append("<button ng-click=\"showAlert()\">click ME</button>")
                    return {
                        post: function($scope, compiledEle){
                            $scope.showAlert = function(){
                                alert("The button is clicked");
                            };
                        }
                    };
                }

            };
        });

В чем причина того, что метод области не привязывается к кнопке, добавленной на этапе компиляции, но то же самое можно связать, если я нахожусь в шаблоне /templateUrl. Также метод get bind, если на этапе связывания мы включаем строку:

$компиляции (compiledEle.contents()) ($ масштаб);)

Также он будет привязан к методу, если вместо добавления "$ scope.showAlert" в фазе связывания мы уже имеем метод в контроллере!!!

    .controller("ctrl1", function($scope){
                $scope.myModelObj = {
                    name: 'Ratnesh',
                    value: 100
                };
                $scope.showAlert = function(){
                    alert("The button is clicked");
                };
            })

метод компиляции заключается в том, чтобы манипулировать DOM и фазой связывания связывать скомпилированный html с областью. Таким образом, мы можем добавить новый элемент в DOM во время компиляции и метод новой области в фазе связывания, так где же мое ожидание становится неправильным?

Ответ 1

Проблема заключается в том, что ваша функция компиляции не имеет доступа к области экземпляра элемента еще в момент компиляции.

Вы хотите, чтобы ng-click выполнял метод области экземпляра, который еще не доступен при компиляции шаблона.

Я добавил комментарии к коду, чтобы проиллюстрировать, что происходит:

app.directive("fromCompile", function($compile) {
  return {
    restrict: 'E',
    scope: {},
    compile: function(tElement) {

      // When AngularJS compiles the template element, it does not have
      // access yet to the scope of the iElement, because the iElement does
      // not exist yet.
      // You want ng-click to execute a method of the iElement scope
      // which does not exist here yet because you are modifying the
      // template element, not the instance element.
      // This will not give you the effect you are looking for because it
      // will execute the function in a scope higher up the scope hierarchy.
      tElement.append('<button ng-click=\"showAlert()\">Using compile: click me (this will not work correctly)</button>');
      return {
        post: function(scope, iElem, iAttrs) {
          scope.showAlert = function() {
            alert("This button was added using compile");
          };
        }
      };
    }
  };
});

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

app.directive("fromTemplate", function($compile) {
  return {
    restrict: 'E',
    scope: {},
    template: "<button ng-click=\"showAlert()\">Using template: click me (this will work)</button>",
    link: function(scope, iElem, iAttrs) {
      scope.showAlert = function() {
        alert("This button was added using template");
      };
    }
  };
});

Скомпилируйте шаблон вручную самостоятельно в функции ссылки экземпляра элемента (потому что вы можете получить доступ к правильной области там):

app.directive("fromLink", function($compile) {
  return {
    restrict: 'E',
    scope: {},
    link: function(scope, iElem, iAttrs) {
      var linkFn = $compile("<button ng-click=\"showAlert()\">Using link: click me (this will work)</button>");
      var button = linkFn(scope);
      iElem.append(button);
      scope.showAlert = function() {
        alert("The button was added using $compile in link function");
      };
    }
  };
});

Я создал Plunk со всем кодом и рабочими версиями прямо здесь.

Надеюсь, что это поможет!