2016-03-02 33 views
0

在下面的代码中,我试图在编译阶段添加一个按钮,并且指定了ng作为范围的方法。 在链接阶段,通过调试,我发现“compiledEle”包含按钮,那么ng-click也不会调用scope方法。作用域没有与在编译阶段添加的新元素相关

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进行绑定,如果我按钮的原因。此外该方法获得绑定如果链接阶段,我们有一句台词:

$编译(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添加新的元素,在链接阶段添加新的范围方法,那么我的期望会出现什么问题呢?

+0

尝试在预编译时附加它 – charlietfl

+0

尝试了前后两者,结果相同。 –

回答

3

问题是编译函数在编译时尚未访问元素实例的作用域。

您希望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,其中包含所有代码和工作版本right here

希望有帮助!

+0

非常感谢!对于你的回答,我在阅读你的答案后有一个疑问,当你说 - “为了解决问题,你可以使用一个模板让AngularJS自动为你编译模板”,这是否意味着,在compile()之后编译angularjs和link()方法? 汇编的流程是什么? compile(),link,angularjs-compilation是什么情况? 将DOM作为模板添加到compile()方法之间有什么区别? –

+0

下面的代码也工作,在模板而不是添加按钮的地方,我只是添加一些文本的跨度,然后你的解释如何保持真实,因为仍然在下面的代码中,我在编译阶段添加按钮! http://plnkr.co/edit/ppAdIyv5by6nIMoMDpsP 刚刚添加:'template:“就像那个”,“ –