Form validation with Bootstrap 4 and AngularJS - angularjs

I have a form made with Bootstrap 4 and AngularJS and I want to make a simple form validation where I could:
validate input fields AFTER user has touched them,
show two different error messages depending on validation constraint,
create custom validation constraint (e.g. compare password and password confirmation field).
1.
In previous versions of Bootstrap you could do something like:
<div class="form-group" ng-class="{'has-error': userForm.email.$invalid && userForm.email.$touched}">
but with Bootstrap 4, there is no 'has-error' class. I tried to use 'is-invalid' class instead
<div class="form-group" ng-class="{'is-invalid': userForm.email.$invalid && userForm.email.$touched}">
but nothing happens. I managed to make it work as it is shown in Bootstrap 4 Documentation but validation happens only after the form submission and not when user has touched the input field.
2.
There are no error messages in Bootstrap 4, only 'invalid-feedback' and I can't figure out how to change message text depending on which constraint was violated. I tried something like:
<div class="invalid-feedback">
<p ng-show="userForm.email.$error.required">Required</p>
<p ng-show="userForm.email.$error.email">Enter a valid email</p>
</div>
but this does not work.
3.
I tried to make an Angular directive but because 1. and 2. didn't work I couldn't test this.
Any help will be appreciated.
UPDATE
As Peter Wilson suggested, nothing was wrong with my code. The code didn't work because my form was in a modal window and modal window must have a separate controller in AngularJS to be able to work correctly.

the is-invalid class is the right answer you may have another problem with your form so check my below demo
Note to test touched input you have to focus on the input and then leave focus to trigger touched state
angular.module('myApp',[])
.controller('myCtrl',function(){
})
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.5/angular.js"></script>
<div ng-app="myApp" class="container">
<!-- Button trigger modal -->
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#exampleModal">
Launch demo modal
</button>
<!-- Modal -->
<div class="modal fade" id="exampleModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Modal title</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div ng-controller="myCtrl" class="container">
<form name="loginForm" novalidate>
<div class="form-group">
<label for="exampleInputEmail1">Email address</label>
<input type="email" ng-model="email" required class="form-control" name="email" ng-class="{'is-invalid':loginForm.email.$error.required && loginForm.email.$touched}" placeholder="Enter email">
<small ng-show="loginForm.email.$error.required && loginForm.email.$touched" id="emailHelp" class="form-text text-danger">email is required.</small>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
</div>

Related

How to validate forms in modal with tabs and angularJs

I have a modal form with angular and uib-tabset.
I have only a footer in modal.
Each tabset has a form( A B and C).
When I try enabled/disable the save button on footer, I can´t acesss
acesss the forms. They are undefined.
So, in the 'Save' button(see plunker) - formA.$invalid doesn´t works. I think it is a scope problem.
I´d prefer doesn´t put a global form to all tabs.
Is there some workaround to solve it?
Markup:
<div class="modal-content">
<div class="modal-header bg-primary">
<button type="button" class="close" ng-click="doCancel()" aria-hidden="true">×</button>
<h4 class="modal-title" id="ativarSmsLabel">
Test
</h4>
</div>
<div class="modal-body">
<uib-tabset active="activePill" vertical="false" type="pills">
<uib-tab index="0" heading="Agendamento">
<form name="formA" novalidate>
<input type="text" ng-model="testA"
</form>
</div>
</div>
</div>
</uib-tab>
<uib-tab index="1" heading="Ficha">
<form name="formB" novalidate>
<input type="text" ng-model="testB"
</form>
</uib-tab>
<uib-tab index="2" heading="Histórico">
<form name="formC" novalidate>
<input type="text" ng-model="testC"
</form>
</uib-tab>
</uib-tabset>
</div>
<div class="modal-footer">
<div class="btn-toolbar">
<button type="button" class="btn btn-sm btn-primary pull-right" ng-click="saveItem()"
aria-hidden="true" ng-disabled="formA.$invalid">
Save
</button>
<button type="button" class="btn btn-sm pull-right" ng-click="doCancel()"
aria-hidden="true">
Close
</button>
</div>
</div>
</div>
Core AngularJS directives such as ng-repeat, ng-switch, ng-view, ng-include and ng-if all create new child scopes. As a result, the form controller will attach its API to that child scope. In this case the uib-tabset directive is transcluding to a child scope.
To access form controls on the parent scope, use the ng-form directive to create a nested form:
<form name="top">
<div ng-if="AngularExpression">
<ng-form name="formA" novalidate>
<input ng-model="userData.testA" required />
</ng-form>
</div>
</form>
<div ng-show="top.formA.$error.$required">
ERROR: input required
</div>
Also it is important to follow the "best practice" of always have a dot, '.', in your ng-models.
For more information, see What are the nuances of scope prototypal / prototypical inheritance in AngularJS?.

modal is losing focus on device with narrower display

My app has ui-bootstrap modal with a few inputs and button. It works perfectly on desktop, but on narrower screen the modal is losing focus (cursor disappears from input box) after releasing mouse button, so it's quite difficult to enter anything there.
TIP: It works when I have mouse button pressed. I'm able to enter test:).
modal code:
<div ng-controller="LoginModalCtrl as $ctrl" class="modal-login">
<script type="text/ng-template" id="loginModalContent.html">
<div id="ModalLog" tabindex="-1" role="dialog" aria-labelledby="Zaloguj się">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" aria-label="Close" ng-click="$ctrl.cancel();"><span aria-hidden="true">×</span></button>
<h2 class="modal-title" id="myModalLabel">Zaloguj się do accTrader.com</h2>
</div>
<div class="modal-body">
<form method="post" name="submit_reg">
<label for="login">Login:</label>
<input type="text" placeholder="login" ng-model="$ctrl.loginData.login" name="login" title="Wpisz swój login, użyj 6 do 20 znaków!" required />
<label for="password">Hasło:</label>
<input type="password" placeholder="hasło" ng-model="$ctrl.loginData.password" name="password" title="Wpisz swój login, użyj 8 do 20 znaków!" required />
Zapomniałem hasła :(
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" ng-click="$ctrl.cancel()">Zamknij</button>
<button type="button" class="btn btn-primary btn-md" ng-click="$ctrl.login()">Zaloguj się</button>
</div>
</div>
</div>
</script>
<A ng-click="$ctrl.open()">Zaloguj</A>
</div>
index.html:
<!-- angular modules -->
<script src="scripts/angular/angular.min.js"></script>
<script src="scripts/angular/angular-route.min.js"></script>
<script src="scripts/angular/ui-bootstrap.min.js"></script>
<script src="scripts/angular/angular-animate.min.js"></script>
<script src="scripts/angular/angular-touch.min.js"></script>
<script src="scripts/angular/angular-local-storage.min.js"></script>
UPDATE 1:
I added ngTouch to application modules, but still the same problem:
var app = angular.module('XXXX', [
'ngRoute', 'ui.bootstrap', 'LocalStorageModule', 'duScroll', 'ngTouch'
]).
UPDATE 2: after implementing UPDATE1 it works a bit better:It works stable in FF &IE11, but sometimes it fails in Chrome.

How to get popup when url status success in angular js

I am doing an event scheduler app using angular js. In calendar when i am clicking the event i am sent the event id to back end to getting event details.Here how to get the pop up on my calendar when the url status is true.
My code is:
$scope.alertOnEventClick = function( date, jsEvent, view){
var event_id=date.id;
$http.post("Youin-api/v2/business/event_information",{"event_id":event_id}).then(function(response) {
if(response.error="true")
{
$scope.eventInformation= response;
}
});
};
My bootstrap model pop up is:
<div class="modal fade" id="AddUsers" ng-model="eventInformation" role="dialog">
<div class="modal-dialog " style="top:80px;">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">User Details</h4>
</div>
<div class="modal-body">
<p><form role="form" ng-submit="AddUsers(addusers)">
<div class="form-group">
<label for="pwd">User Type</label>
<input type="text" class="form-control" id="user_type" ng-model="addusers.user_type" value="{{addusers.user_type}}">
</div>
<div class="form-group">
<label for="pwd">Created By</label>
<input ty{{addusers.user_type}}pe="text" class="form-control" id="created_by" ng-model="addusers.created_by" value="">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="submit" class="btn btn-default">Submit</button>
</div>
</form></p>
</div>
</div>
</div>
</div>
thanks in advance..!!
To manually trigger modal to show from javascript. Use this.
$('#AddUsers').modal('show')
Note: You have to add bootstrap.js and jquery.js to use this functionality.
You can view the complete modal api options here.
Wherever you want to open the modal based on your condition you can achieve the same using following:
angular.element(document.getElementById("AddUsers")).modal();

object Object in text box

i have a bootstrap model
<div id="otpModal" class="modal fade" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Enter OTP</h4>
</div>
<div class="modal-body">
<form class="form-otp" name="otp" ng-submit="enterOtp()" >
<div class="row col s6">
<p>A verification code has been sent to your mobile by SMS. Please enter the verification code.
</p>
<input type="text" id="otp" placeholder="enter your OTP code" name="otpName" class="validate" maxlength="6" ng-pattern="/^[0-9]{4,6}$/" ng-model="otp" required>
</div>
<p id="otpMsg" style="color:#e52424"></p>
Resend ?
<button type="submit" ng-disabled="form-otp.$invalid" class="waves-effect waves-light btn done">
<i class="material-icons left">done</i> Done
</button>
</form>
</div>
</div>
</div>
</div>
i have a controller in which enterOtp() & resendOtp() is defined. Problem is text box with name "otpName" is showing [object Object] in it .
Try changing
ng-model="otp"
to
ng-model="otp.name"
You are probably using the wrong field as ng-model.

form-control attribute is not adjusting to bootstrap modal template

I am trying to create a modal with form using angularjs and bootstrap.
First I created the form and now I am trying to put it to modal template but the form-control is sliding out of the modal as you can see in the link attached.
<div class="modal-header">
<h3 class="modal-title">Add New Review</h3>
</div>
<div class="modal-body">
<form role="form">
<fieldset>
<legend>Basic Information</legend>
<div class="container">
<div class="form-group">
<label for="address">Address</label>
<input type="text" id="address" name="address" class="form-control col-sm-1"
ng-model="editableReview.address"
required>
</div>`enter code here`
</fieldset>
</form>
</div>
<div class="modal-footer">
<div class="col-sm-offset-10">
<input type="button" class="btn btn-default" value="Cancel" ng-click="cancelForm()"/>
<input type="submit" class="btn btn-primary" value="Submit" ng-click="submitForm()"/>
</div>
</div>
this is what I get:
It seems like your problem is with the div class, specifically the container. I think you should try to delete this line:
<div class="container">
(and ofcourse its closing tag: </div>, and see if it fixes your issue.
Let me know if that helps.

Resources