【问题标题】:Can I access a form in the controller?我可以访问控制器中的表单吗?
【发布时间】:2013-11-03 07:51:29
【问题描述】:

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

$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>

这不起作用。请注意,我的表单位于 Foundation 选项卡内。如何访问firstName

编辑:当form 在基础选项卡中时,它似乎没有添加到scope

有人有解决办法吗?

【问题讨论】:

    标签: angularjs angular-foundation angularjs-forms


    【解决方案1】:

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

    除非您的表单在控制器范围内定义,而是在子范围内定义。

    基本上,一些角度指令,例如ng-ifng-repeatng-include,会创建一个独立的子作用域。任何定义了scope: {} 属性的自定义指令也是如此。可能,您的基础组件也妨碍了您。

    &lt;form&gt; 标签周围引入一个简单的ng-if 时,我遇到了同样的问题。

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

    注意:我建议你重写你的问题。您的问题的答案是,但您的问题略有不同:

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

    答案很简单:

    【讨论】:

    • ...除非您按照@ondrs 的回答中所述设置表单和控制器(使用$scope.forms = {}name="forms.form1"
    • 请看你上面的答案,作者是 KhalilRavanna。您可以从 $scope.formName 访问表单。他提供了一个工作示例
    【解决方案2】:

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

    父控制器

    $scope.forms = {};
    

    子范围内的一些模板

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

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

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

    【讨论】:

    • 我建议使用 var watcher = $scope.$watcher 并在 if 语句中执行 watcher() 来解除手表绑定。这使它成为 1 次观看,因此您不会在设置后观看每个摘要
    【解决方案3】:

    答案有点晚,但有以下选项。它对我有用,但不确定它是否正确。

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

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

    在控制器中:

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

    现在我在我的控制器变量中得到了我的表单$scope.myForm

    【讨论】:

    • 我唯一要添加的是确保它位于表单的底部。
    • 的位置无关紧要。请注意它的形式。
    • 好,但我更喜欢更简单的解决方案:ng-init="$parent.myForm = formName" 无需更改控制器注意:它仅适用于直接控制器,与解决方案相反以上
    • 在尝试了其他方法之后,我选择了这个,因为它允许name 属性正是我想要的。其他虚拟对象解决方案的问题是,如果该组件用于具有 ng-form 的另一个组件中,则其他 ng-form 按字面意思使用该表单名称。所以它将有一个字符串字面量(不是嵌套属性)名称为“dummy.myForm”的字段,我发现这是不可接受的。
    • 我多次尝试使用 controllerAs 语法但都失败了(我正在使用 $mdDialog)。终于解决了这个问题,它做得很好。唯一需要注意的是,任何控制器初始化都需要在 $timeout 上运行,因为在控制器首次运行时表单不可用
    【解决方案4】:

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

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

    【讨论】:

    • 为了澄清未来的读者,如果说您的表单的命名/定义类似于此&lt;form name="myform"&gt;&lt;/form&gt;,甚至&lt;div ng-form name="myform"&gt;&lt;/div&gt;,那么您的点击事件将如下:ng-click="submit(myform)"。然后您可以在单击功能中访问 Angular 表单对象,例如:$scope.submit = function (form) { if (form.$valid) { 等。
    • 我在这里发现了一个问题——假设表单中有一个下拉列表。使用上述方法只会给我视图值,而不是我需要的确切值。或者我做错了什么,会添加一个小提琴。
    【解决方案5】:

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

    类似$scope.dummy = {}

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

    <form name="dummy.customerForm">
    

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

    $scope.dummy.customerForm
    

    你将能够做类似的事情

    $scope.dummy.customerForm.$setPristine()
    

    WIKI LINK

    有一个“。”在您的模型中将确保原型继承是 在玩。所以,使用&lt;input type="text" ng-model="someObj.prop1"&gt; 而不是 比&lt;input type="text" ng-model="prop1"&gt;

    如果您真的想要/需要使用原语,有两种解决方法:

    1.在子作用域中使用 $parent.parentScopeProperty。这将防止 子范围从创建自己的属性。 2.定义一个函数 父作用域,并从子作用域调用它,传递原语 对父级的价值(并非总是可能的)

    【讨论】:

    • 定义表单绑定的有效区域在哪里?
    • 值得一提的是,如果表单元素有一个ng-if 条件,dummy.customerForm 将在满足ng-if 的条件之前是未定义的
    【解决方案6】:

    您无法访问输入的原因是“基础”选项卡(或ng-repeat?)创建了一个isolate scope。解决此问题的一种方法是使用 controller as 语法:

    <div ng-controller="MyController as ctrl">
    
    <!-- an example of a directive that would create an isolate scope -->
    <div ng-if="true">
    
    <form name="ctrl.myForm">
        ...inputs
        Dirty? {{ctrl.myForm.$dirty}}
    
        <button ng-click="ctrl.saveChanges()">Save</button>
    </form>
    
    </div>
    
    </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”方法,因为它没有暴露给模板
    • “saveChanges”方法暴露在 javascript 的第 3 行还是我误解了?
    • 这很好,因为这意味着您可以避免注入整个 $scope,这在我看来更干净
    • 你如何在 jasmine 中测试这个?在我的规范中, vm.myForm 是未定义的
    • 这应该在 1.5.X 的官方文档中注明,这是做组件和 es6 的方式。谢谢楼主
    【解决方案7】:

    这个答案有点晚了,但我偶然发现了一个让一切变得更容易的解决方案。

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

    我通过 ui-router 配置了控制器(但您可以随心所欲地进行,即使在 HTML 中直接使用 &lt;div ng-controller="someController as myCtrl"&gt; 之类的东西)这就是它在 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
                }
        }]);
    

    【讨论】:

    • 虽然这与其他几个答案所暗示的技术基本相同,但它是最好的变体,应该是公认的答案,特别是因为现在每个人都使用控制器。
    【解决方案8】:

    绝对不能访问范围 bec 中的表单。它不是创建的。 html 模板中的 DOM 加载速度有点慢,就像控制器构造函数一样。 解决方案是观察直到 DOM 加载并定义了所有范围!

    在控制器中:

    $timeout(function(){
        console.log('customerForm:', $scope.customerForm);
        // everything else what you need
    });
    

    【讨论】:

      【解决方案9】:

      ng-model="$ctrl.formName" 属性添加到您的表单,然后在控制器中,您可以通过this.formName 将表单作为控制器内的对象访问

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-03-07
        • 2013-04-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多