childscope 如何处理 ng-if 语句?具体在 <SELECT> 元素中

How does childscope work on an ng-if statement? Specifically in a <SELECT> element

注意:我是这里的新成员,所以我不能直接发表评论并要求澄清。

所以,我的问题是:如果为 select 元素创建子作用域,我该如何解决 ng-if 问题?

我有以下代码:

HTML

        <select id="project-select" 
            ng-if="projects.length > 0"
            ng-options="project.name for project in projects" 
            ng-model="currentProject"
            ng-change="broadcastChange('project-changed', currentProject)">
        </select>

我的控制器设置为以下格式:

function Controller() {
    //Do code stuffz
}
angular
   .module('app')
   .controller('Controller', Controller);

我从 post 了解到 "ng-if" 正在创建一个子作用域。

因此即使模型发生变化,这部分也保持不变,因为它是原始值:(名称只是一个字符串)

<div id="current-project" class="pull-left">
    <strong>Project: </strong>{{currentProject.name}}
</div>

此外,在上述 post 中还有几个选项。

一个。只需更改为:ng-model="$parent.currentProject" 感觉有点 hacky

b。在控制器中设置对象值,我不太确定该怎么做。我觉得这很容易解决,但不知何故我把它弄得太复杂了。

无论如何,现在我只是将 ng-if 更改为 ng-show,这就解决了问题。但是,我正在尝试更深入地理解 Angular,我觉得这个问题可以向我解释得更好一些。提前致谢!

如果您只想show/hide select 元素基于您的 'Controller' 控制器范围内的项目,那么 ng-show 是正确的方法。根据我的经验,当我有条件地加载一个包含大量控件的更大 "partial" 视图时,我使用了 ng-if ).

你是对的。不要在任何生产 Angular 应用中使用 $parent。它使您的模型依赖于视图的结构,这使您的代码难以重构且模块化程度较低。

绑定到对象属性是可行的方法,正如您在 "b" 回答中所建议的那样。在最新版本的 Angular 1.x 中推荐的方法是使用 "controller as" 语法。此方法利用 javascript 中的 "prototypical inheritance"。这里有一个很好的解释:http://javascript.info/tutorial/inheritance

我为您创建了一个 plunker 来演示如何在嵌套范围内绑定到对象属性。看看 "controller as" 语法”。另外,尝试更改输入中 ctrl.testBinding 的值,你会看到它反映在 ng-if 子范围中。我会尝试找到一些链接以更详细地解释这一点。

https://plnkr.co/edit/Gx5xbkJXgzjPSG8kajPR?p=preview

<!DOCTYPE html>
<html >

  <head>
    <link rel="stylesheet" href="style.css">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.7/angular.min.js"></script>
    <script src="script.js"></script>
  </head>

  <body ng-app="testApp">
    <div ng-controller="testCtrl as ctrl">
      <input ng-model="ctrl.testBinding" type="text"/>
      <button ng-click="ctrl.toggle()">toggle show</button>
      <div ng-if="ctrl.show">
         {{ ctrl.testBinding }}
      </div>
    </div>
  </body>

</html>

//script.js
function testController($scope) {
    var vm = this;
    vm.show = true;
    vm.toggle = function(){
      vm.show = !vm.show
    }
}
angular
   .module('testApp', [])
   .controller('testCtrl', testController);

您会发现 Angular 作用域变量是:始终使用点。

这是优秀ng-book

的口头禅

在你的例子中,这意味着:

你有这个代码:

    <select id="project-select" 
        ng-if="projects.length > 0"
        ng-options="project.name for project in projects" 
        ng-model="currentProject"
        ng-change="broadcastChange('project-changed', currentProject)">
    </select>

这意味着您要绑定到名为 $scope.currentProject.

的 $scope 变量

由于 javascript 神秘而令人敬畏的工作方式,当您在子范围内时,不会 得到更新。

值得庆幸的是,解决方案实际上非常简单。相反,像这样创建一个对象:

$scope.myData = {
    currentProject: ''
}

然后在您的标记中,像这样绑定到它:

    <select id="project-select" 
        ng-if="projects.length > 0"
        ng-options="project.name for project in projects" 
        ng-model="myData.currentProject"
        ng-change="broadcastChange('project-changed', myData.currentProject)">
    </select>

瞧。它会更新,即使它在子范围内。

这实际上非常有用,因为您现在可以 "meaningfully" 将变量组合在一起。这里有一些其他的伪代码来证明我的意思:

$scope.projectData = {
    currentProjectID: 1,
    currentProjectTitle: 'My Cool Project',
    projects: [
             {id: 1, name: 'My Cool Project'},
             {id: 2, name: 'Another Project'}
         ],
    someOtherProperty: false
    // ...etc....
}

作为旁注,本文的这一部分可能会有所帮助:http://docstore.mik.ua/orelly/webprog/jscript/ch11_02.htm#jscript4-CHP-11-SECT-2.1