Why angular sets undefined to empty ng-model fields
Asked Answered
G

2

15

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

Gayomart answered 1/10, 2014 at 9:26 Comment(0)
C
18

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

Cookshop answered 1/10, 2014 at 10:55 Comment(2)
I need to the required attribute for the input cause Angular form validation... And Yes I have novalidate on the form tag it doesn't helpGayomart
Unfortunately that is just not the way "required" works in angular. See my edited answer.Cookshop
M
19

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 }"/>
Morphophonemics answered 17/3, 2016 at 13:5 Comment(1)
Perfection - I was wondering why my model was being set to undefined, whenever my validation failed! This fixed the issue. Thanks!Catholicize
C
18

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

Cookshop answered 1/10, 2014 at 10:55 Comment(2)
I need to the required attribute for the input cause Angular form validation... And Yes I have novalidate on the form tag it doesn't helpGayomart
Unfortunately that is just not the way "required" works in angular. See my edited answer.Cookshop

© 2022 - 2024 — McMap. All rights reserved.