更新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());
});
因此,正如您所看到的,子控制器将通过ng-repeat
从其作用域的数据生成一个表。这一步成功。下一步是父控制器复制粘贴内部HTML从src
到copy
。目的是让copy
在src
中包含一个完全由angularJS生成的完整表的副本。
此步骤失败。只有表头和静态皮卡丘行是可见的。在做了一些研究之后,我确信这是因为pokemon
在父控制器无法访问的子控制器范围内。复制到copy
容器中的HTML包含了整个ng-repeat
指令。这个复制的指令在父作用域内,其中$scope.pokemon
不存在/不包含任何数据,这就是为什么copy
中的ng-repeat
没有生成任何内容。
我不能把数据放在父控制器中。在我的实际应用中,系统采用了模块化设计。每个内部控制器代表一个模块,它从服务器提取自己的一组数据。有多个与模块有多对多关系的网页(由外部控制器表示),每个网页中的模块组成需要修改。这意味着模块所使用的数据必须包含在其自身中。
我该如何纠正这个问题?
Update 1:已编辑。我发布了一个使用$emit
和$on
的例子,但罗伯特的例子应该被认为是正确的,因为我对这个还很陌生。参考他的回答
更新2:在测试Alvaro Vazquez的&罗伯特的解决方案,我已经确定了具体的根本原因。当$("#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());
实际上是第三方库实现的一部分,所以我不能改变它。因此,使用这个语句是必需的。
我认为你应该利用angular的服务。
声明服务
首先,你应该声明一个服务,它将为应用程序的其余部分"提供"数据。为了简单起见,我将只展示一个返回预定义数组的方法,但是您可以在这里从服务器获取数据。
app.service('pokemonService', function () {
return {
getPokemon: function () {
return [{
name: "Bulbasaur",
type: "Grass/Poison"
}, {
name: "Charmander",
type: "Fire"
}, {
name: "Squirtle",
type: "Water"
}];
}
};
});
在控制器中使用服务
然后,你可以在任何控制器上使用该服务,把它像其他预定义的angular服务一样注入:
app.controller('innerController', function($scope, pokemonService) {
$scope.pokemon = pokemonService.getPokemon();
});
app.controller('outerController', function($scope, pokemonService) {
$scope.outerPokemon = pokemonService.getPokemon();
});
显示视图中的数据
最后,你可以在你想要的模板的任何模板/部分中列出所有的poksammon:
<!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的方式。相反,您应该将所有数据和业务逻辑放入服务中,然后在控制器中使用这些服务来检索数据并将其传递给视图。
Angular中的作用域使用原型继承,所以子作用域可以访问父作用域的属性,但父作用域不能访问子控制器的属性。
你可以使用一个服务来共享数据,或者使用$emit来向上发送事件(向上直到根范围)。
我为您创建了一个plnkr,向您展示如何使用emit(您可以在这里找到它)
var app = angular.module("myApp", []);
app.controller("outerController", ['$scope', function($scope) {
console.log('aici');
$scope.$on('pokemonEvent', function(event, mass) { console.log(mass); });
}]);
app.controller("innerController", ['$scope', function($scope) {
$scope.pokemon = [{
name: "Bulbasaur",
type: "Grass/Poison"
}, {
name: "Charmander",
type: "Fire"
}, {
name: "Squirtle",
type: "Water"
}];
$scope.$emit('pokemonEvent', $scope.pokemon);
}]);