从 FormController 获取表单控件 [英] Getting form controls from FormController

查看:21
本文介绍了从 FormController 获取表单控件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要一种方法来循环遍历 AngularJS 表单的已注册控件.从本质上讲,我试图获取所有 $dirty 控件,但没有控件数组(除了包含控件本身之外,FormController 还具有许多不同的属性/功能 - 每个都作为它自己的对象).

我一直在查看源代码,我看到 FormController 中有一个 controls 数组,这正是我要查找的数组.有没有办法访问这个值,或者扩展 FormController 以包含一个返回这个 controls 数组的函数?

Plnkr 演示

此外,我意识到从技术上讲我可以检查$"键字符串中的第一个字符,但我想避免这种情况,以防未来版本的 Angular 中 FormController/指令发生变化.

编辑 2:另一个澄清:我在所有这些方面的目标是能够确定哪些特定字段是 $dirty,是否通过循环遍历整个控件列表(不包括 $dirty、$invalid、$error、$name 和其他存在于 Form 对象中的属性)或通过扩展 FormController 并创建一个函数,该函数仅返回当前脏的控件(并且不等于它们的起始值)

编辑 3:我正在寻找的解决方案需要适用于不同结构的表单/模型.示波器上的模型是通过 AJAX 生成的,因此它们的结构已经设置(我想避免必须为我已经通过 AJAX 接收的所有数据硬编码一个新结构).此外,我希望在多个表单/模型中使用此表单提交过程,并且每个表单/模型都有不同的 JSON 结构 - 因为它们适用于我们对象模型中的不同实体.这就是为什么我选择寻求一种方法来访问 FormController 中的 controls 对象(我将在下面发布 FormController 中的代码),因为它是唯一可以得到我所有字段的平面数组的地方.

function FormController(element, attrs) {var 形式 = 这个,parentForm = element.parent().controller('form') ||nullFormCtrl,invalidCount = 0,//用来轻松判断我们是否有效错误 = form.$error = {},控制 = [];//初始化状态form.$name = attrs.name ||attrs.ngForm;form.$dirty = false;form.$pristine = true;form.$valid = true;form.$invalid = false;parentForm.$addControl(form);//设置控件的初始状态element.addClass(PRISTINE_CLASS);切换ValidCss(真);//方便切换类的便捷方法函数 toggleValidCss(isValid, validationErrorKey) {验证错误键 = 验证错误键?'-' + snake_case(validationErrorKey, '-') : '';元素.removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);}/*** @ngdoc 函数* @name ng.directive:form.FormController#$addControl* @methodOf ng.directive:form.FormController** @描述* 用表单注册一个控件.** 使用 ngModelController 的输入元素在链接时会自动执行此操作.*/form.$addControl = 函数(控件){控制推(控制);if (control.$name && !form.hasOwnProperty(control.$name)) {表单[控件.$名称] = 控件;}};/*** @ngdoc 函数* @name ng.directive:form.FormController#$removeControl* @methodOf ng.directive:form.FormController** @描述* 从表单中注销控件.** 使用 ngModelController 的输入元素在销毁时会自动执行此操作.*/form.$removeControl = 函数(控制){if (control.$name && form[control.$name] === control) {删除表单[control.$name];}forEach(错误,函数(队列,validationToken){form.$setValidity(validationToken, true, control);});arrayRemove(控件,控件);};//删除了额外的代码}

如您所见,表单本身具有私有可用的 controls 数组.我想知道是否有办法扩展 FormController 以便我可以公开该对象?或者创建一个公共函数,这样我至少可以查看私有数组?

解决方案

为了直接解决问题,像这样修改@lombardo的答案;

 vardirtyFormControls = [];var myForm = $scope.myForm;angular.forEach(myForm, function(value, key) {if (typeof value === 'object' && value.hasOwnProperty('$modelValue') && value.$dirty)dirtyFormControls.push(value)});

然后数组dirtyFormControls"将包含脏的表单控件.

您还可以使用此技巧在必需"验证和所有其他验证的表单提交中显示错误消息.在您的 submit() 函数中,您将执行以下操作;

 if (form.$invalid) {form.$setDirty();angular.forEach(form, function(value, key) {if (typeof value === 'object' && value.hasOwnProperty('$modelValue'))value.$setDirty();});//在表单顶部显示用户错误摘要.$('html, body').animate({scrollTop: $("#myForm").offset().top}, 1000);返回;}

在您的表单中,您将显示错误消息

 <span ng-messages="myForm['subject-' + $index].$error" ng-show="myForm['subject-' + $index].$dirty" class="有错误"><span ng-message="required">课程主题是必需的.</span></span>

当您使用ng-repeat"或类似的东西动态生成控件时,上述解决方案很有用.

I need a way to loop through the registered controls of an AngularJS form. Essentially, I'm trying to get all the $dirty controls, but there's no array of the controls (the FormController has a number of different properties/functions in addition to containing the controls themselves - each as its' own object).

I've been looking at the source code, and I see that there is a controls array in the FormController that is exactly the array I'm looking for. Is there a way to get access to this value, or extend the FormController to include a function that returns this controls array?

Edit: Plnkr demo

Also, I realized that technically I could check the first character in the key string for "$", but I'd like to avoid that in case the FormController/directive changes in a future version of Angular.

Edit 2: Another clarification: My goal in all of this is to be able to determine which specific fields are $dirty, whether by looping through the entire list of controls (not including the $dirty, $invalid, $error, $name, and other properties that live in the Form object as it is) or by extending the FormController and creating a function that returns only the controls which are currently dirty (and not equal to their starting values)

Edit 3: The solution I'm looking for needs to be applicable to forms/models of different structures. The models on the scope are generated via AJAX, so their structure is already set (I'd like to avoid having to hardcode a new structure for all the data I'm already receiving via AJAX). Also, I'm looking to use this form submission process across multiple forms/models, and each of them have differing JSON structures - as they apply to different entities in our Object Model. This is why I've chosen to ask for a way to get access to the controls object in the FormController (I'll post the code from FormController below), because it's the only place where I can get a flat array of all of my fields.

function FormController(element, attrs) {


var form = this,
      parentForm = element.parent().controller('form') || nullFormCtrl,
      invalidCount = 0, // used to easily determine if we are valid
      errors = form.$error = {},
      controls = [];

  // init state
  form.$name = attrs.name || attrs.ngForm;
  form.$dirty = false;
  form.$pristine = true;
  form.$valid = true;
  form.$invalid = false;

  parentForm.$addControl(form);

  // Setup initial state of the control
  element.addClass(PRISTINE_CLASS);
  toggleValidCss(true);

  // convenience method for easy toggling of classes
  function toggleValidCss(isValid, validationErrorKey) {
    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';
    element.
      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).
      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);
  }

  /**
   * @ngdoc function
   * @name ng.directive:form.FormController#$addControl
   * @methodOf ng.directive:form.FormController
   *
   * @description
   * Register a control with the form.
   *
   * Input elements using ngModelController do this automatically when they are linked.
   */
  form.$addControl = function(control) {
    controls.push(control);

    if (control.$name && !form.hasOwnProperty(control.$name)) {
      form[control.$name] = control;
    }
  };

  /**
   * @ngdoc function
   * @name ng.directive:form.FormController#$removeControl
   * @methodOf ng.directive:form.FormController
   *
   * @description
   * Deregister a control from the form.
   *
   * Input elements using ngModelController do this automatically when they are destroyed.
   */
  form.$removeControl = function(control) {
    if (control.$name && form[control.$name] === control) {
      delete form[control.$name];
    }
    forEach(errors, function(queue, validationToken) {
      form.$setValidity(validationToken, true, control);
    });

    arrayRemove(controls, control);
  };

  // Removed extra code
}

As you can see, the form itself has the controls array privately available. I'm wondering if there's a way for me to extend the FormController so I can make that object public? Or create a public function so I can at least view the private array?

解决方案

For a direct solution to the question, modify @lombardo's answer like so;

     var dirtyFormControls = [];
     var myForm = $scope.myForm;
     angular.forEach(myForm, function(value, key) {
         if (typeof value === 'object' && value.hasOwnProperty('$modelValue') && value.$dirty)
             dirtyFormControls.push(value)                        
     });

The array 'dirtyFormControls' will then contain the form controls that are dirty.

You can also use this trick to show error messages on form submission for 'Required' validations and all others. In your submit() function you will do something like;

 if (form.$invalid) {
     form.$setDirty();              
     angular.forEach(form, function(value, key) {
         if (typeof value === 'object' && value.hasOwnProperty('$modelValue'))
             value.$setDirty();                        
     });
    //show user error summary at top of form.
     $('html, body').animate({
         scrollTop: $("#myForm").offset().top
     }, 1000);
     return;
 }

And in your form you will show error messages with

    <span ng-messages="myForm['subject-' + $index].$error" ng-show="myForm['subject-' + $index].$dirty" class="has-error">
        <span ng-message="required">Course subject is required.</span>
    </span>

The above solution is useful when you have dynamically generated controls using 'ng-repeat' or something similar.

这篇关于从 FormController 获取表单控件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆