javascript - 使用子作用域的数据作为父作用域的 ng-repeat

标签 javascript jquery angularjs

添加了更新 2,见下文

首先,这是我正在使用的框架的起点(并且需要修复):

// index.html
<!doctype html>

<html ng-app="myApp">
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
  <script src="index.js"></script>

  <body>
    <div ng-controller="outerController">
      <div id="copy"></div>
      <hr>
      <div id="src" ng-controller="innerController">
        <table>
          <th>Name</th>
          <th>Type</th>
          <tbody>
            <tr ng-repeat="poke in pokemon">
              <td>{{ poke.name }}</td>
              <td>{{ poke.type }}</td>
            </tr>
            <tr>
              <td>Pikachu</td>
              <td>Electric</td>
            </tr>
          </tbody>
        </table>
      </div>
    </div>
  </body>
</html>

// index.js
var app = angular.module("myApp", []);

app.controller("innerController", function($scope) {
  $scope.pokemon = [{
    name: "Bulbasaur",
    type: "Grass/Poison"
  }, {
    name: "Charmander",
    type: "Fire"
  }, {
    name: "Squirtle",
    type: "Water"
  }];
});

app.controller("outerController", function($scope) {
  $("#copy").html($("#src").html());
});

正如您所看到的,子 Controller 将通过 ng-repeat 从其作用域的数据生成一个表。这一步就成功了。下一步是父 Controller 将内部 HTML 从 src 复制粘贴到 copy 。目的是让 copy 包含由 angularJS 在 src 内完全生成的完整表的副本。

此步骤失败。仅表格标题和静态皮卡丘行可见。经过一些研究后,我确信这是因为 pokemon 位于子 Controller 的范围内,父 Controller 无法访问该范围。复制到 copy 容器中的 HTML 包含整个 ng-repeat 指令。这个复制的指令位于父作用域内,其中 $scope.pokemon 不存在/不包含任何数据,这就是为什么 ng-repeat 中的 copy 没有生成任何内容。

我无法将数据放入父 Controller 中。在我的实际应用中,系统采用了模块化设计。每个内部 Controller 代表一个模块,该模块从服务器提取自己的数据集。存在多个网页(以外部 Controller 为代表),这些网页与模块具有多对多的关系,并且每个网页中的模块的构成需要可修改。这意味着模块使用的数据必须包含在其自身内。

我该如何纠正这个问题?

更新 1:已编辑。我发布了一个使用 $emit$on 的示例,但罗伯特的示例应该被认为是正确的,因为我对此还很陌生。引用他的回答。

更新 2:在测试 Alvaro Vazquez 和 Robert 的解决方案时,我已经确定了具体的根本原因。当执行 $("#copy").html($("#src").html()); 时,复制的 ng-repeat 要么在任何数据传输到 outerController 之前执行,要么从未执行过。最后,修改我最初在上面所做的事情使其完全正常工作:

var app = angular.module("myApp", []);

$(function() {
  $("#copy").html($("#src").html());
});

app.controller("innerController", function($scope) {
  $scope.pokemon = [{
    name: "Bulbasaur",
    type: "Grass/Poison"
  }, {
    name: "Charmander",
    type: "Fire"
  }, {
    name: "Squirtle",
    type: "Water"
  }];
});

app.controller("outerController", function($scope) {
  $scope.pokemon = [{
    name: "Bulbasaur",
    type: "Grass/Poison"
  }, {
    name: "Charmander",
    type: "Fire"
  }, {
    name: "Squirtle",
    type: "Water"
  }];
});

随着该特定语句的位置发生变化,剩下的就是将数据传输到 outerController ,此时 Alvaro 和 Robert 的解决方案都有效。

顺便说一句,我认为有些人建议不要使用 $("#copy").html($("#src").html()); 。正如我在评论中部分描述的那样,我正在开发的实际应用程序由多个网页组成,每个网页都包含自己的 outerController 。每个 innerController 都位于其自己单独的 HTML 文件中,通过 include 指令添加到 src 中。 outerController 复制 src 的内部 HTML,将其传递给第三方库,该第三方库将其粘贴到 copy 并控制其视觉布局。 $("#copy").html($("#src").html()); 实际上是第三方库实现的一部分,所以我无法更改它。因此,使用此语句是一项要求。

当我回家并且可以方便地使用 PC 键盘时,我会将上述内容作为解决方案发布。同时,如果您有更好的解决方案,请随时推荐,谢谢!

最佳答案

我认为你应该使用 Angular 服务。

声明服务

首先,您应该声明一个服务,它将数据“提供”给应用程序的其余部分。为了简单起见,我将只展示一个返回预定义数组的方法,但您可以在此处从服务器获取数据。

app.service('pokemonService', function () {
    return {
        getPokemon: function () {
            return [{
                  name: "Bulbasaur",
                  type: "Grass/Poison"
              }, {
                  name: "Charmander",
                  type: "Fire"
              }, {
                  name: "Squirtle",
                  type: "Water"
              }];
        }
    };
});

使用 Controller 中的服务

然后,您可以在任何 Controller 上使用该服务,将其作为任何其他预定义的 Angular 服务注入(inject):

app.controller('innerController', function($scope, pokemonService) {
    $scope.pokemon = pokemonService.getPokemon();
});

app.controller('outerController', function($scope, pokemonService) {
    $scope.outerPokemon = pokemonService.getPokemon();
});

在 View 中显示数据

最后,您可以在您想要的任何模板/模板的一部分中列出所有神奇宝贝:

<!doctype html>

<html ng-app="myApp">
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
  <script src="index.js"></script>

  <body>
    <div ng-controller="outerController">
      <div id="copy">
          <!-- Here you can also list the pokémon from your outerController, maybe this time in a list -->
          <ul>
              <li ng-repeat="poke in pokemonOuter">
                  {{ poke.name }} - <span class="type">{{ poke.type }}</span>
              </li>
          </ul>
      </div>
      <hr>
      <div id="src" ng-controller="innerController">
        <table>
          <th>Name</th>
          <th>Type</th>
          <tbody>
            <tr ng-repeat="poke in pokemon">
              <td>{{ poke.name }}</td>
              <td>{{ poke.type }}</td>
            </tr>
          </tbody>
        </table>
      </div>
    </div>
  </body>
</html>

总结

正如您所看到的,根本不需要搞乱 DOM。如果你使用 AngularJS,你应该以 Angular 的方式做事,直接使用 DOM 根本不是 Angular 的方式。相反,您应该将所有数据和业务逻辑放入服务中,然后在 Controller 中使用这些服务来检索该数据并将其传递给 View 。

关于javascript - 使用子作用域的数据作为父作用域的 ng-repeat,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39350426/

相关文章:

javascript - 为什么这个下拉菜单会移动另一个元素?

javascript - 相互使用 Razor 和 javascript

javascript - 在 ViewportChecker 上 5 秒后删除类

javascript - 将来自innerjoin的数据存储在javascript数组上

javascript - Angular 中的过滤和 $http promise

javascript - JS 表单验证问题

javascript - 我需要向 div 添加 2 个类,一个是字符串,另一个来自变量

javascript - jQuery:展开 HTML 字符串中的元素

angularjs - 如何使用 ngGrid 进行客户端分页?

asp.net-mvc - angularjs和mvc5之间沟通的最佳方式是什么?