I am having trouble with form validation in AngularJS. I am trying to show a div based on whether an input is invalid. Angular is putting the correct classes on my inputs (ng-touched and ng-invalid) but it is still keeping the div with a ng-hide class.
form.html
<form id="" name="contactForm"
ng-submit="postForm()" novalidate>
<div class="form-group row">
<label for="full-name" class="col-lg-2 col-md-3 col-xs-4 col-form-label">Name</label>
<div class="col-lg-10 col-md-9 col-xs-8">
<input class="form-control" type="text" placeholder="Jon Doe"
id="full-name" required data-ng-model="formData.name">
</div>
</div>
<!-- This is the only input implemented with the errors -->
<div class="form-group row">
<label for="phone-number" class="col-lg-2 col-md-3 col-xs-4 col-form-label">Phone
Number</label>
<div class="col-lg-10 col-md-9 col-xs-8">
<input class="form-control" type="tel"
placeholder="(630) 555-6723" id="phone-number" required
data-ng-model="formData.phone" name="phone" ng-minlength="10"/>
</div>
<div ng-show="(contactForm.phone.$invalid && contactForm.phone.$touched) || contactForm.phone.$error.minlength">Please enter a valid phone
number.</div>
</div>
<div class="form-group row">
<label for="email" class="col-lg-2 col-md-3 col-xs-4 col-form-label">Email</label>
<div class="col-lg-10 col-md-9 col-xs-8">
<input class="form-control" type="email"
placeholder="jon.doe#gmail.com" id="email" required
data-ng-model="formData.email" />
<div class="invalid-feedback">Please enter a valid email.</div>
</div>
</div>
<div class="form-group row">
<label class="col-2 col-form-label">Contact Method</label>
<div class="col-lg-2 col-md-3 col-xs-4">
<label class="custom-control custom-radio"> <input
id="radio1" name="email" type="radio"
class="custom-control-input" checked="checked"
data-ng-model="formData.pref"> <span
class="custom-control-indicator"></span> <span
class="custom-control-description">Email</span>
</label> <label class="custom-control custom-radio"> <input
id="radio2" name="phone" type="radio"
class="custom-control-input" data-ng-model="formData.pref">
<span class="custom-control-indicator"></span> <span
class="custom-control-description">Phone</span>
</label>
</div>
</div>
<div class="form-group row">
<label for="full-name" class="col-lg-2 col-md-3 col-xs-4 col-form-label">Body</label>
<div class="col-lg-10 col-md-9 col-xs-8">
<textarea rows="15" class="form-control"
placeholder="Type your message here..." id="body-text" required
data-ng-model="formData.body"></textarea>
<div class="invalid-feedback">Please enter a message here.</div>
</div>
</div>
<div class="text-center">
<button ng-disabled="contactForm.$invalid" class="btn-primary btn" type="submit">Submit</button>
</div>
</form>
</div>
angular.js
<!-- SCRIPTS -->
<script>
//form validate
var app = angular.module('contactUs', []);
app.controller('formCtrl', function($scope, $http) {
$scope.formData = {};
$scope.postForm = function() {
$('#loadingScreen').modal('show');
$http({
url : '/api/v1/contact',
method : 'POST',
data : $.param($scope.formData),
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
})
.then(function onSuccess() {
console.log("success");
window.scrollTo(0,0);
$('#success-message').show();
}, function onError(){
console.log("error");
window.scrollTo(0,0);
$('#error-message').show();
})
.then(function() {
$('#loadingScreen').modal('hide');
})
}
$scope.formData = {};
});
</script>
Looking at other errors I made sure that the ng-show was using the formName.inputName and that the app and controller were working correctly. The button is disabled correctly when the form is invalid which leads me to believe that the controller and app are not the problem.
I tried using ng-messages which changed my phone portion of the form to
<div class="form-group row">
<label for="phone-number" class="col-lg-2 col-md-3 col-xs-4 col-form-label">Phone
Number</label>
<div class="col-lg-10 col-md-9 col-xs-8">
<input class="form-control" type="tel"
placeholder="(630) 555-6723" id="phone-number" required
data-ng-model="formData.phone" name="phone" ng-minlength="10"/>
</div>
<div ng-messages="contactForm.phone.$error" class="error" ng-if="contactForm.phone.$dirty">
<div ng-message="required">Please enter a phone number we can reach you at.</div>
<div ng-message="pattern">Please enter a valid phone number here.</div>
<div ng-message="minlength">Please enter a phone number that's atleast 10 digits</div>
</div>
</div>
Angular is still adding the correct classes to the input but it is still not displaying. I believe the ng-if is evaluating false. Oddly, when I run
{{contactForm.phone.$dirty}}
in the console it is coming back as undefined
Take a look here and you can see how I got it working. I'll break down the steps below. https://plnkr.co/edit/LJYurBObZsS6ptlVKxvP?p=preview
With the change to using ng-messages, you need to include that module in your app. I wasn't sure if you had made this change or not, but it's straightforward. Include the script for the library, and then update your modules to include ngMessages as a dependency.
var app = angular.module('contactUs', ['ngMessages']);
The second part is fixing a typo. In your html for the contact method area, you have
<label class="custom-control custom-radio">
<input id="radio2" name="phone" type="radio" class="custom-control-input" data-ng-model="formData.pref">
<span class="custom-control-indicator"></span>
<span class="custom-control-description">Phone</span>
</label>
You're reusing the name "phone" there, which is going to cause problems since you'll have two different form items with the same name. Probably change those inputs to emailPreference and phonePreference or something to be clear.
As soon as I cleaned that up, it started working. So I think you were all there, just this typo was getting you.
Related
I want to load data of a selected row in a form in order to update it. I successfully had the data loaded in the form, the but the problem is when I use ng model to save the data all the stuff have been put in the form fields disappear.
<div class="panel-body pan" ng-if="loadedpr">
<form action="#">
<div class="form-body pal">
<div class="row">
<div class="col-md-2">
<div class="form-group">
<label for="refprojet" class="control-label">
Référence Projet *</label>
<input id="refprojet" type="text" value="{{loadedpr.ref_projet}}" class="form-control" disabled ng-model="ref_projet"/>
</div>
</div>
<div class="col-md-5">
<div class="form-group">
<label for="intitulefr" class="control-label">
Intitulé *</label>
<input id="intitulefr" type="text" value="{{loadedpr.intitule_fr}}" class="form-control" ng-model="intitule_fr" />
</div>
</div>
<div class="col-md-5">
<div class="form-group">
<label for="ctot" class="control-label"> Coût Total (TND) *</label>
<input id="ctot" type="text" value="{{loadedpr.cout_total}}" ng-model="cout_total" class="form-control" disabled ng-model="cout_total" />
</div>
</div>
</div>
<div class="form-group">
<label for="description" class="control-label">
Description</label><textarea id="description" rows="3" value="{{loadedpr.description}}" ng-model="description" class="form-control"></textarea>
</div>
<div class="form-actions text-center pal">
<button type="submit" class="btn btn-primary" ng-click="upadateProjet()">Valider</button>
</div>
</div>
</form>
this is the angularjs method:
$scope.updateProjet= function(){
$scope.projet={'ref_projet':$scope.refprojet,'intitule_fr':$scope.intitule_fr,'description':$scope.description,cout_total':$scope.cout_total};
$http.put("/editprojet", $scope.projet)
.success(function(data,status,headers,config){
});
}
rest controller
#RequestMapping(value="/editprojet",method=RequestMethod.PUT)
public Projet editProjet(#RequestBody Projet p) {
return projetMetier.editProjet(p);
}
you are using button type="submit"
it will clear the form use button tag
<button></button>
$scope.updateProjet= function(projData){
$http.put("/editprojet", projData)
.success(function(data,status,headers,config){
}).error(function(data){
console.log(data)
});
}
<div class="panel-body pan" ng-if="loadedpr">
<form action="#">
<div class="form-body pal">
<div class="row">
<div class="col-md-2">
<div class="form-group">
<label for="refprojet" class="control-label">
Référence Projet *</label>
<input id="refprojet" type="text" value="{{loadedpr.ref_projet}}" class="form-control" disabled ng-model="proj.ref_projet"/>
</div>
</div>
<div class="col-md-5">
<div class="form-group">
<label for="intitulefr" class="control-label">
Intitulé *</label>
<input id="intitulefr" type="text" value="{{loadedpr.intitule_fr}}" class="form-control" ng-model="proj.intitule_fr" />
</div>
</div>
<div class="col-md-5">
<div class="form-group">
<label for="ctot" class="control-label"> Coût Total (TND) *</label>
<input id="ctot" type="text" value="{{loadedpr.cout_total}}" ng-model="proj.cout_total" class="form-control" disabled ng-model="proj.cout_total" />
</div>
</div>
</div>
<div class="form-group">
<label for="description" class="control-label">
Description</label><textarea id="description" rows="3" value="{{loadedpr.description}}" ng-model="proj.description" class="form-control"></textarea>
</div>
<div class="form-actions text-center pal">
<button type="button" class="btn btn-primary" ng-click="upadateProjet(proj)">Valider</button>
</div>
</div>
</form>
</div>
have you tried removing the value attribute? this happened to me when I once added DOM forms on the fly, I managed by using jquery to force capture by:
$(this).find('.inputClass').val();
this sort of jequery is already embeded inside Angular so no need to add the the library.
I am developing an application where I am using bootstrap and angular together. Form validation using angular and bootstrap is working fine but I have a problem to reset the form. I call $setPristine() but it doesn't seem to be doing anything.
Here is my html.
<div class="cl-xs-12" style="margin-top:20px">
<div class="col-xs-3"></div>
<div ng-controller="AddUpdateUserController" class="col-xs-6">
<form class="form-horizontal" role="form" id="addEditMemberForm" name="addEditMemberForm" ng-submit="addUpdateMember(member)" novalidate>
<input type="hidden" id="mmeberId", name="memberId" ng-model="member.id">
<div class="form-group required" ng-class="{ 'has-error': addEditMemberForm.firstName.$invalid && addEditMemberForm.firstName.$dirty}">
<label for="firstName" class="control-label col-xs-4">First Name</label>
<div class="col-xs-8">
<input type="text" class="form-control" id="firstName" name="firstName" placeholder="First Name" ng-model="member.firstName" ng-pattern="/^[0-9A-Za-z]+$/" required>
<div ng-show="addEditMemberForm.$submitted || addEditMemberForm.firstName.$touched" ng-messages="addEditMemberForm.firstName.$error">
<div ng-show="addEditMemberForm.firstName.$error.required" class="validationErrorMessage">First Name is required</div>
<div class="validationErrorMessage" ng-message="pattern">First name is invalid. Only Alphanumeric characters are allowed</div>
</div>
</div>
</div>
<div class="form-group required" ng-class="{ 'has-error': addEditMemberForm.middleName.$invalid && addEditMemberForm.middleName.$dirty}">
<label for="lastName" class="control-label col-xs-4">Middle Name</label>
<div class="col-xs-8">
<input type="text" class="form-control" id="middleName" name="middleName" placeholder="Middle Name" ng-model="member.middleName" ng-pattern="/^[0-9A-Za-z]+$/" required>
<div ng-show="addEditMemberForm.$submitted || addEditMemberForm.middleName.$touched" ng-messages="addEditMemberForm.middleName.$error">
<div class="validationErrorMessage" ng-message="required">Middle name is required.</div>
<div class="validationErrorMessage" ng-message="pattern">Middle name is invalid. . Only Alphanumeric characters are allowed</div>
</div>
</div>
</div>
<div class="form-group required" ng-class="{ 'has-error': addEditMemberForm.lastName.$invalid && addEditMemberForm.lastName.$dirty}">
<label for="lastName" class="control-label col-xs-4">Last Name</label>
<div class="col-xs-8">
<input type="text" class="form-control" id="lastName" name="lastName" placeholder="Last Name" ng-model="member.lastName" ng-pattern="/^[0-9A-Za-z]+$/" required>
<div ng-show="addEditMemberForm.$submitted || addEditMemberForm.lastName.$touched" ng-messages="addEditMemberForm.lastName.$error">
<div ng-show="addEditMemberForm.lastName.$error.required" class="validationErrorMessage">Last Name is required</div>
<div class="validationErrorMessage" ng-message="pattern">Last name is invalid. . Only Alphanumeric characters are allowed</div>
</div>
</div>
</div>
</form>
<div class="row">
<label>{{message}}</label>
</div>
<label ng-model="status"></label>
</div>
<div class="col-xs-3"></div>
</div>
Here is my Javascript:
angular.module('SiteControllerModule').controller('AddUpdateUserController', ['$scope', '$http', '$location', function($scope, $http, $location){
$scope.resetForm = function () {
$scope.member = null;
$scope.addEditMemberForm.$setPristine();
}
}]);
When $setPristine is called, my form is still dirty and looks like it left behind my Bootstrap validation Error.
Any help related to this is appreciated.
Thanks
Try this too:
$scope.addEditMemberForm.$setPristine();
$scope.addEditMemberForm.$setUntouched();
I'm getting set of data by calling a GET method in angularjs.
controller
$scope.edit = function (id) {
var edit_url = 'http://localhost/AwtCW2012002/api/restApiController/editQuestion.json?question_id=' + id;
$http.get(edit_url)
.success(function (data) {
console.log(data);
})
.error(function () {
})
};
Data from the GET method is like follows
How can I pass the data into respective fields in my view (into placeholders, as this view is used to edit existing data)
view
<div class="container" ng-controller="questionEditCtrl">
<form class="form-horizontal" role="form" name='quizAdd' ng-submit="submit(data)">
<div class="form-group">
<label class="control-label col-sm-2" for="question">Question:</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="question" ng-model="data.question" placeholder="Enter Question">
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="answer1">Answer 1:</label>
<div class="col-sm-10">
<input type="text" class="form-control" name="answer1" ng-model="data.ans1" id="answer1" placeholder="Enter Answer 1">
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="answer2">Answer 2:</label>
<div class="col-sm-10">
<input type="text" class="form-control" name="answer2" ng-model="data.ans2" id="answer2" placeholder="Enter Answer 2">
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="answer3">Answer 3:</label>
<div class="col-sm-10">
<input type="text" class="form-control" name="answer3" ng-model="data.ans3" id="answer4" placeholder="Enter Answer 3">
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="answer4">Answer 4:</label>
<div class="col-sm-10">
<input type="text" class="form-control" name="answer4" id="answer4" ng-model="data.ans4" placeholder="Enter Answer 4">
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="answer5">Answer 5:</label>
<div class="col-sm-10">
<input type="text" class="form-control" name="answer5" id="answer5" ng-model="data.ans5" placeholder="Enter Answer 5">
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="sel1">Select Correct Answer:</label>
<div class="col-sm-10">
<select class="form-control" ng-model="data.correct_ans" id="sel1">
<option>{{data.ans1}}</option>
<option>{{data.ans2}}</option>
<option>{{data.ans3}}</option>
<option>{{data.ans4}}</option>
<option>{{data.ans5}}</option>
</select>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-default">Submit</button>
</div>
</div>
</form>
</div>
You are getting the response in array. Use ng-repeat to render you fields. What you perform ng-repeat, you can add placeholder like,
placeholder="Write Answer {{$index}}"
Firstly, populate a $scope variable with the data from the api for it to be available for binding in the template:
$http.get(edit_url)
.success(function (data) {
$scope.data = data; //populate a scope variable
})
.error(function () {
});
Then, you can use one time expressions :: for your placeholders as follows:
placeholder="{{::data.ans1}}"
This will ensure only the default value of data.ans1 which was fetched from the api will be used as the placeholder. All subsequent changes to data.ans1 will change the value, but the placeholder will remain the same.
I am setting up a blog and have a contact form page (standard bootstrap blog template)
I have everything uploaded onto my host - hostgator, but I can't manage to get the contact form to send an email out properly.
I have tried both an external email account and an account on the same domain name with no luck.
Here is the original html source for the contact page from bootstrap: https://github.com/IronSummitMedia/startbootstrap-clean-blog/blob/gh-pages/contact.html
and the original source for the contact_me.php: https://github.com/IronSummitMedia/startbootstrap-clean-blog/blob/gh-pages/mail/contact_me.php
Is there a setting I need to change from the hostgator cpanel or something in the code I'm missing?
Edit: Here is my domain if you want to view the source I have in place:
www.decentralizeblog.com
I have made bit changes to the form
you have not used certain attributes in your form
link method, action and name attribute in text field
<form name="sentMessage" id="contactForm" action="mailer.php" method="post" novalidate>
<div class="row control-group">
<div class="form-group col-xs-12 floating-label-form-group controls">
<label>Name</label>
<input type="text" name="name" class="form-control" placeholder="Name" id="name" required data-validation-required-message="Please enter your name.">
<p class="help-block text-danger"></p>
</div>
</div>
<div class="row control-group">
<div class="form-group col-xs-12 floating-label-form-group controls">
<label>Email Address</label>
<input type="email" name="email" class="form-control" placeholder="Email Address" id="email" required data-validation-required-message="Please enter your email address.">
<p class="help-block text-danger"></p>
</div>
</div>
<div class="row control-group">
<div class="form-group col-xs-12 floating-label-form-group controls">
<label>Phone Number</label>
<input type="tel" name="phone" class="form-control" placeholder="Phone Number" id="phone" required data-validation-required-message="Please enter your phone number.">
<p class="help-block text-danger"></p>
</div>
</div>
<div class="row control-group">
<div class="form-group col-xs-12 floating-label-form-group controls">
<label>Message</label>
<textarea rows="5" name="message" class="form-control" placeholder="Message" id="message" required data-validation-required-message="Please enter a message."></textarea>
<p class="help-block text-danger"></p>
</div>
</div>
<br>
<div id="success"></div>
<div class="row">
<div class="form-group col-xs-12">
<button type="submit" class="btn btn-default">Send</button>
</div>
</div>
</form>
This may not be a problem with your code, have you checked that your hostgator plan supports the php mail() function? Some plans (I know from experience) have this disabled as an incentive for you to upgrade.
Hope this helps.
Right now I'm working on a project in which I need to use JSlider plugin of jquery with Angularjs. I tried to use this plugin into a directive and within directive I put this in $evalAsync so that I assign the values dynamically to Jslider after content loaded and before page rendering. The way I did this is mentioned below:-
var sliderDirective = angular.module("sliderModule",[]);
sliderDirective.directive("slider",function(){
return {
restrict: 'AE',
replace: true,
template: '<input id="slider" name="price" type="slider" value="{{filters.price}}">',
link: function(scope, elem, attrs) {
scope.$evalAsync(function(scope){
elem.slider({
from: 0,
to: 3000,
step: 50,
smooth: true,
round: 0,
limits: false,
scale: ['$0','|','$500','|','$1,000','|','$1,500','|','$2,000','|','$2,500','|','$3,000+'],
skin: "blue",
onstatechange:function(value){
scope.filters.price = value;
}
})
})
}
}
})
I'm setting the values dynamically that are being passing in link function's scope variable. But the problem is this that the slider doesn't get these dynamic values and shows only single pointer with value zero. So, anybody who has some solution for this problem. Also, there is a possibility that I followed a wrong way of doing this so please make me correct in that case.
I recommend you set the scope attribute of the directive to something like:
scope : {
values: '='
}
This means you have to provide the values through databinding to the directive. You can then watch the values in the linking function of the directive. As soon as they are not null, call the elem.slider function. I recommend to not use the evalAsync but use a watcher like this instead
Recently I have used RANGE SLIDER in angularJS.
<form>
<div class="choose_industry">
<div class="form-group">
<label class="control-label col-xs-12 col-sm-4 col-md-2 col-lg-2 " for="name">What Industry?</label>
<div class="col-xs-12 col-sm-8 col-md-10 col-lg-10">
<div class="radio col-xs-6 col-sm-6 col-md-6 col-lg-6">
<input type="radio" name="radio1" id="radio1" value="cdl" ng-model="leg_ser.industry">
<label for="radio1">
Commercial Trucking Transportation
</label>
</div>
<div class="radio col-xs-6 col-sm-6 col-md-6 col-lg-6">
<input type="radio" name="radio1" id="radio2" value="non_cdl" ng-model="leg_ser.industry">
<label for="radio2">
Other Industries
</label>
</div>
</div>
</div>
</div>
<div class="employee_counting">
<div class="form-group col-xs-12 col-sm-4 col-md-4 col-lg-4">
<label class="control-label" for="name">Number of Employees?</label>
<div class="input-group">
<span class="input-group-addon"><i class="fa fa-user"></i></span>
<input type="number" class="form-control" placeholder="Employees" name="Number of Employees" ng-model="leg_ser.num_of_emp">
<!-- <span>Total Number of Employees</span> -->
</div>
<div class="range_slider">
<span class="pull-left">0</span>
<span class="pull-right">25k</span>
<div id="slidecontainer">
<input type="range" min="0" max="25000" value="0" class="slider" id="myRange" ng-model="leg_ser.num_of_emp">
</div>
</div>
</div>
<div class="form-group col-xs-12 col-sm-4 col-md-4 col-lg-4">
<label class="control-label" for="name">Enrollment Percentage (%)?</label>
<div class="input-group">
<span class="input-group-addon"><i class="fa fa-percent"></i></span>
<input type="number" class="form-control" placeholder="Percentage" name="Enrollment Percentage" ng-model="leg_ser.enroll_per">
<!-- <span>Estimated Percentage that will enroll</span> -->
</div>
<div class="range_slider">
<span class="pull-left">0%</span>
<span class="pull-right">100%</span>
<div id="slidecontainer">
<input type="range" min="1" max="100" value="1" class="slider" id="myRange" ng-model="leg_ser.enroll_per">
</div>
</div>
</div>
<div class="form-group col-xs-12 col-sm-4 col-md-4 col-lg-4">
<label class="control-label" for="name">Annual Cost per Employees?</label>
<div class="input-group">
<span class="input-group-addon"><i class="fa fa-dollar"></i></span>
<input type="number" class="form-control" placeholder="Cost" name="Annual Cost per Employees" ng-model="leg_ser.annual_cost">
<!-- <span>Avarage Salary and benifits per Employee</span> -->
</div>
<div class="range_slider">
<span class="pull-left">$0</span>
<span class="pull-right">$300k</span>
<div id="slidecontainer">
<input type="range" min="0" max="300000" value="0" class="slider" id="myRange" ng-model="leg_ser.annual_cost">
</div>
</div>
</div>
</div>
</form>
Add following code in the script tag
<!-- RANGE SLIDER JS START -->
<script>
var slider = document.getElementById("myRange");
var output = document.getElementById("demo");
output.innerHTML = slider.value;
slider.oninput = function() {
output.innerHTML = this.value;
}
</script>
<!-- RANGE SLIDER JS OVER -->
Above script working good for me, should work for you too.