Form validation with modals in Angular - angularjs

I have a form inside a modal pop up. I am trying to run form validation on the inputs after the user attempts to submit the form. So far, I'm struggling to make things work.
In my view, I have the following (sorry if there are any syntax errors, I'm converting this from jade on the fly):
<script type="text/ng-template", id="modalVideoNew">
<div class="ngdialog-message">
<form class="form-horizontal" ng-submit="submitForm()" novalidate name="newVideoForm">
...
<div class="form-group">
<label> Title </label>
<div class="col-sm-8">
<input type="text" name="title", required='', ng-model="newVideoForm.title">
<span class="text-danger" ng-show="validateInput('newVideoForm.title', 'required')"> This field is required</span>
</div>
</div>
</div>
</script>
And then in my controller, where I'm calling the ng-dialog pop up, I have this:
$scope.newVideo = function() {
ngDialog.openConfirm({
template: 'modalVideoNew',
className: 'ngdialog-theme-default',
scope: $scope
}).then(function() {
$scope.validateInput = function(name, type) {
var input = $scope.newVideoForm[name];
return (input.$dirty || $scope.submitted) && input.$error[type];
};
var newVideo = $scope.newVideoForm;
...
Right now, I am still able to submit the form, but once I open it back up I see the 'This field is required' error message. Also, the input is pre-filled with [object, Object] instead of an empty text input box.

A way of cleaning your model would work with using a model var that belongs to your parent controller and cleaning it in the callback. Check out how the template has attached your parent controller's var FormData.
Check this out
So about your validation, what I would recommend you is to have your own controller in it, no matter how much code it will have. It helps you keeping concepts of modularization and a better control over your scopes. This way will also facilitate a lot when validating.

Related

Angular js ng messages show error on init

In my project I have angularjs 1.5.10 and ng-messages 1.5.10. I use it in simple form:
<form class="form-horizontal" ng-submit="createBooking()" role="form" name="createBookingForm" novalidate>
<div class="form-group">
<label for="payment_details_last_name" class="col-sm-3 control-label">Last name</label>
<div class="col-sm-6">
<input type="text"
id="payment_details_last_name"
name="payment_details_last_name"
class="form-control"
ng-model="payment_details.last_name"
ng-required="true"
ng-maxlength="30" />
<div ng-messages="createBookingForm.payment_details_last_name.$error" role="alert">
<div ng-message="required">This field is required</div>
<div ng-message="maxlength">Your field is too long</div>
</div>
</div>
<div class="col-sm-3"></div>
</div>
</form>
In controller:
$scope.members = [{
'first_name': '',
'last_name': '',
'email': '',
'phone_number': '',
'date_of_birth': '',
}];
And on initial I always see error This field is required. I tried to create empty object in controller:
$scope.createBookingForm = {};
I also show form after initialized <div ng-if="initialized">
Nothing is working. Project using angular-seed skeleton
I saw dirty hacks like if $touched else, but I want to understand what is wrong...
Nothing is wrong about it, check out the sample in the official guide. They have required error shown by default. It seems wrong for the first glance, but this is the only correct way to handle such a case.
So basically, ng-messages does exactly what docs says:
ngMessages is a directive that is designed to show and hide messages
based on the state of a key/value object that it listens on.
the directive works in a real time and shows errors for current input state, that makes sense.
So if you want no messages to be shown by default, you should use some of approaches, discussed hundred of times
How to make ngMessage for required fields only show when dirty or submitting a form?
Angular : ng-message validation on submit click
AngularJS: Hiding ng-message until hitting the form-submit button
AngularJS 1.5.6 reset form & ng-messages
If you need some other improved behavior - there is no quick solution at the moment, you have to come up with your own validation engine that fit your needs.

Angular validation (can't reach controller if required fields are empty)

I'm trying to implement validation for a form using Angular 1.1.1 and Ionic.
There are many "wallets" and the user needs to send a new "value" to each of the wallet. There's also a specified previous value of the wallet. The validation should check if all the input field are filled out and if the new value is bigger than previous.
My form (index.html):
<form name="myForm" ng-submit="sendValues(wallets)" ng-controller="valuesCtrl">
<div class="row" ng-repeat="wallet in wallets">
<div class="col item item-input-inset">
<label class="item-input-wrapper item-text-wrap">
<input name="wallet_{{wallet.id}}" type="number" ng-model="wallet.value" type="text" required/>
</label>
<span ng-show="myForm.wallet_{{item.id}}.$error.required">!!!</span>
</div>
<div class="col item">{{ wallet.previous }}</div>
</div>
<button class="button" type="submit">Submit</button>
</form>
It results in always showing "!!!" error for empty input even if the user haven't already submitted the form. I tried to use $scope.myForm.submitted=true; in the controller but the problem is it reaches the controller only if all the fields are filled out.
My controller (values.js):
'Use Strict';
angular.module('App')
.controller('valuesCtrl', function($scope, $localStorage, UserService, $state) {
$scope.sendValues = function(wallets){
debugger;
...
})
Can anyone help me to figure out why I can't see the debugger window if not all the fields are with info?
Can you suggest how to make a custom validation? (new value should be bigger than previous)
It results in always showing "!!!" error for empty input even if the user haven't already submitted the form?
Your ng-show should be
ng-show="myForm.$submitted==true && myForm.wallet_{{item.id}}.$error.required"
and form should be have novalidate attribute if you want custom validation
<form name="myForm" ng-submit="sendValues(wallets)" novalidate>
otherwise it will do default html validation
I tried to use $scope.myForm.submitted=true; in the controller but the problem is it reaches the controller only if all the fields are filled out
Its because ng-submit will validate for true condition($valid==true) for every form control element .
If it is filled and valid data then only form $valid flag is set to true otherwise not.In case $valid==true,you will able to submit the form and function in controller get fired
you can use
<input type="submit" ng-click="sendValues(wallets)" value="Save" />
if you want to submit the form without validation and want to do validation in controller
You can read more from angular#form

injecting error manually to form

Is there any way to inject error manually to form, I know the way via directive but not sure how can inject error from the controller.
<div ng-controller="myController">
<form name="createForm">
<div ng-repeat="item in someItems">
<input type="text" ng-change="customValidation()" />
</div>
<input type="button" ng-disabled="createForm.$invalid" value="Submit" />
</form>
</div>
controller
function myController($scope) {
$scope.customValidation = function() {
//do some validation and made createForm valid/invalid based on it
};
}
Yes, You can do it in two ways.
instead of Creaeform.$invalid. You can use some value inside your scope.
You should set the value true or false depending on the validation result of the input. If this doesn't make sense to you, give a comment. I'll give some code.
another way is passing the form object itself to the controller and set the createForm.$valid = false; in the controller.

Angular Form HTML from API with ng-model not binding

So I'm generating form HTML on the server and serving it up via an API for angular to use. The reason for this is that the forms need to be generated by server-side plugins. This may not be the best way do to it for Angular, but I'm asking whether it will be possible...
template.html
<form>
<div ng-bind-html="form"></div>
<button ng-click="save"></button>
</form>
directive.js (abridged)
ExtensionManagementService.getConfiguration({
extension_id: $scope.extension.id,
configuration_id: configuration.id || null
}).$promise.then(function(data) {
$scope.form = $sce.trustAsHtml(data['form']);
$scope.configuration = data.data;
})
The code above binds successfully into the div and I can see the form as I expect.
Example markup:
<p>
<label for="id_name">Name:</label>
<input id="id_name" name="name" ng-model="configuration.name" type="text" />
</p>
I have a save event that passes the scope.configuration into a controller which I then console out the values.
However configuration.name is always blank, I expect because angular hasn't registered the binding of the inserted markup.
Is there a way to essentially give Angular a nudge?
As #originof suggested, and a colleague almost beat him to it, the $compile module is the key to this:
ExtensionManagementService.getConfiguration({
extension_id: $scope.extension.id,
configuration_id: configuration.id || null
}).$promise.then(function(data) {
var form_element = $element.find('div[role="form"]');
form_element.html(data['form']);
$scope.configuration = data.data;
$compile(form_element.contents())($scope);
});

Validating repeating inputs inside an AngularJS form

I know this has been asked before, and have even found a well-upvoted answer here:
How to validate inputs dynamically created using ng-repeat, ng-show (angular)
But I can't get that solution to work. I've got an example here - annoyingly both jsFiddle and Plunkr seem to be down right now.
Here's the JS:
app.controller('DetailsCtrl', ['$scope', function($scope) {
$scope.loading = false;
$scope.formData = {
lines: [{
text: 'test.com'}]
};
$scope.addRow = function() {
$scope.formData.lines.push({text:null});
};
}]);
Here's the markup:
<body ng-controller="DetailsCtrl">
<div>
<form name="mainForm" novalidate class="form-vertical">
...some non-repeating inputs go in here...
<div data-ng-repeat="line in formData.lines" data-ng-form="lineForm">
<input type="text" name="myinput" data-ng-model="line.text" data-ng-required="true">
<span data-ng-show="mainForm.lineForm.myinput.$error.required">Error!</span>
</div>
New Line
</form>
</div>
</body>
You'll notice initially there is one text input with text in - great. Click the 'New Line' link. Because the new text input fails validation - BOTH text inputs get the warning span shown... I just want the one span relating to the one empty text input to show up.
As AngularJS relays on input names to expose validation errors, and you used the same name for all inputs, you faced with this effect.
So you can't generate input name dynamically, but instead you can use ng-form (see https://docs.angularjs.org/api/ng/directive/ngForm).
<form name="mainForm" novalidate class="form-vertical">...some non-repeating inputs go in here...
<div data-ng-repeat="line in formData.lines" data-ng-form="lineForm">
<input type="text" name="myinput" data-ng-model="line.text" data-ng-required="true">
<span data-ng-show="lineForm.myinput.$error.required">Error!</span>
</div> New Line
</form>
EDIT. Please note, access to error myinput.$error.required instead of lineForm.myinput.$error.required.
Please, checkout working fiddle http://jsfiddle.net/Y9g4q/7/.

Resources