Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 209
Karol F Avatar asked Oct 01 '14 09:10

Karol F


2 Answers

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

like image 182
Stephen Friedrich Avatar answered Nov 10 '22 09:11

Stephen Friedrich


You can configure angular to set your model even when the value is not valid with the property allowInvalid from ngModelOptions.

allowInvalid: boolean value which indicates that the model can be set with values that did not validate correctly instead of the default behavior of setting the model to undefined.

API Reference

Example:

<input 
   type="text" 
   ng-model="myvalue"
   ng-model-options="{ allowInvalid: true }"/>
like image 30
Alexandre Junges Avatar answered Nov 10 '22 09:11

Alexandre Junges