使用angular.js中的输入从指令调用控制器

时间:2014-10-15 04:31:21

标签: javascript angularjs forms angularjs-directive angularjs-controller

我正在通过制作基于浏览器的数独求解器来学习角度。有很多方法可以解决我的问题,但我正在寻找最有角度的方法。

我的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>

提前致谢。

2 个答案:

答案 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>

http://plnkr.co/edit/peDjFbKGm6ydO4E45b5u?p=preview

答案 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>