I'm running a simple example from the main page of Angular involving a todo list. I want to prevent the user from submitting a todo when the input field is blank. The problem is when I load the page and the first thing I do is I click inside the input field and press enter, then the blank todo is added the Todo list. However, after that the validation works. I know there are other ways of doing this, but I want to know why this bug exists and how to fix it.
My html below
<form ng-submit="addTodo()">
<input ng-model="todoText" placeholder="Add a todo here" type="text" />
<input class="button" type="submit" value="add">
</form>
My js file
$scope.addTodo = function() {
var text = $scope.todoText;
if (text != "") {
$scope.todos.push({text:$scope.todoText, done:false});
$scope.todoText = '';
}
};
$scope.todoText is undefined , so it passes your condition and then is set to empty string '', based on your model's variables
either do if (!$scope.todoText) { or initialize it to empty string $scope.todoText = '';
in controller:
$scope.todoText = '';
$scope.addTodo = function() {
if ($scope.todoText != "") {
$scope.todos.push({text:$scope.todoText, done:false});
$scope.todoText = '';
}
};
Have you tried using the required attribute in the input?
<input type="text"
ng-model="todoText"
required <------------- prevents submission and marks the view as invalid
size="30"
placeholder="add new todo here" />
Have a try at http://jsfiddle.net/hbulhoes/uBXfN/
Related
I am trying to create a simple google search bar in my website. It works fine. However, I am accounting for user error, and for some reason I cannot re-enable my submit button once it is clicked, under the condition that no input is provided. Please see Javascript code below.
const text = document.querySelector("#search");
const msg = document.querySelector(".msg");
document.querySelector(".google-form").addEventListener('submit', onclick)
function onclick(e) {
if (text.value === '' || text.value === null) {
e.preventDefault();
msg.classList.add('error');
msg.innerHTML = 'Please enter a proper search query';
setTimeout(() => msg.remove(), 3000);
document.querySelector("#button").disabled = false; // <-- This method doesn't seem to work.
}
}
<div class="google-form">
<div class="msg"></div>
<form id="my-form" action="https://www.google.com/search">
<input id="search" type="text" name="q" placeholder="Enter Search">
<button id="button" type="submit">Submit</button>
</form>
</div>
As you can see, if no text is input, it will let the user know they will need to enter an actual search query. However, after that point, the submit button just wont work again.
I tried using .querySelector().disabled = false; , as well as .removeAttribute("disabled"), but nothing is working. What exactly am I missing here, to re-activate the submit button once it was clicked with no input?
Your button works just fine. You just remove the complete element and then the msg = document.querySelector(".msg"); doesn't find anything. In addition i would leave the timeout out and let the message there until the user writes something.
You should do it like that:
const text = document.querySelector("#search");
const msg = document.querySelector(".msg");
document.querySelector(".google-form").addEventListener('submit', onclick)
function onclick(e) {
msg.innerHTML= '';
if (text.value === '' || text.value === null) {
e.preventDefault();
msg.classList.add('error');
msg.innerHTML = 'Please enter a proper search query';
document.querySelector("#button").disabled = false; // <-- This method doesn't seem to work.
}
}
<div class="google-form">
<div class="msg"></div>
<form id="my-form" action="https://www.google.com/search">
<input id="search" type="text" name="q" placeholder="Enter Search">
<button id="button" type="submit">Submit</button>
</form>
</div>
When button type is set on submit value, it will send the information to the server anyway. (not if you use preventDefault() method!)
My suggestion is to change button type to button and then write an onclick event for it and check the validation there , if everything was right then call for form submit event!
This is how you can prevent incorrect information from being sent into the server side and avoid the errors that it can cause.
I have added a pattern attribute to my custom input field in the Shopify add to cart form.
The problem is that the pattern validator won't pass unless i refresh the page after it has caught something in the validation.
I have tried to reset the form with .reset and it works, but the custom validation messages won't work in that case.
<input required class="required" id="add-your-name-here" type="text" pattern="^[A-Za-z_]{1,15}" placeholder="{{ section.settings.text-custom-name-placeholder }}" name="properties[Ditt namn]">
var input = document.getElementById('add-your-name-here');
input.oninvalid = function(event) {
if ($(".wgcurrent").hasClass("en")) {
event.target.setCustomValidity("Letters only please");
} else if ($(".wgcurrent").hasClass("sv")) {
event.target.setCustomValidity("Vänligen ange endast bokstäver");
}
}
It works like this, except that the custom validation message won't display.
var input = document.getElementById('add-your-name-here');
input.oninvalid = function(event) {
if ($(".wgcurrent").hasClass("en")) {
document.getElementById("addtocart").reset();
event.target.setCustomValidity("Letters only please");
} else if ($(".wgcurrent").hasClass("sv")) {
document.getElementById("addtocart").reset();
event.target.setCustomValidity("Vänligen ange endast bokstäver");
}
}
I want the validation to work without having to refresh the page as it's not a very nice user experience.
You need to clear the Custom Validation message on input event. To do so use,
setCustomValidity('');
Check working code snippet below.
var input = document.getElementById('add-your-name-here');
input.oninput = function(event){
event.target.setCustomValidity('');
}
input.oninvalid = function(event) {
event.target.setCustomValidity("Letters only please");
}
<form action="#">
<input required class="required" id="add-your-name-here" type="text" pattern="^[A-Za-z_]{1,15}" placeholder="Add text here" name="properties[Ditt namn]">
<button type="submit">Submit</button>
</form>
More details on Constraints Validation at MDN
I want to select either file or entered data. i need to validate that but i failed. it takes must be either file or text data only with button click. please help me to solve this problem thanks in advance. JSFiddle
i need if user entered both file and textarea text it shows error. user must select either file or textarea only. this is my requirement
HTML:
<form name="form" ng-app="app" ng-controller="Ctrl" >
Upload file: <input type="file" id="file" /><br/><br/>
Enter text: <textarea id="textarea" required></textarea>
<br/><br/>
<button type="submit" class="btn btn-primary btn-large" ng-click="submitForm()">Submit</button>
</form>
JS:
var app = angular.module('app', []);
app.controller('Ctrl', function ($scope) {
$scope.submitForm = function(){
alert("hi");
var string1 = document.getElementById('file').value;
var string2 =document.getElementById('textarea').value;
if (string1 == string2) {
return true;
}
else {
return false;
}
}
});
There's no how to get the filename with ng-model for it doesn't work with type=file.
To achieve what you want, you must create a directive, as seen in the link below:
https://uncorkedstudios.com/blog/multipartformdata-file-upload-with-angularjs
After that, you must assign the file-model directive to the input, telling which variable of the $scope will be two-way-binded with the value.
The textarea data could be achieved with ng-model.
JSFiddle
once you click on file input then disable the textarea field and if u don't have any file to upload you can click on text area field and onClick of textarea disable file input
You can't use required on both inputs if it's an either or condition.
I created a codepen that should work for you here:
http://codepen.io/anon/pen/XdYBWp
Here's the code:
HTML
<form name="form" ng-app="app" ng-controller="Ctrl as ctrl">
Upload file:
<input type="file" id="file" ng-model="ctrl.file" />
<br/>
<br/> Enter text:
<textarea id="textarea" ng-model="ctrl.text"></textarea>
<br/>
<br/>
<button class="btn btn-primary btn-large" ng-click="ctrl.submitForm()">Submit</button>
</form>
JavaScript
angular.module('app', []).controller('Ctrl', function() {
var vm = this;
vm.file = ""
vm.text = ""
vm.submitForm = function() {
// angular doesn't update the model for input type="file"
vm.file = document.getElementById('file').value;
var retVal = false ;
if (vm.file && ! vm.text)
{retVal = true}
else if (vm.text && ! vm.file)
{retVal = true}
else if (!vm.text && !vm.file)
{retVal = false}
else if (vm.text && vm.file)
{retVal = false}
if (!retVal) {
alert("Please specify either a file or text, not both!")
} else
alert("ok")
}
});
You probably could combine all the ifs & else ifs into a single expression, but it wouldn't be very readable IMO.
Apply angular validations only after submit and not to show validations, if user removed text from text box after submit.
my requirement is technically,
--> if user entered text it should not show any validation
--> show validations only after if user clicked on submit
&
--> after submit if user touched that text box (or) removed text from text box then validation msgs should not show
can you guys please give me solution,
fast replies are appreciated, If you provide me fiddles then i would be very thankful.
thanks in advance
You can solve the problem by using a flag. Assume you have a form that contains an input. You have to set the flag isSubmitted to true when you clicked the submit button. and make it false when your input changes. Then show your validation message based on that flag:
Here is a hypothetical controller:
function appCtrl($scope) {
$scope.isSubmitted = false;
$scope.submit = function() {
$scope.isSubmitted = true;
//...
}
$scope.inputChanged = function() {
$scope.isSubmitted = false;
}
}
And this can be a part of your view:
<input name="inputName" type="text" ng-model="myModel" ng-change="inputChanged()" required="" />
<span ng-show="form.$error.required && form.$dirty && isSubmitted">name is required</span>
I don't know exactly what you are looking for, but I guess this piece of code could be useful.
It's just a basic form with its controller and some validated field.
Each field is required in this example, but as you can see no validation feedback is given to the user.
The validation pass only if the form is valid and then the submission is registered with a flag ( true/false ).
If the flag is true and the user touch one of the fields, all fields are blank again.
The Controller
(function(){
var Controller = function($scope){
// Parameters
var isFormSubmitted = false;
// Methods
// Shared Methods
$scope.checkFocus = function(){
if(!isFormSubmitted){
return;
}
// Reset all fields
$scope.fields = null;
// Do something
}
$scope.validate = function(){
isFormSubmitted = true;
// Do some validation
};
};
Controller.$inject = [
'$scope'
];
app.controller('MainCtrl', Controller);
})();
The view
<div ng-controller="MainCtrl">
<form name="form" ng-submit="form.$valid && validate()" novalidate>
<input ng-focus="checkFocus()" ng-model="fields.username" type="text" required placeholder="Username">
<input ng-focus="checkFocus()" ng-model="fields.password" type="password" required placeholder="Password">
<input type="submit" value="Submit">
</form>
</div>
I have a reset function in angular to clear all the fields in a form. If I do something like:
reset
$scope.resetForm = function() {
$scope.someForm = {};
}
Everything works fine. But I want to use this function for multiple forms on the site. If I pass the form object in like:
reset
$scope.resetForm = function(form) {
$scope.form = {};
}
Then it won't work. Can someone explain to me why this would be happening?
You have 2 problems:
You're not accessing the passed in variable, still access the someForm of current scope.
When you pass parameter to the function, it's passed by reference. Even when you use form = {}, it does not work because it only changes the reference of the parameter, not the reference of the passed in someForm.
Try:
$scope.resetForm = function(form) {
//Even when you use form = {} it does not work
form.fieldA = null;
form.fieldB = null;
///more fields
}
Or
$scope.resetForm = function(form) {
//Even when you use form = {} it does not work
angular.copy({},form);
}
instead of:
$scope.resetForm = function(form) {
$scope.form = {};
}
In your plunk, I see that you're not separating the view from the model. You should do it for separation of concerns and to avoid problems that might happen when you clear all the fields (including DOM form object's fields).
<form name="form2" ng-controller="SecondController">
<label for="first_field">First Field</label>
<input ng-model="form2Model.first_field" />
<br />
<label for="second_field">Second Field</label>
<input ng-model="form2Model.second_field" />
<br />
Reset the form
</form>
http://plnkr.co/edit/x4JAeXra1bP4cQjIBld0?p=preview
You can also do:
form.fieldA = undefined;
It works great for radio buttons and checkboxes.
you can try this :
Deploy your function inside form button reset , in this way ...
<input type ="button" ng-click="Object.field1 = null; ObjectN.fieldN = null;" value="Reset" />