Monday, May 20, 2024
 Popular · Latest · Hot · Upcoming
39
rated 0 times [  44] [ 5]  / answers: 1 / hits: 7790  / 11 Years ago, sat, january 25, 2014, 12:00:00

I need to be able to temporarily persist data that isn't fully validated yet, then enforce validation when I'm ready to make it permanent. But Angular is preventing that.



I have a form. The user can saveDraft() on early versions of the form, which are persisted to the server. Then, when the user is ready, they can submit() the form, which will persist it with different flags, thus beginning the actual processing of that data.



The problem I'm running into is with Angular's built-in validations. When a user enters some data into an input with validations on it, that data is cached on the $viewValue property. But if validation fails, it's never copied to the $modelValue property, which is a reference to the actual $scope property I bound the input to. And hence the 'invalid' value will not be persisted.



But we need to persist it. We'll deal with forcing the user to correct their validation failures later, when they submit(). Also, we have no way to know whether the user is going to saveDraft() or submit() on a particular instance of the view/controller, so we can't setup the views and validation differently beforehand.



My thinking is that we need to somehow iterate the form elements and get Angular to somehow let the data go through. But I can't find a way that's flexible and scalable.



I've tried setting $scope.formName.inputName.$modelValue = $scope.formName.inputName.$viewValue, but that seems to just upset the gods, as both values are then null'ed.



I've tried using $scope.formName.inputName.$setValidity('', true), but that only updates the UI state. It never touches $modelValue.



I can successfully use $scope.model.boundPropertyName = $scope.formName.inputName.$viewValue but that feels very imperative and won't allow any variance between the identifiers for boundPropertyName and inputName. In other words, you either need individual functions for all form controls, or you need to rely on naming conventions. Both of which are super-brittle.



So... how can I get that $modelValue updated elegantly? And/Or, is there another, better way to obtain the same results, whereby sometimes I can persist with validation, and sometimes persist without?



Other options I'm considering, but not happy with:




  • Run validation manually, only when the user hits submit(). But that defeats the UX value of instant, inline validation in the UI. We might as well just offload all the validation to the server and do a round-trip each time.

  • Make copies of ngModel and ngModelController, and monkey-patch them to update $modelValue regardless of validity. But that hacks the framework when there should be a more elegant path.



See CodePen here.



(Side-note: Angular appears to be filtering the data according to the validator in both directions. If you set a default value on the model for formData.zip of '1234', which isn't enough characters to validate, Angular doesn't even show it. It never reaches the initial $viewValue.)


More From » html

 Answers
3

The following solution can be used since Angular version 1.3:



You can set ng-model-options={ allowInvalid: true } in the input field of the model where you want to persist invalid attributes.




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




https://docs.angularjs.org/api/ng/directive/ngModelOptions



Then, when you are ready to show the user their validation errors, you are free to do it your way. Just remember to give your inputs and forms name attributes, so that you can reference them in your scope.



E.g. if($scope.myFormName.my_input_name.$invalid) { ... }



A relevant tutorial: http://blog.thoughtram.io/angularjs/2014/10/19/exploring-angular-1.3-ng-model-options.html


[#48363] Friday, January 24, 2014, 11 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
jaleelh

Total Points: 661
Total Questions: 125
Total Answers: 103

Location: Sweden
Member since Mon, May 8, 2023
1 Year ago
;