使用双花​​括号的Angularjs插值在ng-if

时间:2017-07-21 21:10:48

标签: angularjs angularjs-scope interpolation angular-ng-if

UPDATE1:开发了可以重现问题的plunker示例。见下文。

我的项目中有一个奇怪的问题,它只出现在一个地方。最后,我能够使用plunker样本重现问题:

http://plnkr.co/edit/JJbq54?p=preview

在上面的示例中,请参阅“使用ng-if”和“不使用ng-if”部分,在输入文本中输入内容,并查看双花括号如何在ng-if下无效,但{ {1}}工作正常。此外,如果您从模板ng-bind中删除check-if-required,问题也就解决了。

以下更多详情:

我有以下HTML5代码块:

sites-and-improvements.html

我知道 <div ng-if="isFullCUSPAP" id="sites_and_imrpovements_comments"> <div class="form-row"> <div class="inputs-group"> <label>WIND TURBINE:</label> <div class="input-binary"> <label> <input type="radio" id="wind_turbine" name="wind_turbine" ng-model="$parent.wind_turbine" value="Yes" force-model-update /> Yes </label> </div> <div class="input-binary"> <label> <input type="radio" id="wind_turbine" name="wind_turbine" ng-model="$parent.wind_turbine" value="No" force-model-update /> No </label> </div> <span ng-bind="wind_turbine"></span> <span>wind_turbine = {{wind_turbine}}</span> </div> </div> </div> 会创建一个新的子范围。请参阅上面的代码,范围变量ng-if。仅在此HTML5文件中,大括号wind_trubine不起作用。但是,如果我使用{{}},它可以正常工作。在其他HTML5文件中,我没有任何问题。这个HTML5使用指令实现如下:

ng-bind

而且,简单地说,我把它放在父母身上,如下所示:

app.directive('sitesAndImprovements', function() {
    return {
        restrict: 'E',
        replace:true,
        templateUrl: '<path-to-file>/site-and-improvments.html',
        link: function (scope, elem, attrs) {
            //Business Logic for Sites and Improvements
        }
    } 
})

我能看到的唯一区别是,这个实现有两层嵌套<sites-and-improvements></sites-and-improvements> ,如下所示:

ng-if

根据评论,我使用了<div ng-if="some_expression"> ... ... <sites-and-improvements></sites-and-improvements> ... ... </div> 符号并相应地定义了controller As。请参阅下面的快照。如果MainController与两个级别嵌套,则似乎存在问题。范围变量完全混淆。使用ng-if和双花括号,我得不到相同的结果。

enter image description here

enter image description here enter image description here

enter image description here

如果您检查上述快照,即使我使用了ng-bind表示法,与使用controller As进行插值相比,您会看到ng-bind给出不同的结果。

我甚至在链接函数中将{{}}的默认值更改为如下设置:

wind_turbine

我注意到在页面加载时,一切看起来都很好,但是当我使用鼠标更改输入元素scope.MainController.wind_turbine = 'Yes'; 的值时,除了使用wind_trubine的引用之外,所有相关引用都会正确更新。

也许这是因为{{}}有两个嵌套级别?

感谢您的反馈。

塔雷克

2 个答案:

答案 0 :(得分:2)

replace: true指令中删除sites-and-improvements

app.directive('sitesAndImprovements', function() {
    return {
        restrict: 'E',
        ̶r̶e̶p̶l̶a̶c̶e̶:̶t̶r̶u̶e̶,̶
        templateUrl: 'site-and-improvments.html',
        link: function (scope, elem, attrs) {
          //debugger;
        }
    } 
})

正在与check-if-required指令作斗争:

app.directive('checkIfRequired', ['$compile', '$timeout', function ($compile, $timeout) {
  return {
    priority: 2000,
    terminal: true,
    link: function (scope, el, attrs) {
      el.removeAttr('check-if-required');

      $timeout(function(){
        //debugger;
        $(':input', el).each(function(key, child) {
          if (child && child.id === 'test_me') {
                angular.element(child).attr('ng-required', 'true');
                }
          if (child && child.id === 'testInput1') {
            //debugger;
                //angular.element(child).attr('ng-required', 'true');
                }
        });
            $compile(el, null, 2000)(scope);
      })
    }
  };
}])

DEMO on PLNKR

replace:true is Deprecated

来自文档:

  

replace([已弃用!],将在下一个主要版本中删除 - 即v2.0)

     

指定模板应替换的内容。默认为false

     
      
  • true - 模板将替换指令的元素。
  •   
  • false - 模板将替换指令元素的内容。
  •   

- AngularJS Comprehensive Directive API - replace deprecated

来自GitHub:

  

Caitp--它被弃用了,因为replace: true存在已知的非常愚蠢的问题,其中一些问题无法以合理的方式得到解决。如果你小心并避免这些问题,那么对你有更多的权力,但为了新用户的利益,告诉他们更容易,这会让你头疼,不要这样做&#34;。

- AngularJS Issue #7636

有关详细信息,请参阅Explain replace=true in Angular Directives (Deprecated)

答案 1 :(得分:0)

AngularJS团队发布的另一个解决方案:

https://github.com/angular/angular.js/issues/16140#issuecomment-319332063

基本上,他们建议将link()函数转换为使用compile()函数。这是更新代码:

app.directive('checkIfRequired', ['$compile', '$timeout', function ($compile, $timeout) {
  return {
    priority: 2000,
    terminal: true,
    compile: function (el, attrs) {
      el.removeAttr('check-if-required');
      var children = $(':input', el);
      children.each(function(key, child) {
        if (child && child.id === 'test_me') {
            angular.element(child).attr('ng-required', 'true');
                }
      });
            var compiled = $compile(el, null, 2000);
            return function( scope ) {
                compiled( scope );
            };
    }
  };
}]).directive('sitesAndImprovements', function() {
    return {
        restrict: 'E',
        replace:true,
        templateUrl: 'site-and-improvments.html'
    } 
});

我对此解决方案的主要问题是我使用传递给scope函数的link()参数。例如,在上面的.each()循环中,我需要使用{{<angular expre>}}获取基于插值的元素ID的值。

因此,我尝试在pre-link函数中使用post-linkcompile,其中scope可用。我注意到,执行在ng-if时删除了带有pre-link的部分,然后在此之后不久添加。因此,我必须使用$watch来监视子项的更改,以便在需要时运行所需的过程。我开发了这个plunker样本:

http://plnkr.co/edit/lsJvhr?p=preview

即使经过所有这些努力,问题也未得到解决。因此,类似案例的底线是,如果您需要使用范围,则必须删除replace: true

任何反馈都将不胜感激。

塔雷克