AngularJS形式和null /空值

时间:2022-04-11 15:31:28

I am working with a somewhat dynamic AngularJS form. In other words, I am able to add rows of input fields, etc. So my approach was to start with a $scope.formData empty object, to encapsulate all the properties that are bound to both static and dynamic HTML form elements.

我正在使用一个有点动态的AngularJS表单。换句话说,我能够添加输入字段等行。所以我的方法是从$ scope.formData空对象开始,以封装绑定到静态和动态HTML表单元素的所有属性。

The AngularJS code is as follows:

AngularJS代码如下:

(function() {
    var formApp = angular.module("formApp", []);
    formApp.controller("FormCtrl", function ($scope, $timeout) {
        $scope.formData = {};
        $scope.formData.subscribers = [
            { name: null, email: null }
        ];
        $scope.addSubscriber = function() {
            $scope.formData.subscribers.push({ name: null, email: null });
        };
    });
})();

The HTML for the AngularJS form:

AngularJS表单的HTML:

<body data-ng-app="formApp">
    <div data-ng-controller="FormCtrl">
        <p>
            Name of Topic: <input type="text" data-ng-model="formData.title" placeholder="enter a title" />
        </p>
        Subscribers:
        <button data-ng-click="addSubscriber()">Add subscriber</button>
        <table>
            <tr>
                <th>Name</th>
                <th>Email</th>
            </tr>
            <tr data-ng-repeat="subscriber in formData.subscribers">
                <td><input type="text" data-ng-model="subscriber.name" placeholder="enter name" /></td>
                <td><input type="text" data-ng-model="subscriber.email" placeholder="enter email" /></td>
            </tr>
        </table>
        <hr style="margin:1em 0;" />
        <p>
            <em>Debug info</em>: {{ formData }}
        </p>
    </div>
</body>

Note the Debug info section at the end, which displays the $scope.formData object and its contents. I have a couple of issues with the way I have implemented this form.

请注意最后的Debug info部分,它显示$ scope.formData对象及其内容。我对实现此表单的方式有几个问题。

  • When the page first loads, there is no formData.title property in the $scope, but since it is bound to the Title input text field, when I start typing a value, the title property gets added to the $scope. However when I delete the value in the input text field, the formData.title property still exists in the $scope as an empty string. I suppose this is okay, but I really want to clean up empty or null values when submitting the form. I would like to do it on the client side if it is easy to do so, so the server side code does not have to clean up anything.
  • 当页面首次加载时,$ scope中没有formData.title属性,但由于它绑定到Title输入文本字段,因此当我开始键入值时,title属性将添加到$ scope。但是,当我删除输入文本字段中的值时,formData.title属性仍作为空字符串存在于$ scope中。我想这没关系,但我真的想在提交表单时清理空值或空值。如果容易这样做,我想在客户端这样做,所以服务器端代码不必清理任何东西。
  • With the dynamic Subscribers section, I can keep adding as many rows as I want, but ultimately, I would like to filter out all empty subscriber objects on the client side.
  • 使用动态订阅者部分,我可以继续添加尽可能多的行,但最终,我想过滤掉客户端上的所有空订阅者对象。

Does AngularJS have any options for detecting and cleaning null/empty values in the $scope before further processing, such as a $http POST?

在进一步处理之前,AngularJS是否有任何选项可以检测和清除$ scope中的null / empty值,例如$ http POST?

Note I have set up a jsFiddle for this example.

注意我为这个例子设置了一个jsFiddle。

4 个解决方案

#1


4  

Simply use ngModelController $parsers and overwrite the default HTML input element.

只需使用ngModelController $解析器并覆盖默认的HTML输入元素。

With this implementation you can have control over the model value all the time. So in your case you can set the model to null whenever the view value is empty String.

通过此实现,您可以始终控制模型值。因此,在您的情况下,只要视图值为空,就可以将模型设置为null。

var inputDefinition = function () {
return {
  restrict: 'E',
  require: '?ngModel',
  link: function (scope, element, attr, ngModel) {
    if (ngModel) {
      var convertToModel = function (value) {
        return value === '' ? null : value;
      };
      ngModel.$parsers.push(convertToModel);
    }
  }
};
/**
* Overwrite default input element.
*/
formApp.directive('input', inputDefinition);

Here is the updated JSFiddle: https://jsfiddle.net/9sjra07q/

这是更新的JSFiddle:https://jsfiddle.net/9sjra07q/

#2


2  

I try and avoid using watchers for performance reasons. With that being said, this really isn't as much of an Angular question as it is a JavaScript question. Since you have total control over when the data is passed off to the service I would simply clean it up first. This is fairly simple since your data structure is so shallow.

出于性能原因,我尽量避免使用观察者。话虽如此,这确实不是一个Angular问题,因为它是一个JavaScript问题。由于您可以完全控制数据何时传递给服务,因此我只需先将其清理干净即可。这非常简单,因为您的数据结构非常浅。

https://jsfiddle.net/1ua6oj5e/9/

https://jsfiddle.net/1ua6oj5e/9/

(function() {
    var formApp = angular.module("formApp", []);
    formApp.controller("FormCtrl", function ($scope, $timeout) {

        // Remove junkiness
        var _remove = function remove(item) {
            if ($scope.formData.title === undefined || $scope.formData.title === '') {
                delete $scope.formData.title;
            }
        };


        $scope.formData = {};
        $scope.formData.subscribers = [
            { name: null, email: null }
        ];
        $scope.addSubscriber = function() {
            $scope.formData.subscribers.push({ name: null, email: null });
        };

        // Submit to test functionality
        $scope.submit = function() {

            // Remove title if empty
            _remove($scope.formData.title);

            /* Remove name and email if empty.
             * If your list of fields starts to get large you could always
             * just nest another iterator to clean things up.                 
             */

            angular.forEach($scope.formData.subscribers, function(sub) {
                _remove(sub.name);
                _remove(sub.email);
            });

        };
    });
})();

#3


2  

function replacer(key, value) {
    if (value == "" || value == null) {
       return undefined;
    }
  return value;
}

var foo = {foundation: "", model: {year: 2015, price:null}, week: 45, transport: "car", month: 7};
foo = JSON.stringify(foo, replacer);
foo =JSON.parse(foo);
console.log(foo);

#4


1  

Added Watcher on formData,

在formData上添加了Watcher,

$scope.$watch('formData',function(n,o){
      if(typeof $scope.formData.title !== 'undefined' && $scope.formData.title === "" ){
        delete $scope.formData.title;
      }
},true);

Updated fiddle: https://jsfiddle.net/1ua6oj5e/6/

更新小提琴:https://jsfiddle.net/1ua6oj5e/6/

For all the dynamic fields you should use angular form validation, you should see this: https://docs.angularjs.org/guide/forms

对于所有动态字段,您应该使用角度表单验证,您应该看到:https://docs.angularjs.org/guide/forms

#1


4  

Simply use ngModelController $parsers and overwrite the default HTML input element.

只需使用ngModelController $解析器并覆盖默认的HTML输入元素。

With this implementation you can have control over the model value all the time. So in your case you can set the model to null whenever the view value is empty String.

通过此实现,您可以始终控制模型值。因此,在您的情况下,只要视图值为空,就可以将模型设置为null。

var inputDefinition = function () {
return {
  restrict: 'E',
  require: '?ngModel',
  link: function (scope, element, attr, ngModel) {
    if (ngModel) {
      var convertToModel = function (value) {
        return value === '' ? null : value;
      };
      ngModel.$parsers.push(convertToModel);
    }
  }
};
/**
* Overwrite default input element.
*/
formApp.directive('input', inputDefinition);

Here is the updated JSFiddle: https://jsfiddle.net/9sjra07q/

这是更新的JSFiddle:https://jsfiddle.net/9sjra07q/

#2


2  

I try and avoid using watchers for performance reasons. With that being said, this really isn't as much of an Angular question as it is a JavaScript question. Since you have total control over when the data is passed off to the service I would simply clean it up first. This is fairly simple since your data structure is so shallow.

出于性能原因,我尽量避免使用观察者。话虽如此,这确实不是一个Angular问题,因为它是一个JavaScript问题。由于您可以完全控制数据何时传递给服务,因此我只需先将其清理干净即可。这非常简单,因为您的数据结构非常浅。

https://jsfiddle.net/1ua6oj5e/9/

https://jsfiddle.net/1ua6oj5e/9/

(function() {
    var formApp = angular.module("formApp", []);
    formApp.controller("FormCtrl", function ($scope, $timeout) {

        // Remove junkiness
        var _remove = function remove(item) {
            if ($scope.formData.title === undefined || $scope.formData.title === '') {
                delete $scope.formData.title;
            }
        };


        $scope.formData = {};
        $scope.formData.subscribers = [
            { name: null, email: null }
        ];
        $scope.addSubscriber = function() {
            $scope.formData.subscribers.push({ name: null, email: null });
        };

        // Submit to test functionality
        $scope.submit = function() {

            // Remove title if empty
            _remove($scope.formData.title);

            /* Remove name and email if empty.
             * If your list of fields starts to get large you could always
             * just nest another iterator to clean things up.                 
             */

            angular.forEach($scope.formData.subscribers, function(sub) {
                _remove(sub.name);
                _remove(sub.email);
            });

        };
    });
})();

#3


2  

function replacer(key, value) {
    if (value == "" || value == null) {
       return undefined;
    }
  return value;
}

var foo = {foundation: "", model: {year: 2015, price:null}, week: 45, transport: "car", month: 7};
foo = JSON.stringify(foo, replacer);
foo =JSON.parse(foo);
console.log(foo);

#4


1  

Added Watcher on formData,

在formData上添加了Watcher,

$scope.$watch('formData',function(n,o){
      if(typeof $scope.formData.title !== 'undefined' && $scope.formData.title === "" ){
        delete $scope.formData.title;
      }
},true);

Updated fiddle: https://jsfiddle.net/1ua6oj5e/6/

更新小提琴:https://jsfiddle.net/1ua6oj5e/6/

For all the dynamic fields you should use angular form validation, you should see this: https://docs.angularjs.org/guide/forms

对于所有动态字段,您应该使用角度表单验证,您应该看到:https://docs.angularjs.org/guide/forms