我正在通过制作基于浏览器的数独求解器来学习角度。有很多方法可以解决我的问题,但我正在寻找最有角度的方法。
我的html使用嵌套的ng-repeat创建一个9x9的文本输入网格。我想要实现的行为是这样的:在用户在文本输入中输入一个数字(使用一个名为“grid-cell”的指令)之后,onBlur事件将被触发并且该数字将被添加到控制器的9x9中。数组(在控制器中标识为$ scope.grid,初始化为九个空字符串的数组数组)
我的HTML看起来像这样。我觉得它相当不错:
<div ng-controller="SudokuController">
<table>
<tr ng-repeat="row in dimension">
<td ng-repeat="col in dimension">
<grid-cell row="{{ row }}" col="{{ col }}"></div>
</td>
</tr>
<tr>
<td id="submit" colspan="9">
<button ng-click="submit()" id="submit">Submit</button>
</td>
</tr>
</table>
</div>
我的角度代码看起来像这样(我觉得我不应该只需要一个控制器和一个指令):
var app = angular.module('app',[]);
app.controller('SudokuController', function($scope) {
$scope.dimension = [1,2,3,4,5,6,7,8,9];
$scope.grid = [];
for (var i = 1; i<=$scope.dimension.length; i++) {
$scope.grid[$scope.grid.length] = ['','','','','','','','',''];
}
$scope.addNumber = function(row, col, val) {
$scope.grid[row][col] = val; // I would like it to work this way
};
$scope.submit = function() {
// insert sudoku-solving algorithm here
};
});
app.directive('gridCell', function() {
return {
restrict: "EA",
template: '<input type="text" />',
replace: true,
scope: {
row: '@',
col: '@'
},
link: function(scope, elem, attrs) {
elem.bind('blur', function() {
//how do I correctly write this?
scope.addNumber(scope.row, scope.col, elem[0].val);
});
}
}
});
这不起作用;在指令的链接中使用elem.bind()似乎无法与控制器通信。但是,我甚至不确定这是否是接近它的“正确”方式。我也想知道我是否应该做这样的事情:
<td ng-repeat="col in dimension">
<grid-cell row="{{ row }}" col="{{ col }}" ng-blur="addNumber(row, col, getThisValueSomehow)"></div>
</td>
提前致谢。
答案 0 :(得分:1)
您可以更新grid-cell指令中的网格:
app.controller('MainCtrl', function($scope) {
$scope.dimension = [1,2,3,4,5,6,7,8,9];
$scope.grid = [];
for (var i = 1; i<=$scope.dimension.length; i++) {
$scope.grid[$scope.grid.length] = ['','','','','','','','',''];
}
$scope.submit = function() {
// insert sudoku-solving algorithm here
};
});
app.directive('gridCell', function() {
return {
restrict: "EA",
template: '<input type="text" ng-model="value" />',
replace: true,
scope: {
row: '&',
col: '&',
grid: '='
},
link: function(scope, elem, attrs) {
elem.bind('blur', function() {
scope.$apply(function () {
if (scope.value)
{
scope.grid[scope.row()][scope.col()] = scope.value;
}
});
});
}
}
});
HTML:
<tr ng-repeat="row in dimension">
<td ng-repeat="col in dimension">
<grid-cell row="row" col="col" grid="grid"></grid-cell>
</td>
</tr>
答案 1 :(得分:0)
尝试第三种方法: http://ngtutorial.com/create/ways-to-pass-variable-from-directive-to-controller.html#/toc_4
该示例使用别名,因此控制器的实例可以从范围引用。
<!DOCTYPE HTML>
<html>
<head>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.0-rc.3/angular.min.js"></script>
<script type="text/javascript">
var app = angular.module("MyApp", []);
//
// our controller
//
app.controller("MyController", MyController)
function MyController($scope) {
var _private_var1 = "**value is not set**";
this.MyMethod = function(var1) {
_private_var1 = var1;
}
this.GetVar1 = function() {
return _private_var1;
}
}
app.directive({
"mySampleBtn": mySampleBtnDirective,
"mySampleTxt": mySampleTxtDirective
});
//
// our directives
//
function mySampleBtnDirective(){
return {
restrict: 'EA',
template: "<button ng-click='CallMethod()'>{{name}}</button>",
link: function(scope, element) {
var ctrl = element.attr('ctrl');
scope.name = element.attr('name');
scope.CallMethod = function() {
alert( scope[ctrl].GetVar1() );
}
}
}
};
function mySampleTxtDirective(){
return {
restrict: 'EA',
template: "<input ng-model='theText'/>",
link: function(scope, element) {
var ctrl = element.attr('ctrl');
scope.$watch("theText", function(newVal){
scope[ctrl].MyMethod( scope.theText );
});
}
}
};
</script>
<body ng-app="MyApp">
<div ng-controller="MyController as ctrlName">
theText: <my-sample-txt ctrl="ctrlName"></my-sample-txt>, invokes <i>ctrlName.MyMethod( theText )</i><br/>
<br/>
<my-sample-btn name="Sample One" ctrl="ctrlName"></my-sample-btn>, invokes <i>alert( ctrlName.GetVar1() )</i><br/>
<br/>
=> ctrlName.GetVar1() = {{ ctrlName.GetVar1() }}
</div>
</body>
</head>
</html>