Search code examples
angularjslaravelangular-resource

Why angular sets undefined to empty ng-model fields


I have simple crud application in Angular (1.2) and Laravel (4.2). To simple crud operations I use efficient Eloquent method:

$product->fill(Input::all());

which takes all fields from request payload, but is there a problem when I need to do update model with empty fields.

In the edit action I have a form which is filled with the response of $resource get method of my service:

adminModule.factory 'Product', ($resource) ->
  $resource '/admin/products/:id', { id: '@id' }, {
    query: { method: 'GET', isArray: false }
    update: { method: 'PUT' }
  }

a controller:

adminModule.controller 'ProductFormEditController', ($scope, Product, $stateParams) ->

  $scope.formData = Product.get({id: $stateParams.id})

and html:

    <input  type="text" data-ng-model="formData.name" name="name" class="form-control" id="name"
                           placeholder="Nazwa" data-server-error required>

If I clear this field value and do submit the value of $scope.formData is set to undefined and there is not included in the PUT request, so the Laravel model fill method doesn't see the field anyway and don't sets the empty value for the validation, but takes the original value of the model.

The problem is: How can I send the empty string from ngModel instead of undefined?

p.s. If the input type is Textarea the $resource send empty "" string :-/, so I'm confusing...


Solution

  • When you have the "required" directive on an input, an empty value will never be set (so it will be undefined).

    See the source code ("requiredDirective" in file input.js) where no value is retrieved to store in the model, when the input is blank:

    if (attr.required && ctrl.$isEmpty(value)) {
       ctrl.$setValidity('required', false);
          return;
       } else {
          ctrl.$setValidity('required', true);
          return value;
    }
    

    IMHO it is a little strange use case anyway: You do want client side validation, but still want to submit invalid values to the server, right?

    I guess you can write your own validation ("my-required") to do that.

    Alternatively you could copy over default values before posting the data to the server, for example with lodash (or underscore):

    _.defaults(formData, { name: ""});