AngularJS - How to trigger submit in a nested form - forms

I'm building a form that generates an invitation when submitted. The invitation has several fields, one of which is an email address input with an 'add' button, which when clicked should add that address to a list of email addresses that should receive the invite.
This can be done with a single form, however if the user hits the enter key while typing an email then it triggers submit on the whole form. I'd like to have the enter key result - when the email input field is focused - have the same effect as clicking the 'add' button. I expected that the proper way to solve this would be to nest an email entry form within the invitation form, something like this:
<ng-form ng-submit="sendInvite()">
<input type="text" placeholder="Title" ng-model="invitation.title"/>
<ng-form ng-submit="addInvitee()">
<input type="email" placeholder="Title" ng-model="inviteeEmail"/>
<button class="btn" type="submit">add</button>
</ng-form>
<button class="btn" type="submit">Send</button>
</ng-form>
With the following javascript in the controller:
$scope.addInvitee = function() {
$scope.invitation.emails.push($scope.inviteeEmail);
$scope.inviteeEmail = '';
}
$scope.sendInvite = function() {
//code to send out the invitation
}
My problem is that having nested the forms (and in doing so converted from <form> to <ng-form>, submitting either one no longer works.
Plunker here

I've similar requirement - wizard driven multi-step form. When user clicks 'Next' button, I've to validate the current step form.
We can trigger validation by firing '$validate' event on the scope bound to the form.
isFormValid = function($scope, ngForm) {
$scope.$broadcast('$validate');
if(! ngForm.$invalid) {
return true;
}
}
When ever I want to check if the form values are correct, I'll call isFormValid with the scope & form instance.
Working code: Plunker link
It is also useful to have few additional logic in isFormValid (included in the above Plunker) which makes the form & form fields $dirty as we would be showing/hiding validation messages based on their $dirty state.

You can use one of the following two ways to specify what javascript method should be called when a form is submitted:
* ngSubmit directive on the form element
* ngClick directive on the first button or input field of type submit (input[type=submit])
-- form docs
<ng-form>
<input type="text" placeholder="Title" ng-model="invitation.title"><br>
<ng-form>
<input type="email" placeholder="Title" ng-model="inviteeEmail">
<button class="btn" ng-click="addInvitee()">add</button><br>
</ng-form>
<ul class="unstyled">
<li ng-repeat="invitee in invitation.invitees">
<span>{{invitee.email}}</span>
</li>
</ul>
<button class="btn" ng-click="sendInvite()">Send</button>
</ng-form>
Plunker

When the form is submitted, you can find all nested forms using some thing like below
forms = []
forms.push(form)
nestedForms = _.filter(_.values(form), (input) -> (input instanceof form.constructor) and (input not in forms))
Here, form is the outer form controller which was submitted. You can hook this code on ur onsubmit, and find all nested forms and do whatever you have to.
Note: This is coffeescript

Related

how to get the form name of current input text onchange in angular 2

I have scenario where I am changing the input text, i have multiple forms and one input within each form so i want to get the current form name whose input i am changing. how to do this in angular 2??
Below is my code for child component
<form #form1="NgForm" novalidate>
<input id="phoneNumber" type="text" placeholder="phoneNumber" class="validate"/>
</form>
<form #form2="NgForm" novalidate>
<input id="mobileNumber" type="text" placeholder="mobileNumber" class="validate"/>
</form>
Now suppose i am adding mobile number i want its form name. How to do this angular 2?? This is i want to access in parent component I am accessing the child component form using #ViewChildren and i am able to access the form manually but i want access dynamically with respect to the input i am accessing ..
In Angular you have two choices use dynamic forms or template driven forms,
your choice is dynamic forms using #form1="NgForm"
Angular dynamic-form
In your code you forgot the '[formControlName]' directive on the inputs, when you have those you can access the form from your component code like:
Component:
this.form1.valueChanges.subscribe(data => console.log('Form changes', data));
HTML:
<form #form2="NgForm" novalidate>
<input [formControlName]="mobileNumber" type="text" placeholder="mobileNumber" class="validate"/>
</form>
I am able to get the current form valid invalid in parent form by passing index as input to child form and emitting the same in parent form...

Reset Fields on AMP Form Submission

I want to reset all the form fields on successful AMP form submission as I am allowing user for multiple data entry.
Manually I can do it by managing states of each field through amp-bind but I want to reset fields in one go. Is there any function like form.reset present which I can call on form submit success event?
You can use the clear action to reset all fields in a form:
<form id=myForm>
<input>
</form>
<button on="tap:myForm.clear">Clear inputs</button>
You can use submit-success.
<form id=myForm on=submit-success: myForm.clear>
<input name=name value= />
<button>Submit form</button>
</form>

form input with email keyboard but no validation

I want to build a form (in bootstrap) that has an email or telephone number input field.
In mobile I want that field to open the "email keyboard" and I want it to don't validate if the value is an email.
This form also has some text inputs that I want them to be required.
What is the simple way for this to be achieved?
If I understood your question correctly, you want to validate your form's inputs but DO NOT want to validate teh email input in the same form....
use something like this:
jQuery:
$(document).on('click', ".button", function(){
var name = $(".name").val();
var lastname = $(".lastname").val();
var email = $(".email").val();
if(name == "" || lastname == "" ){
alert('Please fill in all the details')
}else{
///////submit your form here... you can even use AJAX to submit yuour form////
}
});
HTML:
<form action="" method="post">
<input type="text" class="name">
<input type="text" class="lastname">
<input type="email" class="email">
</form>
YOU CAN USE ANY JQUERY LIB.
EDIT:
If you are using html5, the <input type="email" will automatically open the 'keypad email' on your device.
A working FIDDLE:
https://jsfiddle.net/2v7ybe9h/2/
Based on the link you provided in the comments below, this is what it says:
They also provided an example in the same page...
As you can already see, the email input in that page has a 'required' attribute and the pattern attribute.
If you simply remove those attributes, there wont be any "Verification" anymore.
Example here:
https://jsfiddle.net/2v7ybe9h/3/
You can also use the novalidate attribute on your form and simply validate your form using jQuery same as what i have provided you in the first fiddle.
Example:
https://jsfiddle.net/2v7ybe9h/4/
The modern answer (as of 2020) is to use inputmode:
<input type="text" inputmode="email">
<input type="text" inputmode="tel">
See MDN for more

How can I submit a AngularJS model the old-fashioned way?

In my Angular app I'm having a form bound to a model. The form does not have fields for all model properties.
When the user hits the submit button I want to post the form the traditional way, not as AJAX request (I have to deal with an already existing server side script).
That basically works if I add a action to the form. But it obviously only submits the form with its present fields as it is, not the whole model just like it's done when using the $http service.
And additionally it does not create name attributes.
How could I submit the form the old-school way with the full model data? Do I have to create the missing form fields on my own or is there a way to let Angular do that for me?
<script>
angular.module('foobar', []).controller('ContentCtrl', ['$scope', function($scope) {
$scope.content = {
'title': 'Foo',
'subtitle': 'Bar',
'text': 'desc' // this field is missing in the form itself and therefore is not submitted
};
}]);
</script>
<form action="http://postcatcher.in/catchers/521c6510429f840200000169" method="post" ng-controller="ContentCtrl">
<input type="text" name="est" ng-model="content.title" value="asdf">
<input type="text" ng-model="content.subtitle">
<button>submit</button>
see post result
</form>
Here's a plunker: http://plnkr.co/edit/5XYGH9hTe7cpchSFWbTK
Angular doesn't do anything special when you have a form with an action defined. It's pure html form submission with exactly the fields that are defined.
Normally you would use:
<input type="hidden" ng-model="content.desc">
but angular currently (1.2.0rc1) still doesn't support ng-model binding to hidden inputs.
The workaround is this:
<input type="text" name="text" ng-model="content.text" ng-hide="true">

How to change a form's action in Lift

I am building a Lift application, where one of the pages is based on the "File Upload" example from the Lift demo at: http://demo.liftweb.net/file_upload.
If you look at the source code for that page... you see that there is a Lift "snippet" tag, surrounding two "choose" tags:
<lift:snippet type="misc:upload" form="post" multipart="true">
<choose:post>
<p>
File name: <ul:file_name></ul:file_name><br >
MIME Type: <ul:mime_type></ul:mime_type><br >
File length: <ul:length></ul:length><br >
MD5 Hash: <ul:md5></ul:md5><br >
</p>
</choose:post>
<choose:get>
Select a file to upload: <ul:file_upload></ul:file_upload><br >
<input type="submit" value="Upload File">
</choose:get>
</lift:snippet>
The idea is that when a user hits the page for the first time (i.e. a GET request), then Lift will show the form for uploading a file. When the user submits the form (i.e. a POST request to the same page), then Lift instead displays the outcome of the file being processed.
With my application, the new wrinkle is that my "results" POST view needs to also contain a form. I want to provide a text input for the user to enter an email address, and a submit button that when pressed will email information about the processed file:
...
<choose:post>
<p>
File name: <ul:file_name></ul:file_name><br >
MIME Type: <ul:mime_type></ul:mime_type><br >
File length: <ul:length></ul:length><br >
MD5 Hash: <ul:md5></ul:md5><br >
</p>
<!-- BEGIN NEW STUFF -->
Output: <br/>
<textarea rows="30" cols="100"><ul:output></ul:output></textarea>
<br/><br/>
Email the above output to this email address:<br/>
<ul:email/><br/>
<input type="submit" value="Email"/>
<!-- END NEW STUFF -->
</choose:post>
...
However, both the GET and POST versions of this page are wrapped by the same Lift-generated form, which has its "action" set to the same snippet in both cases. How can I change this such that in the POST version, the form's action changes to a different snippet?
In a typical web framework, I would approach something like this with an "onclick" event and two basic lines of JavaScript. However, I haven't even begun to wrap my mind around Lift's... err, interesting notions about writing JavaScript in Scala. Maybe I need to go down that route, or maybe there's a better approach altogether.
First, I will suggest you use Lift's new designer friendly CSS binding instead of the custom XHTML tag.
And one thing you should remember when you're using Lift's snippet, is that it is recursive, you could put an lift snippet inside another snippet's HTML block.
For example, if you wish there is another form after POST, then just put it into the block.
<choose:post>
<p>
File name: <ul:file_name></ul:file_name><br >
MIME Type: <ul:mime_type></ul:mime_type><br >
File length: <ul:length></ul:length><br >
MD5 Hash: <ul:md5></ul:md5><br >
</p>
<!--
The following is same as <lift:snippet type="EMailForm" form="post" multipart="true">
-->
<form action="" method="post" data-lift="EMailForm">
<input type="text" name="email"/>
<input type="submit" />
</form>
</choose:post>
Then deal with the email form action at snippet class EMailForm.
Finally, you may pass the filename / minetype and other information by using hidden form element or SessionVar.
I agree with Brian, use Lift's new designer friendly CSS binding.
Use two separate forms, one for the file upload and one for the submitting the email. Use S.seeOther to redirect the user to the second form when the first has finished processing.
I also prefer the new 'data-lift' HTML attribute.
File upload HTML:
<div data-lift="uploadSnippet?form=post">
<input type="file" id="filename" />
<input type="submit" id="submit" />
</div
File upload snippet:
class uploadSnippet {
def processUpload = {
// do your processing
....
if (success)
S.seeOther("/getemail")
// if processing fails, just allow this method to exit to re-render your
// file upload form
}
def render = {
"#filename" #> SHtml.fileUpload(...) &
"#submit" #> SHtml.submit("Upload", processUpload _ )
}
}
GetEmail HTML:
<div data-lift="getEmailSnippet?form=post">
<input type="text" id="email" />
<input type="submit" id="submit" />
</div
Get Email Snippet:
class getEmailSnippet {
def processSubmit = {
....
}
def render = {
"#email" #> SHtml.text(...) &
"#submit" #> SHtml.submit("Upload", processSubmit _ )
}
There's a bit more on form processing in my blog post on using RequestVar's here:
http://tech.damianhelme.com/understanding-lifts-requestvars
Let me know if you want more detail.
Hope that's useful
Cheers
Damian
If somebody comes up with a more elegant (or "Lift-y") approach within the next few days, then I'll accept their answer. However, I came up with a workaround approach on my own.
I kept the current layout, where the view has a GET block and a POST block both submitting to the same snippet function. The snippet function still has an if-else block, handling each request differently depending on whether it's a GET or POST.
However, now I also have a secondary if-else block inside of the POST's block. This inner if-else looks at the name of the submit button that was clicked. If the submit button was the one for uploading a file, then the snippet handles the uploading and processing of the file. Otherwise, if it was the send email submit button shown after the first POST, then the snippet processes the sending of the email.
Not particularly glamorous, but it works just fine.