I want to set 1 of 3 different classes on a span based on the result of a function. My javascript below seems to be returning the correct value, however my markup is always showing the 'require-matched' class.
How can I write an ng-class directive to accommodate this?
HTML:
<span ng-class="{'require-empty': 0,
'require-matched': 1,
'require-not-matched':2 [form.username.$validators.status]}">
</span>
JS:
ctrl.$validators.status = function (value) {
var expression = /^[-\w]+$/;
if (value != null && value != undefined && value != '' && value != ' ') {
if (expression.test(value))
return 1;
if (!expression.test(value))
return 2;
}
else {
return 0;
}
}
This is incorrect usage of validation in Angular. ctrl.$validators.status should return boolean: true for valid result (required-matched in your terminology) and false otherwise (required-not-match). In case of invalid validation ngModelController will receive boolean flag which you can use in view to style control or show error message.
require-empty that you have should be handled by required validator instead of making status validator do this also.
So what you would probably want to have:
ctrl.$validators.status = function(value) {
if (value) {
var expression = /^[-\w]+$/;
return expression.test(value.trim());
}
return false;
}
or directive can be as concise as
ctrl.$validators.status = function(value) {
return value && /^[-\w]+$/.test(value.trim());
}
Corresponding field in HTML will be (providing that the directive name is status):
<input type="text" name="test" ng-model="testModel" status required>
<div class="error" ng-show="testForm.test.$error.required">The field is required.</div>
<div class="error" ng-show="testForm.test.$error.status">The value should match pattern.</div>
Demo: http://plnkr.co/edit/YALB4Vbi5FzNH5FCfwB5?p=preview
Related
I'm new to regex and facing issue in below problem statement.
Problem statement : What I need is a text box where the content must start with 2 upper case alphabets and follows by 3 digits. This textbox can be empty.
function validateModuleCode()
{
var m = document.getElementById("moduleCode").value;
if (/^[A-Z]{2}[0-9]{3}$/.test(m) == false)
{
document.getElementById("moduleError").innerHTML = "Invalid";
return false;
}
else
{
document.getElementById("moduleError").innerHTML = "";
return true;
}
}
Module Code:
<br/>
<input type = "text" id = "moduleCode" name = "module code" onkeypress = "validateModuleCode()">
<span style = "color:red" id = "moduleError"></span>
<br/><br/>
However, the moduleError keeps popping out and shows invalid even though I have entered a valid value. Here is the error image.
How do I correct this ?
You can use oninput event to get the updated input value. Also, You have to add a check for the empty value. So that it should be valid if there is no value in the text box.
Live Demo :
function validateModuleCode() {
var m = document.getElementById("moduleCode").value;
if (m && (/^[A-Z]{2}[0-9]{3}$/.test(m) === false)) {
document.getElementById("moduleError").innerHTML = "Invalid";
return false;
} else {
document.getElementById("moduleError").innerHTML = "";
return true;
}
}
<input type="text" id="moduleCode" name="module code" oninput="validateModuleCode()">
<span style="color:red" id="moduleError"></span>
Me again.
So I have been working on this basic search functionality where I am comparing the value entered as text with a list of other values and doing an action based on it.
In simpler words. I am making a search where the logic compares the value with other strings and if the comparison is successful then show and hide and vice versa if the condition is false.
Now the other condition i want to implement is that when the text bar(where the user will enter the value) is empty then both the divs should be shown. Below is my code for this:
HTML where I am getting the value from: - Im using the onchange to get the value - oninput is not working :(
<label>Find your location:</label>
<input type="text" class="form-control" id="search_input" placeholder="Type address..."
onChange="myFunction()"/>
And This is my JS code
<script>
function myFunction() {
var inzone = document.getElementById("inzone");
var outzone = document.getElementById("outzone");
if(document.getElementById("search_input").value == null
||document.getElementById("search_input").value == "")
{
outzone.style.display = "";
inzone.style.display = "";
}
else if (document.getElementById("search_input").value === 'something something')
{
outzone.style.display = "none";
inzone.style.display = "";
}
else {
inzone.style.display = "none";
outzone.style.display = "";
}
document.getElementById("search_input").value == null will never be true. The value property of an HTMLInputElement is always a string. It may be "", but not null or undefined (the two things == null checks).
Looking for a simple way to validate all required inputs, in a certain div.
In other words make sure all required inputs within a certain div are not empty.
This following code which was found here, shows a way to check all inputs and make sure they aren't empty (including inputs with only spaces in them) on a given page.
I am trying to do the same thing. Just within a certain div and for all required inputs.
$("input").filter(function () {
return $.trim($(this).val()).length == 0
}).length == 0;
You could do the same thing, but you should change the selector to target just the input's inside a given div and add [required] selector to select just those who have required attribute :
$("div_selector input[required]").filter(function () {
return $.trim($(this).val()).length == 0
}).length == 0;
Hope this helps.
$('button').on('click',function(){
var result = $("#div_selector input[required]").filter(function () {
return $.trim($(this).val()).length == 0
}).length == 0;
console.log(result);
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input name='first' required> Required input out of the div
<div id='div_selector'>
<input name='second' required> Required input
<br>
<input name='Third'>
<br>
<input name='Fourth' required> Required input
</div>
<br>
<button>Check</button>
Here's a simple one-liner using Array.reduce():
$(".your-div input").reduce((allFilled, input) =>
allFilled && $.trim($(input).val()) !== "", true)
This approach will match any input be it input, select, textarea etc
var canSubmit = true;
$.each($('.div-in-question').find(':input'), function(element, index){
canSubmit = canSubmit && ($(element).val() !== '');
});
// at this point canSubmit will be true or false and you can act upon it
I'm writing a fairly complicated search form in Angular.
The form is broken into sections - you can search by ID, url, text string or location. When you search by text string and location at the same time, I need to validate that you submit latitude and longitude together.
In other words, searching by a text string is fine. Searching by lat / lng is fine. Searching by a text string and latitude but omitting longitude is not ok.
Whenever possible, I'm using HTML5 and angular directives for validating individual fields' contents, but I'm trying to validate a particular combination of values by using a scope watcher, looking at the form object, and using $setValidity() if I discover that the current search mode is incompatible with a particular combination of fields.
My current issue is that, once I've used $setValidity() once, that validation state is "stuck". When the user switches out of 'textOrLocation' search mode, I want to let angular go back to its default validation behavior. I don't understand why it's not doing that - I only call $setValidity() on scope change after checking the form's in 'textOrLocation' mode.
Javascript:
$scope.search = {
mode: 'id'
};
$scope.$watch(textOrLocationValid, function() {});
function textOrLocationValid() {
var usingTextOrLocation = $scope.search.mode == 'textOrLocation';
if (usingTextOrLocation) {
var textModel = $scope.form.searchText || {},
textValid = textModel.$valid,
textValue = textModel.$modelValue,
latModel = $scope.form.searchLat || {},
latValid = latModel.$valid,
latValue = latModel.$modelValue,
lngModel = $scope.form.searchLng || {},
lngValid = lngModel.$valid,
lngValue = lngModel.$modelValue,
formValid = (textValid && latValid && lngValid) && // No invalid fields
((latValue && 1 || 0) + (lngValue && 1 || 0) != 1) && // Either both lat and long have values, or neither do
(textValue || latValue); // Either text or location are filled out
if (formValid) {
// Explicitly set form validity to true
$scope.form.$setValidity('textOrLocation', true);
} else {
// Explicitly set form validity to false
$scope.form.$setValidity('textOrLocation', false);
}
}
}
HTML
<form name="form">
<div ng-if="search.mode == 'id'">
<input type="text" name="searchId" required>
</div>
<div ng-if="search.mode == 'textOrLocation'">
<input type="text" name="searchText">
<input type="number" name="searchLat" min="-90" max="90" step="0.000001">
<input type="number" name="searchLng" min="-180" max="180" step="0.000001">
</div>
<button ng-disabled="form.$invalid">Submit</button>
</form>
My understanding is that because the function is being watched, it's actually being evaluated by Angular periodically during each digest. A simple solution might be to set the validity of textOrLocation to true when that particular form is not in focus. This would allow the button state to depend on the validity of the field in the id form.
function textOrLocationValid() {
var usingTextOrLocation = $scope.search.mode == 'textOrLocation';
if (usingTextOrLocation) {
var textModel = $scope.form.searchText || {},
textValid = textModel.$valid,
textValue = textModel.$modelValue,
latModel = $scope.form.searchLat || {},
latValid = latModel.$valid,
latValue = latModel.$modelValue,
lngModel = $scope.form.searchLng || {},
lngValid = lngModel.$valid,
lngValue = lngModel.$modelValue,
formValid = (textValid && latValid && lngValid) && // No invalid fields
((latValue && 1 || 0) + (lngValue && 1 || 0) != 1) && // Either both lat and long have values, or neither do
(textValue || latValue); // Either text or location are filled out
if (formValid) {
// Explicitly set form validity to true
$scope.form.$setValidity('textOrLocation', true);
} else {
// Explicitly set form validity to false
$scope.form.$setValidity('textOrLocation', false);
}
}
else{
// Explicitly set form validity to true because form is not active
$scope.form.$setValidity('textOrLocation', true);
}
}
To create complex tests, you can use a small directive use-form-error, which may also be useful to you in the future.
With this directive, you can write:
<div ng-form="myForm">
<div>
<input type="text" ng-model="searchText" name="searchText">
<input type="number" ng-model="searchLat" name="searchLat" min="-90" max="90" step="0.000001">
<input type="number" ng-model="searchLng" name="searchLng" min="-180" max="180" step="0.000001">
<span use-form-error="textOrLocation" use-error-expression="textOrLocationValid()" use-error-input="myForm"></span>
</div>
{{myForm.$error}}
<br>
<button ng-disabled="myForm.$invalid">Submit</button>
</div>
And JS
angular.module('ExampleApp', ['use']).controller('ExampleController', function($scope) {
$scope.search = {
mode: 'textOrLocation'
};
$scope.textOrLocationValid = function() {
var usingTextOrLocation = $scope.search.mode == 'textOrLocation';
if (usingTextOrLocation) {
var textModel = $scope.myForm.searchText || {},
textValid = textModel.$valid,
textValue = textModel.$modelValue,
latModel = $scope.myForm.searchLat || {},
latValid = latModel.$valid,
latValue = latModel.$modelValue,
lngModel = $scope.myForm.searchLng || {},
lngValid = lngModel.$valid,
lngValue = lngModel.$modelValue,
formValid = (textValid && latValid && lngValid) && // No invalid fields
((latValue && 1 || 0) + (lngValue && 1 || 0) != 1) && // Either both lat and long have values, or neither do
(textValue || latValue); // Either text or location are filled out
return !formValid;
} else {
// Explicitly set form validity to true because form is not active
return false;
}
}
});
Live example on jsfiddle:
I got it working, you can find code in this Plunker
There were several problems (I'm making assumption, you are trying handling your form in controller, not in custom directive):
$scope.form that we are trying to access in controller is not same form that we have in the view. Form gets its own scope. which is not directly accessible in controller. To fix this, we can attach form to $scope.forms - object, that is declared in controller (read more on inheritance patterns here)
we should attach ng-model to inputs, so we can $watch them, since it not possible to watch form directly (read more here)
in addition, we have to watch $scope.search changes.
It's definitely not the most elegant solution to handle custom validation... Will try to come up with custom directive for that.
I'm trying to create a simple HTML form & i want to use javascript to validate the values.
Here's the form tage:
<form action="" onSubmit="return formValidation();" method="Post" name="form">
Here's a part of the HTML form:
<label for="text">my text:</label>
<input type="text" name="text">
<div id="error"></div>
<input type="submit" value="submit">
& here's the formValidation() function:
function formValidation() {
var mytext=document.form.text;
if (textValidation(mytext, 3, 20)) {
}
return false;
}
& here's the textValidation() code:
function textValidation(txt, mn, mx) {
var txtlen = txt.value.length;
if (textlen == 0 || txtlen <=mn || txtlen > mx ) {
document.getElementById('error').innerHTML = '<h6 style="color: red;">text is invalid</h6>';
return false;
}
return true;
}
The problem is when i enter an invalid text, it shows the error but hitting the submit button again has no effect, even if i change the text.
i've used alert() & it worked fine.
what am i doing wrong?
You're setting the error text but you don't clear it so it just sticks around. Also, you have to return true in the if statement on your formValidation function otherwise it will always return false.
You can clear the message like this:
function textValidation(txt, mn, mx) {
var txtlen = txt.value.length;
if (textlen == 0 || txtlen <=mn || txtlen > mx ) {
document.getElementById('error').innerHTML = '<h6 style="color: red;">text is invalid</h6>';
return false;
}
document.getElementById('error').innerHTML = "";
return true;
}
Since formValidation always returns false, it will never allow the form to submit. That's fine for testing your JS, but later you'll want to use something like this:
function formValidation() {
var mytext=document.form.text;
if (textValidation(mytext, 3, 20)) {
return true;
}
return false;
}
You can write the form validate function like this
function formValidation() {
var mytext=document.form.text;
//if the variable boolval is initialized inside double quotes it is string now it is bool variable
var boolval=false;
if (textValidation(mytext, 3, 20)) {
boolval=true;
}
return boolval;
}
if textvalidation is true then it will initialize true to boolval or this function will return boolval false as we initialized before[which is default]
Your function formValidation() is always going to return false, regardless of the result of your conditional statement.
Consider your code, corrected in some ways:
function formValidation() {
var mytext=document.form.text;
if (textValidation(mytext, 3, 20)) {
}
return false;
}
If the function textValidation(mytext, 3, 20) is false, formValidation() returns false. If textValidation(mytext, 3, 20) is true, well... the body of the if statement executes, which is empty, and then formValidation returns false.
Additionally, there are also a number of mismatched parentheses and other syntax related issues in your code. Since Javascript is inherently flexible, you might miss these things in practice. I suggest using JSHint to validate and improve the general quality and design of your Javascript code.