I've never worked with Angular or Angular2 before, but now I have to make an update to a site running on my domain that is using Angular2. I need to programatically fill out a textbox and click submit, but after setting the textbox's value using .value = "val", it still treats the textbox as if it is empty.
I've read up on angular and now understand the concept of ng-dirty and ng-pristine, but programatically changing the class to ng-dirty still doesn't work.
It seems like even if I change the classes, it is still not updating the "pristine" status and it still considers the textbox empty.
I've read about "markAsDirty()" and tried using it but I get "markAsDirty is not a function". I just need to figure out how to update the page so that it realizes that the textbox is not empty and lets me submit the form.
Thanks a lot!
Edit:
Page form:
<form id="form_register" novalidate="">
<div class="form-steps">
<div class="form-group">
<div class="input-group">
<input autocomplete="off" class="form-control ng-pristine ng-invalid ng-touched" data-is-regex="true" data-mask="[a-zA-Z0-1\.]+" id="username" name="username" ngcontrol="username" placeholder="Username" required="" style="color: black !important;" tabindex="13" type="text">
</div>
</div>
<div class="form-group">
<div class="input-group">
<input autocomplete="off" class="form-control ng-untouched ng-pristine ng-invalid" id="password" name="password" ngcontrol="password" placeholder="Password" required="" style="color: black !important;" tabindex="14" type="password">
</div>
</div>
<div class="form-group">
<button class="btn btn-block btn-lg btn-info" tabindex="4" type="submit">
Log In
</button>
</div>
</div>
</form>
My problem is that this:
document.getElementById("username").value = "testuser";
document.getElementById("password").value = "testpass";
document.getElementsByClassName("btn btn-block btn-lg btn-info")[0].click();
ends up giving me a message saying the username and password are required even though there is a value showing in the textbox. Simply clicking on the textbox, typing a character, then deleting it will allow me to submit the form, but I need to accomplish this without user interaction.
You are filling the forms with native javascript and that is not updating the angular model. In your backing component you need to use ngmodel to connect your elements to the component. Then update the variables in the component and everything will reflect correctly.
Okay, there are a few issues with your code that I can see and I'll walk through getting this to work as expected.
For a Template driven form, create and assign the form group variable (which will make our shiny NgForm which we later attach controls to with ngControl) in the template, and lets bind the submit function while we're at it:
<form #myForm="ngForm" (ngSubmit)="submit(myForm.value)" id="form_register" novalidate="">
Each of our inputs is standalone and not yet tied to the form, to do so we'll want to clear the ng- classes which should be managed by Angular 2 and add our [(ngModel)] binding to a property.
<input autocomplete="off" class="form-control" data-is-regex="true" data-mask="[a-zA-Z0-1\.]+"
id="username" name="username" placeholder="Username" ngControl="username" [(ngModel)]="username"
required style="color: black !important;" tabindex="13" type="text">
We're going to disable our submit if the form is invalid:
<button [disabled]="myForm.invalid" class="btn btn-block btn-lg btn-info" tabindex="4" type="submit">Log In</button>
Our class has the username and password properties that we bind to, and our submit function:
export class App {
password: string;
username: string;
submit(value) {
console.log("submitting: " + JSON.stringify(value));
}
}
Finally, if we really want to mark things dirty programmatically this way we will have to grab our template variable in our code with a ViewChild:
#ViewChild('myForm') formGroup;
password: string;
ngAfterContentInit() {
this.formGroup.control.markAsDirty();
}
To do it per control we either need to access it through our formGroup variable or add individual template variables on the inputs we can grab with [(ngModel)]="username" #username="ngModel", for instance.
here's a plunker you can play with to try and develop your understanding: http://plnkr.co/edit/ukJ1kq2UFBvtoCsxbyba?p=preview
Related
I have a form structured as so.
<form id="email_subscription_form" class="form-inline float-right" method="post" action="/my-endpoint/">
<div class="form-group">
<label for="id_email_address" class="d-none">Email Address</label>
<input type="email" id="id_email_address" class="form-control border-0 rounded-0" name="email_address" value="" placeholder="Email Address">
<input type="hidden" name="mailpiece_slug" value="{{ page.settings.email_newsletter_slug }}" />
<input type="hidden" name="event_slug" value="subscribe" />
</div>
</form>
I also have a script at the bottom of the file. The point of the script will be to verify a recaptcha before submitting the form. Here is my script.
<script>
document.getElementById('email_subscription_form').addEventListener('submit', verifyRecaptcha);
function verifyRecaptcha(e) {
e.preventDefault()
return false
}
</script>
I was thinking, based on some research, that the function returning false would stop the form from submitting. However, the form still submits and hits the endpoint.
I have also tried this:
<form id="email_subscription_form" class="form-inline float-right" method="post" action="/my-endpoint/" onsubmit="return verifyRecaptcha()">
and
<form id="email_subscription_form" class="form-inline float-right" method="post" action="/my-endpoint/" onsbubmit="return false">
but the form still submits.
What can I do to stop the form from submitting until verified? This is a Django project, so the template is a Django template.
I'd made some research and in the form theres a parameter onsubmit="" where you can fit a call to a verifing function as you already have with verifyRecaptcha(e). As far i can see, return false part should stop the form, maybe it's because you are not using the onsubmit="verifyRecaptcha(e)" in the form opening tag. So direct onload script does not work. Your code should look like this:
html:
<form id="email_subscription_form" onsubmit="verifyRecaptcha(e) class="form-inline float-right" method="post" action="/my-endpoint/">
<div class="form-group">
<label for="id_email_address" class="d-none">Email Address</label>
<input type="email" id="id_email_address" class="form-control border-0 rounded-0" name="email_address" value="" placeholder="Email Address">
<input type="hidden" name="mailpiece_slug" value="{{ page.settings.email_newsletter_slug }}" />
<input type="hidden" name="event_slug" value="subscribe" />
</div>
</form>
js:
<script>
function verifyRecaptcha(e) {
e.preventDefault()
return false
}
</script>
I highly recommend that you look into how django can help you with forms: working with forms.
django's built-in form management has all the good stuff, such as validation, already handled and allows you to focus on other things. Also, you can still add your JS as usual.
See the above link to the docs and this following example to get some quick insight:
from django import forms
from django.core.exceptions import ValidationError
class ContactForm(forms.Form):
# Everything as before.
...
def clean_recipients(self):
data = self.cleaned_data['recipients']
if "fred#example.com" not in data:
raise ValidationError("You have forgotten about Fred!")
# Always return a value to use as the new cleaned data, even if
# this method didn't change it.
return data
This would check if the field 'recipients' has the specific email in it. If not, it would raise a ValidationError with the declared text being displayed below the respective field in the form.
I have a form, and the form has multiple inputs that are all bound to different variables. Before submitting the form, I need to do validity checks, pristine checks, etc. For example, I want my submit button to be disabled if every part of the form is pristine, or if something is invalid.
Using Angular 5, I am trying to get access to the .pristine, .valid, and .invalid flags for each input field, but the values are either undefined or "cannot get .pristine of undefined".
I am able to get these flags on the entire form itself, but this doesn't help, because I want to know how to get it for each individual input.
Here is my current code (I've removed a number of my inputs to simplify the example).
<form #editDetailsForm="ngForm" name="editDetailsForm" >
<label for="name"> Name </label>
<input type="text" id="name" name="name" maxlength="40" [(ngModel)]="myName" required />
<label for="description"> Description </label>
<textarea id="description" name="description" maxlength="250" [(ngModel)]="myDescription" required ></textarea>
<button id="submit" type="button"
[disabled]="saveButtonDisabled(editDetailsForm.invalid, editDetailsForm.name.invalid, editDetailsForm.description.invalid)"
(click)="updateDetails()" >
Save
</button>
</form>
If you see, I bind disabled attribute on the Save button to saveButtonDisabled() function, where I want to pass in information about each input's validity. The first argument, editDetailsForm.invalid returns a true or false, but the other values return undefined.
How do I check validity of these individual inputs?
EDIT: I realize I can derive all of this info inside my component because all of the input values are bound. However, it'd be easier just to check a flag or two.
I'm not sure I totally understand what you want to do, but this is how you get access to the form controls .pristine, .invlaid
<input type="text" id="name" name="name" #name="ngModel" maxlength="40" [(ngModel)]="myName" required />
The #name="ngModel" sets a template reference to the FormControl angular creates
Then you should be able to do something like this:
<input type="text" id="name" name="name" #name="ngModel" maxlength="40" [(ngModel)]="myName" required />
<div *ngIf="name.pristine">
Name is Pristine
</div>
Just to clarify, the individual form fields bubble up to the form itself. So if any field has been touched, then the whole form will be pristine == false.
You can access the input controls using the .controls property, like:
<button id="submit" type="button"
[disabled]="editDetailsForm.controls.name?.invalid || editDetailsForm.controls.description?.invalid">
Created a stackblitz. https://stackblitz.com/edit/angular-5ir4k7
Added template reference variable for ngModel and validate using isValid.
I have an angularjs form that pulls default data from scope. With the default data the form is expected to be validated and hence enable the button for submission but the reverse is the case except data is entered on the input field and this enables the button. here is the snippet
<div ng-controller="FormValidationController as frmValidationController" class="ui basic segment">
<form class="ui form" name="frmValidation" novalidate>
<div ng-class = "{'has-error':frmValidation.option1.$invalid && !frmValidation.option1.$pristine}"
class="required field">
<label>Selection</label>
<input ng-model="option" ng-minlength="3" formcontrol
name="option1" placeholder="Option" type="text"
class="ng-dirty ng-valid ng-touched" required>
<div _ngcontent-c5="" ngxerrors="option1">
<div class="input-error-message" ngxerror="validName" hidden="">
selection should be there
</div>
</div>
<p ng-show = "frmValidation.option1.$invalid && !frmValidation.option1.$pristine"
class = "input-error-message">required</p>
</div>
if the model has data, the button should be enabled on launch but this never happens and I want it to happen
<button ng-click="submit(); frmValidationController.submitForm(frmValidation.$valid)"
ng-disabled ="!frmValidation.$dirty || frmValidation.$invalid"
class="ui primary button" tabindex="0" type="submit">
Proceed
</button>
The problem is here:
ng-disabled ="!frmValidation.$dirty || frmValidation.$invalid"
Specifically:
!frmValidation.$dirty
The form is only dirty if an actually user has interacted with it. Because you're loading default data, the form is filled in correctly but the user has NOT touched or "dirtied" it.
Remove that check and it should work as expected I believe.
I'm trying to reset the values of the fields after sending the data. Does anyone have a hint how can I clear the fields using javascript?
<div class="form-group">
<label>Código da Matéria</label>
<input required class="form-control" type="text" name="codigoMateria"/>
</div>
<div class="form-group">
<label>Nome</label>
<input required class="form-control" type="text" name="nome"/>
</div>
</div>
<div class="row text-left">
<div class="col-md-4 col-md-offset-4">
<button type="button" class="btn btn-primary btn-block">Salvar</button>
Like Jaromanda said there is a reset method for form elements.
To use it you will need to already have a correct form. Then you’re talking about sending the data. For this you need a submit button.
After this to reset your content you can bind the submit event with a function which use the reset method for your form.
here is a fiddle: https://jsfiddle.net/r56nvn51/1/
If you use the input element with the submit type attribute it will send the data and the reset the page which resets the inputs.
Aside from doing that you will need to add some script.
And you do not need the type in your button element.
I have a simple form on my website where it ask the user for their email and the city they're located in like this:
I'm using EmailJS (emailjs.com) and MailJet (mailjet.com) services and while EmailJS and MailJet are doing their jobs, I'm ultimately not able to view the actual form data such as the email and city that was enter anywhere on MailJet, EmailJS or emails that are sent to me. I'm new to web development.
Here's my html code:
<form class="form-inline" type="text" onsubmit="emailjs.sendForm('mailjet', 'myTempNameFromEmailJS', this); return true;" method="get">
<div class="form-group">
<input type="email" class="contactUsEmail" placeholder="Enter email">
</div>
<div class="form-group">
<input type="password" class="contactUsEmail" placeholder="City">
</div>
<button type="submit" class="btn btn-primary contactUsButton">Signup</button>
</form>
What in the world am I doing wrong? I've essentially been working on this since yesterday and can't figure out what I'm doing wrong.
According to the emailjs docs at https://www.emailjs.com/docs/api-reference/emailjs-sendform/ the third parameter of the sendForm method should be "form_id", the id of the form used to collect the parameters. Currently you're sending "this", but that's the variable which (in that particular context) holds the JavaScript representation of the whole form element.
I think you should change it to this.id:
emailjs.sendForm('mailjet', 'myTempNameFromEmailJS', this.id);
Im not familiar with mail jet, however, usually to gain the values out of your forms you need to add the name attribute, for example
<input type="email" class="contactUsEmail" placeholder="Enter email" name="contactUsEmail"/>
name="contactUsEmail"/>