我可以在控制器中访问表格吗?


152

我目前正在使用以下内容。

$scope.$$childHead.customerForm[firstName], 以便:

<form name="customerForm">
  <input type="text" name="firstName" 
         ng-model="data.customer.firstName" 
         tabindex="1"  
         ng-disabled="!data.editable" 
         validationcustomer />
</form>

但这仅适用于Chrome。现在,我尝试了以下方法:

$scope.editCustomerForm[firstName], 以便:

<form name="customerForm" ng-model="editCustomerForm">
  <input type="text" name="firstName" 
         ng-model="data.customer.firstName" tabindex="1"  
         ng-disabled="!data.editable" 
         validationcustomer />
</form>

这不起作用。请注意,我的表单位于“基金会”选项卡中。我该如何访问firstName

编辑:当它位于“基金会”标签中时,似乎form未添加到中scope

有人对此有解决方案吗?

Answers:


210

尽管在其他评论中提到了这一点,但我还是想为那些使用“ Controller As”语法的用户提供一些拼写:

<div ng-controller="MyController as ctrl">

<form name="ctrl.myForm">
    ...inputs
    Dirty? {{ctrl.myForm.$dirty}}

    <button ng-click="ctrl.saveChanges()">Save</button>
</form>

</div>

然后,您可以在代码中访问FormController,例如:

function MyController () {
    var vm = this;
    vm.saveChanges = saveChanges;

    function saveChanges() {

       if(vm.myForm.$valid) { 
            // Save to db or whatever.
            vm.myForm.$setPristine();
       }
}

据我所知,模板无法调用“ saveChanges”方法,因为它没有公开给模板
Spock 2014年

2
“ saveChanges”方法在javascript的第3行中公开,还是我误会了?
slopapa 2014年

3
这很好,因为这意味着您可以避免注入整个$ scope,在我看来,这是更干净的
72GM 2015年

2
您如何在茉莉花中测试呢?在我的规范中,vm.myForm是未定义的
bahrieinn

1
在1.5.X的官方文档中应注意这一点,这是制作组件和es6的方法。谢谢您,先生
MatanCo '16

91

您可以将表单附加到在父控制器中定义的某些对象。然后,您甚至可以从子范围访问表单。

上级控制器

$scope.forms = {};

子范围中的一些模板

<form name="forms.form1">
</form>

问题是在执行控制器中的代码时不必定义表单。所以你必须做这样的事情

$scope.$watch('forms.form1', function(form) {
  if(form) {
    // your code...
  }
});

10
我建议var watcher = $scope.$watcher您在if语句中使用并在里面使用您将使watcher()取消绑定手表。这使它成为1次观看,因此您不必在设置摘要后观看每个摘要
willJk 2015年

91

如果要将表单传递给控制器​​以进行验证,则可以将其作为参数传递给处理提交的方法。使用表单名称,因此对于原始问题,它将类似于:

<button ng-click="submit(customerForm)">Save</button>

13
为了向以后的读者说明,如果说您的表单的命名/定义与此<form name="myform"></form>,甚至相似<div ng-form name="myform"></div>,则您的click事件将如下所示:ng-click="submit(myform)"。然后您可以在单击函数中访问Angular表单对象,例如:$scope.submit = function (form) { if (form.$valid) {etc.
Matty J

我在这里发现问题-假设表单中有一个下拉列表。使用上述方法只能给我提供视图值,而不是我需要的确切值。还是我做错了什么,会加个小提琴。
swateek '16

82

答案有点晚,但附带以下选项。它为我工作,但不确定这是否正确。

在我看来,我正在这样做:

<form name="formName">
    <div ng-init="setForm(formName);"></div>
</form>

并在控制器中:

$scope.setForm = function (form) {
    $scope.myForm = form;
}

现在,完成此操作后,我的控制器变量中有表格 $scope.myForm


1
我要添加的唯一内容是确保它位于表单的底部。
smb

<div ng-init =“ setForm(formName);”> </ div>的位置无关紧要。只是要注意它的形式。
waqas 2014年

1
很好,但是我希望有一个更简单的解决方案:ng-init =“ $ parent.myForm = formName” Whithout无需更改控制器注意:与上述解决方案相反,它仅与直接控制器一起使用
mastilver 2014年

在尝试了其他方法之后,我选择了这个方法,因为它允许name属性恰好是我想要的。其他伪对象解决方案的问题是,如果此组件在另一个具有ng形式的组件中使用,则另一个ng形式实际上使用了该形式的名称。因此它将具有一个字符串文字(不嵌套属性)名称为“ dummy.myForm”的字段,我发现这是不可接受的。
罗勒

我多次尝试并使用controllerAs语法失败(我正在使用$ mdDialog)。终于解决了这个问题,并且做得很好。唯一需要注意的是,任何控制器初始化都需要在$ timeout上运行,因为当控制器首次运行时该窗体不可用
Peter Nixey

22

为了能够访问控制器中的表单,您必须将其添加到虚拟作用域对象中。

就像是 $scope.dummy = {}

对于您的情况,这将意味着:

<form name="dummy.customerForm">

在您的控制器中,您可以通过以下方式访问表单:

$scope.dummy.customerForm

你将能够做类似的事情

$scope.dummy.customerForm.$setPristine()

维基链接

有一个 '。' 在您的模型中,将确保原型继承在起作用。因此,使用<input type="text" ng-model="someObj.prop1">而不是<input type="text" ng-model="prop1">

如果您确实希望/需要使用原语,则有两种解决方法:

1.在子范围内使用$ parent.parentScopeProperty。这将阻止子范围创建自己的属性。2.在父范围内定义一个函数,然后从子级调用它,将原始值传递给父级(并非总是可能的)


定义表单绑定的有效区域在哪里?
Gus Crawford

值得一提dummy.customerFormng-if是,在表单元素有条件的情况下,直到满足条件为止ng-if,它
才是不确定的

22

这个答案有点晚了,但是我偶然发现了一个使很多事情变得更容易的解决方案。

如果使用controllerAs语法,则实际上可以直接将表单名称分配给控制器,然后从“ this”变量中引用它。这是我在代码中的操作方式:

我通过ui-router配置了控制器(但是您可以根据需要进行操作,即使直接在HTML中也可以使用<div ng-controller="someController as myCtrl">),这就是ui-router配置中的样子:

views: {
            "": {
                templateUrl: "someTemplate.html",
                controller: "someController",
                controllerAs: "myCtrl"
            }
       }

然后在HTML中,只需将表单名称设置为“ controllerAs”。“ name”,如下所示:

<ng-form name="myCtrl.someForm">
    <!-- example form code here -->
    <input name="firstName" ng-model="myCtrl.user.firstName" required>
</ng-form>

现在,您可以在控制器内执行以下操作:

angular
.module("something")
.controller("someController",
    [
       "$scope",
        function ($scope) {
            var vm = this;
            if(vm.someForm.$valid){
              // do something
            }
    }]);

2
尽管这基本上与其他几个答案所建议的技术相同,但这是最好的变化,应该是公认的答案,特别是因为现在无论如何每个人都使用controllerAs。
分号

6

是的,您可以在控制器中访问表单(如docs中所述)。

除非您的表单在控制器作用域中定义,而是在子作用域中定义。

基本上,一些角度的指令,例如ng-ifng-repeat或者ng-include,将创建一个孤立子范围。具有scope: {}定义的属性的所有自定义指令也将如此。可能,您的基础组件也很麻烦。

ng-if<form>标记周围引入简单标记时,我遇到了同样的问题。

查看这些以获取更多信息:

注意:建议您重新编写问题。您的问题的答案是肯定的,但您的问题略有不同:

我可以从控制器访问子范围内的表单吗?

答案将是:


...除非您设置的形式和控制器在@ondrs的回答描述(使用$scope.forms = {}name="forms.form1"
marapet

请在KhalilRavanna的上方立即看到答案。您可以从$ scope.formName访问该表单。他提供了一个有效的示例
micahblu 2015年


0

绝对不能在scope bec中访问表单。它不会被创建。html模板中的DOM像控制器构造函数一样缓慢加载。解决方案是观察直到加载DOM和定义所有范围!

在控制器中:

$timeout(function(){
    console.log('customerForm:', $scope.customerForm);
    // everything else what you need
});
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.