I'm trying to impliment some CRUD page with AngularJS. So i have input with some validation requirements
<input ng-class="addForm.country.$error.pattern?'bad-input-border':''"
name="country"
ng-model="adding_element.country"
type="text"
pattern="[A-Za-z]+"
class="form-control">
Pattern that match only letters.
Also i have bingding model with that input.
The problem is: when i change input value directly on page, validation works fine addForm.country.$valid == true; but when i'm trying to change my model from code i get addForm.country.$valid == false even if data is valid.
I changing model on button click, that get generated element from my controller:
$scope.generate_country = function()
{
$http.get("/index.php/cars/generate").then(function(response){
$scope.adding_element.country = response.data.item.Country;
});
};
The result in response.data.item.Country is string. It fails input pattern when i click the button, but when i CTRL+C CTRL+V generated result in input it's OK.
How can i solve that? TIA!
Related
I'm running into a strange issue in Firefox that I hope someone can explain to me. I have an AngularJS controller with a method that is tied to ng-change on a variety of input controls in a form, including one that is marked as a number input. The logic of this method is that if any one of the bound scope variables is set properly, to set another scope variable to true. This is basically an attempt at form validation where any one (or more) of the inputs is required.
Example:
app.controller('test', function($scope) {
$scope.num = 0;
$scope.name = "";
$scope.valid = false;
$scope.inputChange = function() {
console.log('Input changed');
$scope.valid = ($scope.num > 0) || ($scope.name.length > 0);
}
});
And form:
<form name="numberTest" ng-app="myApp" ng-controller="test">
<input ng-model="name" name="name" type="text" ng-change="inputChange()"/>
<input type="number" ng-model="num" name="n" id="n" ng-change="inputChange()"/>
<input type="button" value="Go" ng-disabled="!valid"/>
</form>
This all works fine in Chrome, but in Firefox this ng-change handler is fired when non-numeric text is entered in the numeric input and the textbox itself does get this bogus data in it although the model is not updated. This leads to a confusing state where there is invalid data in the num textbox that is not bound to the AngularJS model but the user can click the button. Chrome does not present this problem as it does not render the non-numeric data in the input control.
How can I detect (and handle) this scenario? The input control is displaying text that is invalid and not bound to the binding model.
I am certainly open to alternative implementations to achieve this same effect. AngularJS version is 1.3.0.
Example plunker to run in Firefox to see the "bad" behavior
I ended up discovering the $valid attribute of these number inputs, and that seemingly satisfies my needs:
Returns true if empty
Returns false if non-numeric data is in the control
So, my updated button:
<input type="button" value="Go" ng-disabled="!valid || !numberTest.n.$valid"/>
I'm trying to add some client-side Ajax validation of my Django form. I want to warn users, as they are typing in a field, if any of the characters they just inputted are not ascii.
I originally put the basic python to check for ascii characters in my form's clean method. I don't want to do that, though, as I don't want to produce an error but rather just give a warning message and let the user continue with the rest of the form.
try:
field_value.decode('ascii')
except UnicodeEncodeError:
#raise forms.ValidationError("Non-ASCII characters may cause issues in registering your data. Consider removing these characters. You may still submit at your own risk.")
# Just want to show a warning so the user can still submit the form if they wish
I want to show a small warning under the field as the user is typing. I've tried using django-dajax, but am not sure. How can I do this?
EDIT:
To clarify, I want to show the warning before the user submits the form. So, as they are filling out the form...
Use
> <input type="text" pattern="^[\x20-\x7F]+$" id ....>
in html
Use JavaScript to validate that form field.
Example (using jQuery):
<form>
<input name="whatever" id="fieldId">
...
</form>
<script type="text/javascript">
/* Define a function to check the form field value */
function containsAllAscii(str) {
return /^[\000-\177]*$/.test(str); // returns true if all are ASCII characters. false otherwise.
}
/* Now a little jQuery */
$('#fieldId').on('change', function() {
str = $(this).val();
is_valid = containsAllAscii(str);
if (!is_valid) {
window.alert("There are Non-ASCII characters in the input field");
}
});
</script>
The above code will check the given field's value whenever it changes (i.e. loses focus). You can use .on('keyup', ... instead of .on('change', ... which will check the field's value as the user is typing.
Finally, the error message that is shown is just a browser alert. Which is crappy. You can display a beautiful error message, you just need to learn a little more of jQuery. But I hope I've given you a good starting point.
Credits:
The code for containsAllAscii function is taken from this answer by Juan Mendes.
In your django form, create a custom field and take advantage of the media class.
from django import forms
class MyWidget(forms.TextInput):
class Media:
css = {
'all': ('pretty.css',)
}
js = ('animations.js', 'actions.js')
and set the js to the javascript file you will use for validation. something along the lines of the the other answer
https://docs.djangoproject.com/en/1.9/topics/forms/media/
Angular validation currently works by updating on model change. Although displaying these validation errors upon keyup is not very UI friendly.
An ideal solution would be to display the error messages on blur, along with on form submit. Once an input is blurred on the first time and an error message is displayed, the input would then need to be updated on keyup/model change.
I have seen the following which allows the model to be updated upon blur, but this is not an ideal solution since the model is only updated on blur for every situation.
<input type="text" name="user" ng-model="user" ng-model-options="{ updateOn: 'blur' }" required>
I also came across the following solution that works well on blur and then changes to keyup after an error exists. Although the validation does not apply on form submit.
http://plnkr.co/edit/VSPOYO16ozq2bKaLl3n9?p=preview
Here for this you can have one angular scope variable which maintain the state of form submit is submitted or not by default that variable is false.
$scope.submitted = false;
and one scope function which validate the fields on form submit. Keep in mind place name attribute of form element is must be stetted and refereed same in function. Function approach is to make it generic. You can directly write into html template also by accessing $dirty and $error variable of that input elements.
$scope.validateInput = function (name, type) {
var input = $scope.demoform[name];
return (input.$dirty || $scope.submitted) && input.$error[type];
};
This is function which will be called on form submission.
$scope.submitForm = function () {
$scope.submitted = true;
if ($scope.demoform.$valid) {
console.log('Submitted!!');
} else {
console.log('Not valid!!');
return false;
}
};
Now on html template you can write this way .
<form name="demoform" ng-submit="submitForm()" novalidate="">
<input type="text" name="name" required="" ng-model="name"/>
<span ng-show="validateInput('name', 'required')" class="text-danger">Name is required</span>
<button type="submit" class="btn btn-info" >Save</button>
</form>
Now on form submit You can see the validation message is there if field is not valid.
Demo Plunkr of form validation on form submit in angular
Create a directive that is bound to the blur event, you seem to have found one that will work but I can't read the Plunkr on my phone, and use this to set validity.
Now inside your submit function in the controller you need to check the form for errors.
if (Object.keys($scope.formName.$error).length > 0) {
return false;
}
is an easy way to do this and will also still have the form set to $submitted.
I have a form with an input such as
<td class="units_depth_form">
<input id="id_form-0-rain" name="form-0-rain" step="0.01" type="number" />
</td>
and I want to allow a user to enter units. For instance the form could expect values in inches, but I would allow a user to enter '20 cm', and when leaving the text box it would contain '7.87'.
To do this I have in the JavaScript part of the page the following jQuery code:
$(".units_temp_form input").focusout(function() {
// Convert and replace if valid double ending with 'cm'
and I added 'novalidate' at the end of the form tag. The problem is that $(this).val() is empty when the input is invalid. Is there another way to get to the user entered value?
Before anyone suggests the solution, removing the type='number' part would solve the problem but I'd prefer not to do this. This form is created in Django through a ModelForm, and it would involve a lot of hacking that would defeat the purpose of using Django in the first place.
That seems to be the way browsers behave when they find invalid data inside a type="number" input.
Perhaps your best option is to use <input type="text"/> and implement the up and down arrows yourself. There are several options around, I found one that looks nice and another that keeps going on mouse down.
If the form inputs must be created with type="number" because of Django, you can change that on the client as soon as the page loads:
$(document).ready(function() {
$(".units_temp_form input").each(function(){
if ($(this).attr('type') == "number") {
$(this).attr('type', 'text');
}
});
});
I am working with JSP and I have a HTML form in which I have a button at the top which is Process button. Now if I click on that Process button, it shows me a form which has two radio button - TestClient and TestServer.
It also has Submit button in that form.
Here is my JSFiddle.
Now what I am trying to do is - As soon as I click on TestClient radio button, I need to type in firstName textbox and lastName textbox before pressing Submit button. Meaning these two textbox are mandatory for TestClient radio button and if somebody has typed in third textbox for TestClient radio button, then it should show error message next to that textbox. But If I am clicking TestServer radio button, all the three textbox are mandatory, meaning I need to type in something in all the three textbox.
May be, I can use disable Submit button feature as well if certain conditions are not met along with the proper message next to the textbox?
I am new to jQuery so still learning.
I think the best thing to do here to avoid confusing your users would be to hide() the unnecessary field like this. When the TestClient button is selected, the address field is hidden, but when the TestServer button is selected, it is shown. This avoids confusion with which boxes to fill in: people tend to dislike error messages, even if they are phrased kindly.
try out this fiddle
for figuring out if the form is submittable, you can use a submittable method to detect whether required inputs have a value:
// update submit button
function submittable() {
// get all required fields (needs to happen each time)
var $required = $('input[required=required]', '#form_process'),
$submittable = true;
$required.each(function() {
if ($(this).val()) {
// nothing
} else {
$submittable = false;
}
});
return $submittable;
}
in order for this to work properly, you need to make sure that your universally required inputs have a required attribute and your optionally required address input does not
<input name="fname" id="fname" placeholder="firstName" required="required">
<input name="lname" id="lname" placeholder="lastName" required="required">
<input name="address" id="address" placeholder="address">
then the validate method which will use the submittable method to validate the form and disable/enable the button
var $submit = $('#submit');
// validate control
function validate() {
if (submittable()) {
// you are valid
//alert('valid');
$submit.attr('disabled',false);
} else {
// you are not valid
//alert('invalid');
$submit.attr('disabled',true);
}
}
then you initially run the validate method
// run initial validation
validate();
and then run it on keyup of all the form inputs
// run validation on input keyup
$('#form_process input').keyup(function() {
validate();
});
you also need a method to get the currently checked radio that will show/hide the extra input. you also need to make that address input required when you need it so that you can include it in the validate method:
var $address = $('#address'),
$server = $('#server');
function getChecked() {
// find currently checked input
var $checked = $('input[name=client]:checked', '#form_process');
// if it is server
if ($checked.attr('id') === 'server') {
//alert('server!');
$address.show();
$address.attr('required',true);
} else {
//alert('client!');
$address.hide();
$address.attr('required',false);
}
}
in order for this to work properly, you should set one of your radios to checked
<input type="radio" name="client" id="client" value="TestClient" checked="checked">TestClient
<input type="radio" name="client" id="server" value="TestServer">TestServer
then you call the getChecked method initially and then whenever a radio value changes (along with the validate method):
// call initial get checked
getChecked();
// for each radio
$('input[type=radio]').each(function() {
// when it changes
$(this).change(function() {
// get checked radio
getChecked();
// run validation
validate();
});
});
edit
I should note that this solution is very specific to this issue. if you were to have more than 2 radios with varying input combinations, the getChecked() function would probably need to be a bit more sophisticated.
additionally, $('input[type=radio]').each() would need to be more specific if you have multiple radio groups. in which case you should probably add a class to each radio $('input.specific-radios').each() or wrap them in a parent $('.specific-radios-group input[type=radio]').each()