I've built a validation component that works great. However, I'd like to extend it by adding success messages when a form is submitted successfully.
In the component I pass in the form, watch for changes, and act on the error:
this.formGroup.valueChanges.pipe(takeUntil(this.ngUnsubscribe)).subscribe(data => {
if (this.formGroup.invalid) {
this.validation = { message: `Check for errors in the form`, valid: false };
} else {
this.validation = { message: '', valid: true };
}
});
However I can't see a direct way to get a submission event into my component so that I can show success in the ui.
Can I use the (ngSubmit) event somehow?
what would you do to get it?
UPDATE:
After significant time invested into this my feature request is here
Wrote about "success handling" on Medium
(2022) we finally have the ng-submitted class (v12.1)
I don't know any submission event directly from the FormGroup class, what I know is that you should listen it from the form template.
<form [formGroup]="formGroup" (ngSubmit)="submit()">
<!-- Your controls here-->
<button>Submit</button>
</form>
In your component code you should listen the submit event creating the submit() method
As of Angular 12.1 an ng-submitted class is added to the form element that has been submitted.
The class is automatically added on submissions, and removed on resets.
Related
Ayo,
I'm a bit struggling with functions in JS.
The idea is that after the user clicks submit button, it checks if all the required fields have been filled out and if yes, it will trigger the loading animation.
The loading animation is supposed to be a status indicator in the meanwhile of sending the form and redirection to the success page.
I tried to use the onsubmit function in the form HTML tag but that does not work. The important thing is that it will happen one if the required fields are filled out.
Thanks
JS
const submit_btn = document.querySelector('.submit-btn')
function loading() {
this.innerHTML = "<div class='loader'></div>"
}
HTML
<form
onsubmit="loading()"
action="https://formsubmit.co/2007080c2cf8bd2ebb68506e7aa98c5f"
method="POST"
enctype="multipart/form-data"
>
I tried to use the onsubmit function in the form HTML tag but that does not work.
In regards to validation:
You can use the Constrained Validation API (see MDN) to check if all fields have been filled. Usually you want to use it after the user has submitted the <form> but before the form is sent to the server.
This is achievable by using it inside an event handler that is called on submitting the form.
In regards to event handling:
To implement the mechanism described above, what you want to do is adding an event listener to the submit event of the form via .addEventListener() instead of the onsubmit attribute. This way you'll receive an event object as argument of the event handler function with which you can prevent the form submission.
Example:
const myForm = document.querySelector('form'); // or '#myform', etc...
// define the event handler function
function onFormSubmission(event) {
const fields = Array.from(event.target.elements);
const allValid = fields.every(field => field.reportValidity());
if (!allValid) {
event.preventDefault(); // stop form submission
return;
}
event.target.innerHTML = '<div class="loading"></div>';
}
// add an event listener that fires on submission
myForm.addEventListener('submit', onFormSubmission);
<form id="myform" action="path/to/backend/script.php" method="POST" enctype="multipart/formdata" novalidate>
<input type="text" name="foo" placeholder="I am required!" required>
<hr>
<button type="submit">Submit form</button>
</form>
EDIT
Sorry, I missed to add the part that displays the loading information/element. Added (although you won't really see it because if all required fields are filled, the form will be submitted which results in a page refresh. You'd need something like XHR or similiar but that's not the scope of the question).
Any idea why the once modifier doesn't work on form submitting in Svelte?
In the following example:
<form action="./" on:submit|preventDefault|once={() => alert('You submitted the form')}>
<button type="submit">Save</button>
</form>
when I submit the form first time - I see the alert, but after that, when I submit - the page refreshes - as a normal form submitting.
(I tried with the button on:click - on:click|preventDefault|once... - but got same result.)
Looks like the 'once' is working, but after running and being removed the default submit behaviour of the form seems to be active again.
Couldn't find any information if disabling this listener is possible any other way than by adding a submit listener with preventDefault.
But this way, when adding a second listener only preventing the default, you can see that 'once' is only executed once -> REPL
<script>
function submitOnce() {
console.log('this logs once')
// put logic here you want to execute once
}
function handleSubmit() {
// console.log('this logs with every submit')
// this prevents default submit behaviour
}
</script>
<form on:submit|preventDefault={handleSubmit} on:submit|once={submitOnce}>
<button>Submit</button>
</form>
can simply be replaced by on:submit|preventDefault={() => {}}
I have an input field with a custom validator and ng-messages to show validation messages.
<input type="tel"
ng-model="ctrl.phoneNumber"
phone-number
required />
The custom validator is simple:
ngModel.$validators.phoneNumber = () => {
return $iElem.intlTelInput('isValidNumber');
};
For some other events I'd like to trigger validation by hand, also simple
$iElem.on('countrychange', () => {
ngModel.$validate();
});
Which will trigger my custom validator and also this will validate the number again, the form.*.$error object will be updated too, but ngMessages won't reflect, the validation messages won't update somewhy :/
Any idea?
edit: when I go for the next input in the line ngMessages kicks in for that input AND for the phone-number input as well and the view gets updated, but it's late, like if it would omit one cycle to update the view
Since the countrychange event is not triggered by angular (i.e. outside the digest cycle) you'll need to wrap the validate call inside a $scope.$apply.
iElem.on('countrychange', () => {
$scope.$apply(function(){
ngModel.$validate();
})
});
See this discussion for an explanation
Is there a way to disable/submit the form submit button if the form has validation errors in such a way that the user can click it only if the form is valid.
I'm using unobtrusive validation with "remote" attribute validation with ASP.Net MVC 4 and razor.
Thanks and best regards
Depends on where you are doing your validation. If you are doing it server side with jquery you can add e.preventDefault to the check if it is invalid and the button click won't fire until your conditions are met. If you are doing server side validation using attributes then you can check model state like
if (ModelState.IsValid){
}else{
}
and if the model state is valid (the data passes all the checks) run one set of code. If the model state is invalid then just return view to go back to where you started and pass a message with whatever failed for the user. Hopefully this helps.
Update:
just saw the edit on your comment. For an ajax call you will want to use prevent default.
$('.SubmitButton').on('click', function(e){
$.ajax({
//your call
success: function(result){
if(result.false){
e.preventDefault();
alert(result.message);
}
}
});
});
so if the call is successful the submit call will go through. If it is false then jquery will stop the button click and you can then display a message or do something else.
In my application I'm using a plugin that generates the following markup:
<form id="addCommentForm"
action="/foo/add"
method="post"
onsubmit="
jQuery.ajax({type:'POST', data:jQuery(this).serialize(),
url:'/foo/add',
success:function(data,textStatus) {
jQuery('#comments').html(data);
},
});
return false">
<!-- form elements here -->
</form>
When the form is submitted successfully I want to do something else after the success handler defined by the plugin, say alert('hello');.
The reason I'm struggling with this is because I can't just add my code to the end of the success handler above, because this code is not under my control.
I looked for a form event that executes after onsubmit that I could attach my code to, but didn't find anything.
If you can't really change it, you could use .ajaxSuccess() to handle all the external ajax calls and filter the one you need:
$('form').ajaxSuccess(function(evt, request, settings) {
if (settings.url == 'xxx')
alert('test');
});
Not pretty but it might work for you.