问题 AngularJS如何在替换之前访问指令内的元素


在模板覆盖内容之前,如何从指令中获取input元素?

HTML

<div xxx>
  <input a="1" />
</div>

JS

app.directive('xxx', function(){
  return {
        restrict: 'A',
        template: '<p></p>',
        replace: true, //if false, just leaves the parent div, still no input
        compile: function(element, attrs) {

            console.log(element);

            return function (scope, iElement, iAttrs) {
            }
        }
    };
});

我在角度为1.0.x,我无法通过'=?'传递可选范围参数语法,我希望能够以非常灵活的方式覆盖指令的默认模板的一部分。而不是每次我计划通过指令时添加范围变量或属性,我希望能够提供要使用的整个元素。

编辑 输入必须保留指令的范围,而不是父节点。

编辑 我试图在指令中包含一个部分模板,该指令将覆盖实际模板的一部分。因此,我所包含的部分需要访问指令的范围,而不是父级的。

更新 看来如果我不提供模板或模板URL,而是使用$ templateCache手动替换内容,我可以访问内部元素。我想让角度处理模板和替换,但只是希望能够在它们被替换之前自然地访问指令中的内容。

Plunkr

HTML

  <body ng-controller="MainCtrl">
        <div editable="obj.email">
            <input validate-email="error message" ng-model="obj.email" name="contactEmail" type="text" />
        </div>
  </body>

JS

app.controller('MainCtrl', function($scope) {
  $scope.obj = {
    email: 'xxx'
  };
});

app.directive('editable', function($log){
    return {
        restrict: 'A',
        transclude: true,
        template: '<div ng-show="localScopeVar">{{value}}<div ng-transclude></div></div>',
        scope: {
          value: '=editable'
        },
        link: function(scope) {
          scope.localScopeVar = true;
        }
    };
});


app.directive('validateEmail', function($log){
    return {
        restrict: 'A',
        require: 'ngModel',
        scope: true,
        link: function(scope, el, attrs, ctrl) {
          console.log(attrs['validateEmail']);
        }
    };
});

12964
2018-01-20 17:41


起源

你需要做什么输入元素? - Ilan Frumer
不确定你要做什么。但是如果你想保留input元素,你应该在p元素中使用ng-transclude指令,并在指令代码中设置选项transclude:true。 - michael
它应该是 template: '<p ng-transclude></p>', 如果你使用 transclude: true。 - dfsq


答案:


我相信你在寻找 transclude 功能(链接到1.0.8文档)。你可以看到发生了什么:

app.directive('xxx', function($log){
    return {
        restrict: 'A',
        transclude: true,
        compile: function(element, attrs, transclude) {

            $log.info("every instance element:", element);

            return function (scope, iElement, iAttrs) {

                $log.info("this instance element:", element);

                transclude(scope, function(clone){

                    $log.info("clone:", clone);

                });
            }
        }
    };
});

9
2018-01-20 18:20



@dfsq和@Michael是正确的,如果你想将指令标签之间的元素传入你的模板,那么你应该使用 ng-transclude 在您希望元素放置的元素上。以上内容将直接访问被转换的元素。 - fooby
如果您向此指令添加模板,则它不起作用。在这种情况下,如果transclude为true或false则无关紧要。 - ogc-nick
我补充道 template: "<strong>Testing</strong><div ng-transclude></div>" 在我的答案中的指令和 clone 在transclude函数中仍然记录 <input> - fooby
好的是我看到它确实记录了模板中的内容有关于某些内容的ng-transclude指令。 +1但这个解决方案的问题在于我需要输入元素具有指令的范围,而不是父节点。 - ogc-nick
我不清楚你想要做什么。听起来你想在不使用'='或将其声明为属性的情况下双重绑定孤立范围内的变量?是对的吗? - fooby