Web User
Web User

Reputation: 7736

AngularJS form and null/empty values

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.

The AngularJS code is as follows:

(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:

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

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

Note I have set up a jsFiddle for this example.

Upvotes: 8

Views: 35248

Answers (4)

Tome Pejoski
Tome Pejoski

Reputation: 1582

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

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.

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/

Upvotes: 4

Raj
Raj

Reputation: 321

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);

Upvotes: 2

Scott Sword
Scott Sword

Reputation: 4718

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.

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);
            });

        };
    });
})();

Upvotes: 2

Ataur Rahim Chowdhury
Ataur Rahim Chowdhury

Reputation: 454

Added Watcher on formData,

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

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

Upvotes: 1

Related Questions