Below is my component.html
<form (ngSubmit)="save(myForm.form)" #myForm="ngForm" novalidate>
<select required id="language" [(ngModel)]="myModel.language" name="language" #language="ngModel">
<option *ngFor="let lang of languages" value={{lang.key}}>
{{lang.value}}
</option>
</select>
<div *ngIf="myForm.submitted && language.invalid" class="ErrorTxt">
<div *ngIf="language.errors.required">Language is required</div>
</div>
<button type="submit" class="btn btn-default ">Save</button>
</form>
It should show message "Language is required" when user click on submit without selecting a value from dropdown , but it does not.
I tried printing value of reference variables like below
{{myForm.submitted}}-{{language.invalid}}-{{language.errors.required}}
and got this output all the time:
false-true-true
After clicking on submit button, {{myForm.submitted}} should be true but it is always set to false. The save method is defined as follows in my component.ts file:
save(form: any) {
if (!form.valid) {
let elements = document.getElementsByClassName("ng-invalid");
if (elements.length > 1) {
(elements[1] as HTMLElement).focus();
}
return;
}
// save code here
}
Can someone please suggest whats wrong with this validation and how to make it work ?
Related
I have a scenario I will try to explain, sorry for my English.
I have created a form to submit some values , within the form user can select an option, but one option of which it is "Others specify..." when it is selected the hidden textarea is displayed and user can fill in some data. For the case that it is selected and user does not fill any data, the form is returned back due to validation failure but the textarea is no longer visible because onchange="selectOption();" is not triggered. Everything works fine but in my case I am trying to make the textarea visible with validation error message when it is returned back. How do I perfom this.
<form method="POST" action="{{route('employer-section-b.store')}}"> #csrf <div class="col-md-12">
<select name="b3" id="sector" class="form-control #error('b3') is-invalid #enderror" onchange="selectOption();">
<option value="" disabled selected>select</option>
<option value="1" #if (old('b3')=="1" ) {{ 'selected' }} #endif>Agriculture, forestry, and fishing </option>
<option value="2" #if (old('b3')=="2" ) {{ 'selected' }} #endif>Mining and quarrying</option>
<option value="14" #if (old('b3')=="3" ) {{ 'selected' }} #endif>Others specify……</option></select>
<div class="col-md-12 mt-2" id="specify" style="display: none">
<div class="form-floating mb-3">
<textarea rows="2" name="b3" class="form-control #error('b3') is-invalid #enderror" placeholder="Type here..">
{{ old('b3') }}</textarea>
</div></div>
</div>
</form>
Script to diplay textarea if others is selected
<script>
function selectOption() {
var sector = document.getElementById("sector").value;
var y = document.querySelector("#specify");
if (sector == 3) {
y.removeAttribute("style")
} else if (sector != 3) {
y.setAttribute("style", "display:none");
}
}
</script>
Why not explicitly showing the textarea when the b3 option with value 3 is selected ? This way, changing the JS code is no longer needed.
Se the example below:
You have a duplicate name in use, b3, so i have changed the second duplicate found on the textarea to b4.
<form method="POST" action="{{ route('employer-section-b.store') }}">
#csrf
<div class="col-md-12">
<select name="b3" id="sector" class="form-control{{ $errors->has('b3') ? ' is-invalid':'' }}" onchange="selectOption()">
<option value="" disabled selected>select</option>
<option value="1"{{ old('b3') == 1 ? ' selected':'' }}>Agriculture, forestry, and fishing </option>
<option value="2"{{ old('b3') == 2 ? ' selected':'' }}>Mining and quarrying</option>
<option value="3"{{ old('b3') == 3 ? ' selected':'' }}>Others specify……</option>
</select>
<div class="col-md-12 mt-2" id="specify"{!! ($hasB4Error = $errors->has('b4') || old('b3') == 3) ? '':' style="display: none"' !!}>
<div class="form-floating mb-3">
<textarea rows="2" name="b4" class="form-control{{ $hasB4Error ? ' is-invalid':'' }}" placeholder="Type here..">{{ old('b3') }}</textarea>
</div>
</div>
</div>
</form>
{!! $errors->has('b4') || old('b3') == 3 ? '':' style="display: none"' !!}
This line of code does the trick, it tells Blade to only place the CSS that hides the textarea only when no errors found on b3 nor b4 elements.
What happens is when you submit the form, the page is reloaded and all the form data is reset.
What you should do is create a submit event listener in javascript, and run
event.preventDefault() to stop the form from reloading the page, and then handle what would happen if the form was submitted when the text area is empty.
document.querySelector('form').addEventListener('submit', (event) => {
// Prevent form from reloading the page
event.preventDefault();
// Get content written inside textarea
let textareaValue = document.querySelector('.form-floating > .form-control').value;
// Check if textarea is empty
if (!textareaValue.trim()) {
// Show a message to the user that an error has occured
console.log('Validation error');
} else {
// Route to "employer-section-b.store"
route('employer-section-b.store');
}
});
Having an odd issue where my javascript doesn't fire off correctly on a drop down item when the field is empty (when it should) and then cancels further items after it from being validated all together. When I pop open the browser console, there error I get is "Uncaught TypeError: Cannot read property 'value' of undefined" and it leads directly to the end of the "if" statement in my code. Unsure where I'm going wrong here, I have several identical lines of JS for number and text input fields that work fine, but this one is causing me grief.
There's quite a bit too it, but here's the HTML for that specific part:
<div id="countryRow" class="col-xl-6 justify-content-xl-center">
<form name="countryForm" onsubmit="return validateCountry()" method="post">
<h5> </h5>
<input type="text" list="Ctry" name="selectCountry" style="width:550px;" value="">
<datalist id="Ctry">
<option value="United States">
<option value="Canada">
</datalist>
<h5>Country</h5>
</form>
</div>
and here is the Javascript:
function validateCountry() {
valid = true;
if (document.countryForm.countryInput.value == "") {
shipMessage.innerHTML = "This field is required";
document.getElementById("countryRow").style.backgroundColor = "#fff7f7"
valid = false;
}
return valid;
}
It's just a small mistake. You have incorrectly named your form input in the Javascript code. And the shipMessage field is not defined in this current example. In the below code I have fixed these small mistakes:
HTML
<div id="countryRow" class="col-xl-6 justify-content-xl-center">
<form name="countryForm" onsubmit="return validateCountry()" method="post">
<h5> </h5>
<input type="text" list="Ctry" name="selectCountry" style="width:550px;" value="">
<datalist id="Ctry">
<option value="United States">
<option value="Canada">
</datalist>
<p id="shipMessage"></p> <!-- Added this shipMessage p element to show the error -->
<h5>Country</h5>
<button type="submit">Submit</button>
</form>
</div>
Javascript:
function validateCountry() {
valid = true;
// since the name of the field is "selectCountry", so I have replaced "countryInput" with "selectCountry"
if (document.countryForm.selectCountry.value == "") {
const shipMessage = document.getElementById("shipMessage"); // defining the shipMessage variable
shipMessage.innerHTML = "This field is required";
document.getElementById("countryRow").style.backgroundColor = "#fff7f7";
valid = false;
}
return valid;
}
I have an HTML form that has its elements displayed in various Bootstrap modals. The first modal has a text box input that and a "Next" button to open the next modal. When the "next" button is pressed. I want to check if the text box is empty, and trigger a validation message. The form does not get submitted until the very end. Everything I've tried has not worked so far.
Javascript/jQuery code
$("#add_assistant_next").click(function () {
var textInput = document.getElementById('add_assistant_user');
var text = textInput.value;
if (text === "") {
textInput.setCustomValidity('Please fill out this field.');
textInput.checkValidity();
var form = $('#form_add_assistant');
form.find(':submit').click();
} else {
textInput.setCustomValidity('');
}
});
HTML
<form name="add_assistant" method="post" id="form_add_assistant">
<div class="modal-body">
<div class="step">
<span class="fas fa-arrow-right choose-arrow mr-1"></span>1. Choose a user to add
</div>
<div class="pl-3 pt-1">
<div>
<input type="text" id="add_assistant_user" name="add_assistant[user]" required="required" placeholder="UCInetID or UCI email address" class="mr-0 form-control" />
<button type="button" id="add_assistant_next" name="add_assistant[next]" data-toggle="modal" data-target="#add-user-modal" class="btn btn-outline-secondary btn">Look up user</button>
</div>
<input type="hidden" name="user_search_route" value="/courseSpace/20900/listAssistantEnrollment">
</div>
</div>
... form continues in other modals
Your JS code is probably fighting with Bootstrap for control of that button. To get around that, and have your validation, you could try modifying your code to have a middle step / temporary button to help with validation first before actually submitting. So something like this:
Javascript/jQuery code
$("#my_temp_button").click(function () {
var textInput = document.getElementById('add_assistant_user');
var text = textInput.value;
// Might also want to handle null and undefined cases?
if (text === "" || text === undefined || text === null) {
// I'm assuming if it's empty, it doesn't pass validation,
// so we just display this warning and wait for the user to fix it:
textInput.setCustomValidity('Please fill out this field.');
} else {
// it's not empty so validate:
if (textInput.checkValidity()) {
// it passed validation, so ok to submit.
// call the real button:
$('#add_assistant_next').click();
// do you need this?
var form = $('#form_add_assistant');
form.find(':submit').click();
} else {
// it failed validation, so display another error?
textInput.setCustomValidity('Try again.');
}
}
});
HTML:
<form name="add_assistant" method="post" id="form_add_assistant">
<div class="modal-body">
<div class="step">
<span class="fas fa-arrow-right choose-arrow mr-1"></span>1. Choose a user to add
</div>
<div class="pl-3 pt-1">
<div>
<input type="text" id="add_assistant_user" name="add_assistant[user]" required="required" placeholder="UCInetID or UCI email address" class="mr-0 form-control" />
<!-- Feel free to change the id name. This is the button the user sees. It's only purpose is to give your function above full control to it and prevent Bootstrap from touching it and jumping to the next modal without having the user fix the validation failure first: -->
<button type="button" id="my_temp_button" class="btn btn-outline-secondary btn">Look up user</button>
<!-- Hide the real button from the user: -->
<div style="display:none">
<button type="button" id="add_assistant_next" name="add_assistant[next]" data-toggle="modal" data-target="#add-user-modal" class="btn btn-outline-secondary btn">Look up user</button>
</div>
</div>
<input type="hidden" name="user_search_route" value="/courseSpace/20900/listAssistantEnrollment">
</div>
</div>
...
Have you tried adding a trap for the submit event itself?
$('#form_add_assistant').submit(function(evt){
//do your validation here
if (validation fails){
return false; // OR, alternatively, `evt.preventDefault()`
}
//form submission will continue if not returned false
});
References:
https://api.jquery.com/submit/
How to conduct manual form validation via jQuery .submit()
I want to ask 2 questions.
I have created dynamic dropdown (class and section) using jquery and
assign the id's like [myclass0, myclass1] [mysection0, mysection1]
etc. Now I want to retrieve the values of both and store in a
variable or array then I will use these variable for sending it to
database. I have done the following code but it's not working and
even it's not showing the ID of dynamic created dropdown.
How to select the values of classes and sections and how to loop them so that valid data will be sent to database?
here is my code
<div class="row">
<div class="col-sm-12" id="dynamic_select">
</div>
</div>
<input type="button" name="" value="Add Class" class="btn btn-primary" id="addclass" style="margin-top: 50px;" onclick="addMore();">
here is my JS:
function addMore(){
var inps = $('#dynamic_select > div:last').data('count')+1 || 0;
$('#dynamic_select').append('<div data-count="'+inps+'"><div class = "col-sm-5"><label>Select Class</label> <select id="childclass'+inps+' " class="form-control"> <option value="9">IX</option><option value="10">X</option><option value="11">FSC I</option><option value="12">FSC II</option></select> </div> <div class = "col-sm-5"><label>Select Section</label> <select id="childsection'+inps+' " class="form-control"> <option value="A">A</option><option value="B">B</option><option value="C">C</option></select></div> <a class=remove>X</a>');
}
Try this (example for #dynamic_select):
$('#dynamic_select select').val();
or
$('#dynamic_select).on('change', function() {
$('#dynamic_select select').val();
});
this works perfectly as I want it to in Firefox, but it does not work in Chrome. Can anyone point me in the right direction please?
<g:javascript>
function selectedStatus()
{
var index = j("#statusId");
if(${statusValue} = ${Status.getAllEnums()})
{
index.selectedIndex = ${statusValue};
}
}
</g:javascript>
I am passing a value for a users status from a controller to a gsp page. I check to see if the value is equal to one of the values in the grails select, and if it is then I set this "current" value as the value appearing in the select box.
Here is my gsp...
<g:formRemote name="custom_status" url="[controller: 'traffic', action: 'status']">
<h4>
<g:select id="statusId" name="MyStatus" from="${Status.getAllEnums()}" value="${statusValue}" noSelection="['':'Please Select...']" onload="selectedStatus()" onchange="document.getElementById('sub_status').value = ''"/>
</h4>
<g:textField name="sub_status" value="${subStatusValue}" />
<g:submitButton name="submit_status" value="Apply Status" />
</g:formRemote>
The select box changes as desired in Firefox but no change occurs in Chrome.
Here is the resulting HTML...
<form onsubmit="jQuery.ajax({type:'POST',data:jQuery(this).serialize(), url:'/portal/traffic/status',success:function(data,textStatus){},error:function(XMLHttpRequest,textStatus,errorThrown){}});return false" method="post" action="/portal/traffic/status" id="custom_status">
<h4>
<select name="status" id="statusId" onload="selectedStatus()" onchange="document.getElementById('sub_status').value = ''" >
<option value="">Please Select...</option>
<option value="available" >available</option>
<option value="away" >away</option>
<option value="dnd" >dnd</option>
<option value="unavailable" >unavailable</option>
</select>
</h4>
<input type="text" name="sub_status" value="In a meeting" id="sub_status" />
<input type="submit" name="submit_status" value="Apply Status" id="submit_status" />
</form>
<br/>
Thanks
It's really strange why value="${statusValue}" doesn't work here. Btw, your Javascript code maybe invalid (i'm not sure what you have as a result JS, but it's very likely), so try following:
<g:javascript>
j(document).ready(function ()
{
j("#statusId").val('${statusValue}'); //I guess `j` is your prefix for jQuery, right?
});
</g:javascript>
and remove onload="selectedStatus()"