Cannot access fields on second form angular - javascript

I have a page in my app which contains a muti-step form. To achieve this I have 3 forms in separate tabs. The js then only allows you to continue to the next step when the form your on successfully validates.
The first form is working perfectly and I've used the same structure on the second form too (as below).
<div class="stepped-content" ng-show="steps[steps_index.yourDetails].active">
<form name="yourDetails" class="form-horizontal vs-onsubmit" ng-submit="submitForm('yourDetails')" novalidate>
<div class="form-group" ng-form="organiser_name">
<label class="col-sm-4 control-label">Event organiser</label>
<div class="col-sm-8">
<input class="form-control" type="text" name="organiser_name" ng-model="event.organiser_name" placeholder="You or your company's name." ng-required="true" />
<div ng-messages="yourDetails.organiser_name.$error">
<div ng-message="required">Please tell us who is organising this event.</div>
</div>
</div>
</div>
</form>
</div>
However when I print out {{ yourDetails.organiser_name | json }} it is undefined. {{ yourDetails }} itself is defined though:
{
"$error": {},
"$name": "yourDetails",
"$dirty": false,
"$pristine": true,
"$valid": true,
"$invalid": false,
"$submitted": false
}
I'm struggling to see anything wrong with what I've written, so maybe I'm missing a rule that disallows more than one form in angular?
Thanks

Not more than one form, but the name of the form will be used to put the FormController onto the scope.
If you have two or more forms with the same name property, the last one processed will overwrite the previous ones.

Related

How to validate multiple form with same name in angularJS

Hi I want to get the valid or invalid state of all the forms outside the form tag i.e suppose if any of the form is not valid error message should be shown. myform.$invalid is not working for all forms and is not updating
<div ng-repeat="a in [0,1,2,3,4]">
<form name="myForm">
<input type="text">
</form>
</div>
<div ng-if="myform.$invalid">Fill all fields</div>
It is better to have all the <input> elements on the same form:
<form name="myForm">
<div ng-repeat="a in [0,1,2,3,4]">
<input type="text" name="myInput{{a}}" ng-model="itemArr[$index]" required />
</div>
</form>
<div ng-show="myForm.$invalid">Fill all fields</div>
$scope.itemArr = [];
Also it is important that each <input> element has an ng-model directive.
For more information, see
AngularJS Developer Guide - Forms
As per my understanding angular validation is not working properly with same form name in same page.
Angular will only consider the last form name
Ex:
<form name="myForm">
<input name="myInput" ng-model="myInput" required>
</form>
<form name="myForm">
<input type="email" name="myInpu" ng-model="myInpu">
</form>
<p>The input's valid state is:</p>
<h1>Form 1 : {{myForm.myInput.$valid}}</h1>
<h1>Form 2 : {{myForm.myInpu.$valid}}</h1>
I am having the same concern here, where I am creating multiple instance of form with same format (it's a table for multiple row input). I have been trying adding the $index to the form name but then I am facing issue to access the form_$index inside ng-messages and ng-click
example:
<div ng-repeat="a in [0,1,2,3,4]">
<form name="myForm_{{ ::$index }}">
<input type="text">
</form>
</div>
<div ng-if="myform_{{ ::$index }}.$invalid">Fill all fields</div>
Wondering if anyone else can propose a solution for this use case.

Getting the field of form angular

I have a form with some fields.
I'm validating the fields with css classes:(if the field is invalid and the user touched it, then input's border-color = red.)
select.ng-invalid.ng-touched,
input.ng-invalid.ng-touched,textarea.ng-invalid.ng-touched {
border-color: red;
}
If the user submits the form without filling one or more field, there would be a danger alert.
HTML:
<div ng-show="formInvalid>
error!
</div>
JS:
if ($scope.pniyaForm.$valid) {
$scope.formInvalid = false;
.....
} else {
$scope.formInvalid = true;
}
But, If the user submits the form and has not touched any of the field, the css classes don't influence.(because user didn't touch...)
I want to add the class in the code.
Does anyone have an idea for an elegant way to do this without writing it on each field separately?
A possible solution:
when you are executing your form function, add the following line into it.
$scope.$apply(function () {});
this line will cause the ng $scope.$watch() run and apply changes if they exist.
may work, may not work, read the following link for deeper understanding of the issue.
http://jimhoskins.com/2012/12/17/angularjs-and-apply.html
Using ng-class validation in angularjs
<div class="form-group">
<label>Name</label>
<input type="text" required ng-model="name" name="name" ng-class="{'has-error': myForm.name.$invalid}" />
</div>
<div class="form-group">
<label>Age</label>
<input type="text" required ng-model="age" name="age" ng-class="{'has-error': myForm.age.$invalid}" />
</div>
If the user submits the form and has not touched any of the field, the css classes don't influence
You need to provide an initial defined value to an ngModel and at least provide the required attribute to an input.
Use ngClass to conditionally apply css classes in case some form parts are invalid
<form name="myform">
<div class="form-group" ng-class="{'has-error': myform.myinput.$invalid}">
<input name="myinput" ng-model="myName" class="...." required>
</div>
....
</form>
....
// in controller
$scope.myName = "cats"; // form is valid
$scope.myName = ""; // form is invalid, and the css class 'has-error' will be applied
Then use ngDisables in your submit button to prevent submission in case the form is invalid
<button type="submit" ng-disabled="myform.$invalid">submit</button>

Angular JS - Notify the user if form is successfully submitted using HTML element

I am new to Angular JS and using it as the framework for my client-side JavaScript. I want to notify the user if the form is successfully submitted using HTML element (not an alert which the user requires to click "OK" in order to continue input). I used ngShow to show the element when the form is submitted. Below is the code of the element.
<p ng-model="successMessage" ng-show="isSuccess"></p>
However, it does not suit me because I am refreshing the page after the user submitted form successfully. As you know, this will cause the variables in $scope refreshed.
$route.reload();
To overcome that, I tried to not refreshing the page. Instead, I emptied all the models on my controller. Yet, it does not work well for me because I am using Angular form validation i.e. !frmRegister.address.$pristine and frmRegister.address.$invalid for all my input. Using these, I am displaying error message if the user has touched the input element, but the input content is still not right. Below is the example.
<div class="form-group row" ng-class="{ 'has-danger' : frmRegister.name.$invalid && !frmRegister.name.$pristine }">
<label class="col-2 col-form-label">Employee Name</label>
<div class="col-10">
<input class="form-control" ng-class="{ 'form-control-danger' : frmRegister.name.$invalid && !frmRegister.name.$pristine }" type="text" placeholder="Enter name..." id="txtName" name="name" ng-model="name" ng-maxlength="50" required autofocus>
<p ng-show="frmRegister.name.$invalid && !frmRegister.name.$pristine" class="form-control-feedback">Name is required.</p>
<p ng-show="frmRegister.name.$error.maxlength" class="form-control-feedback">Name is too long.</p>
</div>
</div>
As I was not refreshing the page and only emptying the model, the error messages are raised due to the input has been touched.
How can I achieve to display a success message on submitted form using Angular? Any help would be appreciated.
If the$route.reload is important, you could also tack on ?success=true or similar to your route before the reload:
...
$route.updateParams({success:"true"});
$route.reload();
...
Inject $routeParams into your controller and check accordingly:
function Controller($scope, $routeParams) {
if($routeParams && !!$routeParams.success){
$scope.showSuccessMessage = true;
}
}
<p> tag don't support ng-model, you have to use ng-bind. and if you successfully changed value of isSuccess, I think it will showup with ng-bind.
refer the below example about ng-model and ng-bind.
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<div ng-app ng-init="data='test';iSuccess=true;">
<h3>Shown nothing by ng-model</h3>
<p ng-model="data" ng-show="iSuccess"></p>
<h3>Shown by ng-bind</h3>
<p ng-bind="data" ng-show="iSuccess"></p>
<button ng-click="iSuccess=!iSuccess">Toggle</button>
</div>
Well, without reloading,
you can clear your form through this code during submit.
$scope.yourFormModel = {};
$scope.yourFormName.$setPristine(true);
$scope.yourFormName.$setUntouched(true);
It will clear your form like it is untouched without refreshing the page.
Also, in your success message, use this code instead
<div ng-show="isSuccess">
{{successMessage}}
</div>

Dynamic form validation using angular 2

I am working on angular 2 application and creating the form fields dynamically(using json) in a subsection template. I wanted to disable submit button when the form is invalid.
<h1>Form Validation</h1>
<div >
<form #loginForm="ngForm">
<subsection [question]="fieldsData"></subsection>
<button type="submit" [disabled]="!loginForm.form.valid">Submit</button>
</form>
</div>
Sub section as it follows
<div *ngFor="let data of question">
<label> {{data.displayName}}</label>
<input type="data.dataType" name="data.fieldId" [(ngModel)]="data.fieldValue" required name="data.fieldId" #name="ngModel">
<div *ngIf="name.errors && (name.dirty || name.touched)" class="alert alert-danger">
<div [hidden]="!name.errors.required">
Name is required
</div>
</div>
<br><br>
I have a requirement where submit button should be enabled after all the required fields are filled
Created plunker link Here
Based on your plunkr I think you'd be better served using a reactive form rather than the template driven form approach you have described, as you are defining your form fields in a model anyway (the fieldsData array defined in AppComponent).
The current template approach isn't giving you the validation behaviour you want as the input fields in the sub-component are not participating in the wider form - if you debug loginForm.value you will see that the name fields are not part of the form - meaning that if you submit the form, the form will not contain the data entered in those fields.
An alternative is to make the sub-component participate in the form by implementing ControlValueAccessor as described here but this adds complexity you may not need.
A simpler way would be (1) use reactive forms or (2) don't use a nested subsection component at all.
<form #loginForm="ngForm">
<div *ngFor="let data of fieldsData">
<label> {{data.displayName}}</label>
<input type="data.dataType" [(ngModel)]="data.fieldValue" required [name]="data.fieldId" #name="ngModel">
<div *ngIf="name.errors && (name.dirty || name.touched)" class="alert alert-danger">
<div [hidden]="!name.errors.required">
{{data.displayName}} is required
</div>
</div>
</div>
<button type="submit" [disabled]="!loginForm.form.valid">Submit</button>
Form contains: {{loginForm.value | json }}
</form>
question.component.html
<form #loginForm="ngForm">
<div *ngFor="let data of question">
<label> {{data.displayName}}</label>
<input type="data.dataType" [(ngModel)]="data.fieldValue" required name="data.fieldId" #name="ngModel">
<div *ngIf="name.errors && (name.dirty || name.touched)" class="alert alert-danger">
<div [hidden]="!name.errors.required">
{{data.displayName}} is required
</div>
</div>
<br><br>
</div>
<button type="submit" [disabled]="loginForm.invalid">Submit</button>
</form>
The above disables the submit button you can use the above to activate using *ngIf. You can also use the above as !loginForm.valid.
app.component.html
<h1>Form Validation</h1>
<subsection [question]="fieldsData"></subsection>

creating dynamic forms using ng-repeat

Hello everyone I need to create some dynamic forms so users can configure feeds to their specification.
I have used ng-repeat to do the following:
For each feed a user needs to configure a new tab is created
for each property a feed has a label and input textbox is created.
Markup:
<tabset>
<tab ng-repeat="feed in feeds" heading="{{feed.heading}}">
<form role="form">
<div class="row" ng-repeat="property in feed.properties">
<div class="col-xs-6">
<div class="input-group">
<span class="input-group-addon">
<span>{{property.name}}</span>
</span>
<input type="text" class="form-control" value="{{property.value}}">
</div>
</div>
</div>
</form>
</tab></tabset>
This works just fine with the backing json that I have however I am wondering what the accepted way of capturing the data for this kind of use case, obviously I won't know how many feeds or properties each feed has so I suppose I need to bind this to an array in some way.
The question is how?
use ng-model
<input type="text" class="form-control" ng-model="property.value">
This way the textbox is bound to property.value. angular automatically updates property.value when you change the text in the textbox. You can use it in your JS just like any other variable. That's the beauty of angular.

Categories