我有一个项目列表,我已通过ng-repeat
在模板中呈现它们。它们中的每一个都由itemController
控制,它暴露了项目的某些行为(例如,抓取焦点)。这是HTML:
<body ng-controller="mainController">
<button ng-click="addItem()">add</button>
<ul>
<li ng-repeat="item in items" ng-controller="itemController">
<div ng-if="item.isEditing">
<input ng-model="item.name"/>
<button ng-click="item.isEditing=false">done</button>
</div>
<span ng-if="!item.isEditing">{{item.name}}</span>
</li>
</ul>
</body>
在mainController
中,我有一个向项目添加新项目的功能。这是mainController的代码:
app.controller('mainController', function($scope){
$scope.items = [
{
name: "alireza"
},
{
name: "ali"
}
];
$scope.addItem = function(){
$scope.items.push({isEditing: true});
}
});
每当我向items
数组添加项目时,相应的li
元素都会添加到视图中,该元素由控制添加到实例中itemController
,相应的模型是我刚添加的新项目(或scope
的{{1}},其中包含 item)。
当我向itemController
添加一些项目时,我只能访问items
,而不能访问最近创建的项目的范围。所以我无法在新项目的范围内运行某些功能(如grabFocus)。
在我的设计中,它在语义上是错误的吗?这个问题的规范方法是什么?
答案 0 :(得分:1)
您可以使用父作用域中的$broadcast
以及子作用域中的$on
来通知新添加项目的子作用域。通过传递(作为参数)与新添加的项对应的子范围的$id
,每个捕获事件的子项都可以知道它是否需要调用grabFocus()
。
这是使用该方法的fork of your Plunker。我不确定你在原始的Plunker中使用$element.find(":text").focus();
想要完成什么,所以我调整它以切换$scope
属性,该属性又控制视图中的样式。新添加的项目将为红色(通过调用自己的grabFocus
函数将标记切换为true
),其他项目将为黑色(通过调用自己的loseFocus
函数来切换标记为false
)。
修改后的HTML(只是重复的li
):
<li ng-repeat="item in items" ng-controller="itemController">
<div ng-if="item.isEditing">
<input ng-model="item.name"/>
<button ng-click="item.isEditing=false;handleItemAdded($index);">done</button>
</div>
<span ng-if="!item.isEditing" ng-style="{ color: isFocused ? 'red' : 'black' }">{{item.name}}</span>
</li>
完整的JavaScript:
var app = angular.module("app",[]);
app.controller('mainController', function($rootScope, $scope){
$scope.items = [ { name: "alireza" }, { name: "ali" } ];
$scope.addItem = function(){
$scope.items.push({isEditing: true});
};
$scope.handleItemAdded = function (index) {
// $rootScope.$broadcast('item-added', { index: index });
for(var cs = $scope.$$childHead; cs; cs = cs.$$nextSibling) {
if (cs.$index === index) {
$rootScope.$broadcast('item-added', { id: cs.$id });
break;
}
}
};
});
app.controller('itemController', function($scope, $element){
$scope.$on('item-added', function (event, args) {
if ($scope.$id === args.id + 1) {
$scope.grabFocus();
} else {
$scope.loseFocus();
}
});
$scope.grabFocus = function() {
$scope.isFocused = true;
};
$scope.loseFocus = function() {
$scope.isFocused = false;
};
});
答案 1 :(得分:0)
我根据索引号为每个输入创建了一个唯一的ID,从而改变了你的方法。请参阅下面的代码,希望它有所帮助。
// Code goes here
var app = angular.module("app",[]);
app.controller('mainController', function($scope,$timeout){
$scope.items = [
{
name: "alireza"
},
{
name: "ali"
}
];
$scope.addItem = function(){
$scope.items.push({isEditing: true});
$timeout(function(){
document.getElementById("newItem"+($scope.items.length-1)).focus();
},0)
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<!DOCTYPE html>
<html ng-app="app">
<head>
<script data-require="angular.js@1.3.0" data-semver="1.3.0" src="//code.angularjs.org/1.3.0/angular.js"></script>
<link href="style.css" rel="stylesheet" />
<script src="script.js"></script>
</head>
<body ng-controller="mainController">
<button ng-click="addItem()">add</button>
<ul>
<li ng-repeat="item in items">
<div ng-if="item.isEditing">
<input ng-model="item.name" id="newItem{{$index}}"/>
<button ng-click="item.isEditing=false">done</button>
</div>
<span ng-if="!item.isEditing">{{item.name}}</span>
</li>
</ul>
</body>
</html>