范围不会与在编译阶段添加的新元素相关联 [英] Scope doesn't get associated with new element added in compile phase

查看:12
本文介绍了范围不会与在编译阶段添加的新元素相关联的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在下面的代码中,我试图在编译阶段添加一个按钮,并将 ng-click 分配给作用域中的方法.在链接阶段,通过调试我发现compiledEle"包含按钮,然后ng-click也没有调用范围方法.

angular.module("app", []).controller("ctrl1", function($scope){$scope.myModelObj = {name: 'Ratnesh',价值:100};}).directive("dirOne",function($compile){返回 {限制:'E',范围: {我的模型:="},编译:函数(ele){ele.append("<button ng-click=\"showAlert()\">点击我</button>")返回 {帖子:函数($scope,compiledEle){$scope.showAlert = function(){alert("按钮被点击了");};}};}};});

scope 方法没有绑定到在编译阶段添加的按钮,但如果我在模板/templateUrl 中添加按钮,也可以绑定相同的方法,这可能是什么原因?如果在链接阶段我们包含一行,则方法 get bind :

<块引用>

$compile(compiledEle.contents())($scope);)

如果不是在链接阶段添加$scope.showAlert",我们已经在控制器中拥有该方法,它将被绑定到该方法!!!

 .controller("ctrl1", function($scope){$scope.myModelObj = {name: 'Ratnesh',价值:100};$scope.showAlert = function(){alert("按钮被点击了");};})

compile 方法是做 DOM 操作,链接阶段是将编译后的 html 链接到作用域.所以我们可以在编译阶段向 DOM 添加新元素,在链接阶段添加新的作用域方法,那么我的期望哪里出错了?

解决方案

问题是你的编译函数在编译的时候还没有访问元素实例的作用域.

您希望 ng-click 执行实例范围的方法,该方法在编译模板时尚不可用.

我在代码中添加了注释来说明发生了什么:

app.directive("fromCompile", function($compile) {返回 {限制:'E',范围: {},编译:函数(tElement){//当 AngularJS 编译模板元素时,它没有//还没有访问 iElement 的作用域,因为 iElement 会//还不存在.//您希望 ng-click 执行 iElement 范围的方法//这里还不存在,因为你正在修改//模板元素,而不是实例元素.//这不会给你你正在寻找的效果,因为它//将在作用域层次结构更高的作用域中执行函数.tElement.append('<button ng-click=\"showAlert()\">使用编译:点击我(这将无法正常工作)</button>');返回 {帖子:功能(范围,iElem,iAttrs){scope.showAlert = 函数(){alert("这个按钮是使用编译添加的");};}};}};});

要解决这个问题,您可以使用模板让AngularJS自动为您编译模板:

app.directive("fromTemplate", function($compile) {返回 {限制:'E',范围: {},模板: "<button ng-click=\"showAlert()\">使用模板:点击我(这会起作用)</button>",链接:功能(范围,iElem,iAttrs){scope.showAlert = 函数(){alert("此按钮是使用模板添加的");};}};});

或者在元素实例的链接函数中自己手动编译模板(因为你可以在那里访问正确的范围):

app.directive("fromLink", function($compile) {返回 {限制:'E',范围: {},链接:功能(范围,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 = 函数(){alert("该按钮是在链接函数中使用 $compile 添加的");};}};});

我已经创建了一个包含所有代码和工作版本的 Plunk 就在此处.>

希望有帮助!

In below code i am trying to add a button at compile phase, and assigned ng-click to a method from scope. During linking phase, through debugging I found the "compiledEle" contains the button, then also ng-click doesn't call the scope method.

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");
                            };
                        }
                    };
                }

            };
        });

What could be the reason that the scope method doesn't get binded to button added during compile phase, but the same can be binded if I button in the template/templateUrl. Also the method get bind if in the linking phase we include a line:

$compile(compiledEle.contents())($scope);)

Also it will be get bind to the method if instead of adding "$scope.showAlert" in linking phase , we already have the method in controller !!!

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

compile method is to do DOM manipulation and linking phase is to link compiled html to scope. So we can add new element to DOM during compile and new scope method in linking phase, so where is my expectation is getting wrong?

解决方案

The problem is that your compile function does not have access to the scope of the element instance yet at the moment of compilation.

You want ng-click to execute a method of the instance scope, which is not yet available when the template is compiled.

I have added comments to the code to illustrate what happens:

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");
          };
        }
      };
    }
  };
});

To solve the problem you can either use a template to let AngularJS automatically compile the template for you:

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");
      };
    }
  };
});

Or compile the template manually yourself in the link function of the element instance (because you can access the correct scope there):

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");
      };
    }
  };
});

I have created a Plunk with all code and working versions right here.

Hope that helps!

这篇关于范围不会与在编译阶段添加的新元素相关联的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆