How to access the control directly by its formGroupName - angular2-forms

In This form I have to access the control of formControlName="last" to show errors of it.
<div [formGroup]="form">
<div formGroupName="name">
<input formControlName="first" placeholder="First name">
<input formControlName="last" placeholder="Last name">
<span *ngIf="name['controls'].last.invalid">invalid</span>
</div>
<input formControlName="email" placeholder="Email">
<button type="submit">Submit</button>
</div>
This code has thrown an error 'controls' of undefined(Bold Formatted line).
control could be accessible by form['controls'].name['controls'].last.invalid , but is there any way I could access the control directly by its formGroupName ?
Thanks in Advance

Try this
<div *ngIf="!form.controls.name.controls.last.valid">
Invalid last name !!
</div>

Could you try below snippet
<span *ngIf="form.get('last').invalid">invalid</span>

#sravanponugoti: we cannot use [formGroup] with in angular.
Try this code
<form [formGroup]="form">
<div formGroupName="name">
<input formControlName="first" placeholder="First">
<input formControlName="last" placeholder="Last">
<span *ngIf="form.controls['name'].controls.last.valid">invalid</s‌​pan>
</div>
<input formControlName="email" placeholder="Email">
<button type="submit">Submit</button>
</form>

Related

How to use the scaffolded LoginModel in another view than Login.cshtml?

I created a dropdown menu to log in instead of logging in at Login.cshtml but i can't seem to be able to use the model that contains the email password etc. I am not sure how to explain this but here is what i made so far:
I created the dropdown form and placed it in _LoginPartial.cshtml so it shows on the navbar
<div class="dropdown">
<button class="btn btn-secondary dropdown-toggle" type="button" id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Log-In
</button>
<div class="dropdown-menu" aria-labelledby="dropdownMenuButton" style="width: 300px" >
<!----------->
<div class="col-lg-12">
<div class="text-center">
<h3><b>Log In</b></h3></div>
<form id="ajax-login-form" method="post" role="form" autocomplete="off">
<div class="form-group">
<label for="username">Username</label>
<input type="text" name="username" id="username" tabindex="1" class="form-control" placeholder="Username" value="" autocomplete="off">
</div>
<div class="form-group">
<label for="password">Password</label>
<input type="password" name="password" id="password" tabindex="2" class="form-control" placeholder="Password" autocomplete="off">
</div>
<div class="form-group">
<div class="col-xs-5">
<input type="submit" name="login-submit" id="login-submit" tabindex="4" class="form-control btn btn-danger" value="Log In">
</div>
</div>
<div class="col-xs-5" align="Center">
<input type="checkbox" tabindex="3" name="remember" id="remember">
<label for="remember"> Remember Me</label>
</div>
<div class="form-group">
<div class="row">
<div class="col-lg-12">
<div class="text-center">
<a tabindex="5" class="forgot-password">Forgot Password?</a>
</div>
</div>
</div>
</div>
</form>
</div>
and after this, i thought i can easily just insert #model loginmodel and i can start using that model but i'm met with so many errors. Any advice on how to do this? I am also open to other approaches too

Show message if there is an error in the form in angular 2

I have the following form and I need that after the user clicks Save, an error message shows next to the radio group that is required (but no radio selected). I tried the following but it doesn't show the message at all.
<form #formList="ngForm" (ngSubmit)="Save(formList)">
<div *ngFor="let item of data">
<p>{{item.name}}</p>
<input type="radio" name="{{item.id}}" [value]="1" [(ngModel)]="item.isSelected" required>Foo
<input type="radio" name="{{item.id}}" [value]="2" [(ngModel)]="item.isSelected">Bar
<div *ngIf="formList.controls.item?.id.required">
The radio is required!
</div>
</div>
<button type="submit">Save</button>
</form>
Try this code
<form #formList="ngForm" (ngSubmit)="Save(formList)">
<div *ngFor="let item of data">
<p>{{item.name}}</p>
<input type="radio" name="{{item.id}}" [value]="1" [(ngModel)]="item.isSelected" required>Foo
<input type="radio" name="{{item.id}}" [value]="2" [(ngModel)]="item.isSelected">Bar
<div *ngIf="!formList.form.valid">
The radio is required!
</div>
</div>
<button type="submit">Save</button>
</form>

How to use taghelpers for not rendering server side request in form validation

When I post the following form, it requests server. How can I stop it from posting to server and validate in client side using jquery validation?
Here is my code:
<form asp-controller="Gigs" asp-action="Create" method="post">
<div class="form-group">
<label asp-for="#Model.Venue"></label>
<input asp-for="#Model.Venue" class="form-control" />
<span asp-validation-for="#Model.Venue"></span>
</div>
<div class="form-group">
<label asp-for="#Model.Date"></label>
<input asp-for="#Model.Date" class="form-control" />
<span asp-validation-for="#Model.Date"></span>
</div>
<div class="form-group">
<label asp-for="#Model.Time"></label>
<input asp-for="#Model.Time" class="form-control" />
<span asp-validation-for="#Model.Time"></span>
</div>
<div class="form-group">
<label asp-for="#Model.Genre"></label>
<select asp-for="#Model.Genre" asp-items="#(new SelectList(Model.Genres, "Id", "Name"))" class="form-control"><option>Please Select One</option></select>
<span asp-validation-for="#Model.Genre"></span>
</div>
<button type="submit" class="btn btn-primary">Save</button>
</form>
I tried this but didn't work
<environment names="Development">
<script src="~/lib/jquery-validation/dist/jquery.validate.min.js"></script>
</environment>

Accessing Map values in gsp page Grails using variables as key

I am trying to create multiple divs on the fly using a template which is called for a number of times and each time i create a new div ... which seems to be working fine below is the code. I am passing a map tempMap from the controller to the gsp page which is of the below format
tempMap = [key_1:v1,key_2:v2,key_3:v3] //from the controller
//this is the gsp part
<g:set var="counter" value="${1}" />
<g:while test="${counter <= tempMap.counter}">
<g:render template="travelDetailsToShow" />
<g:set var="counter" value="${counter + 1}" />
</g:while>
I need to set the ids of the elements based on the counter which also is working ... But i am unable to set the values of the fields.
<div class="col-sm-6" id="key_${counter}"> // This sets the id to key_1, key_2 depending on the counter value
<div class="form-group">
<label>Departure Date</label>
<span class="input-icon-right input-group">
<g:set var="temp" value="kep_${counter}" />
**<input type="text" name="key_${counter}" class="form-control" value="${tempMap?.key_${counter}}" readonly></input> // this does not work**
<span class="input-group-addon"><i class="glyphicon glyphicon-calendar"></i></span>
</span>
</div>
</div>
I searched a lot but with no luck ... can anyone tell me where am i going wrong with this .. Any help is appreciated ... Thanks in advance people
The render tag has a model attribute. It works like the model passed from controller to view. You can use it to pass data into the template.
view
<g:each in="${1..tempMap.counter}" var="counter">
<g:set var="key" value="key_${counter}">
<g:render template="travelDetailsToShow" model="${[id: key, value: tempMap[key]]}"/>
</g:each>
template
<div class="col-sm-6" id="${id}">
<div class="form-group">
<label>Departure Date</label>
<span class="input-icon-right input-group">
<input type="text" name="${id}" class="form-control" value="${value}" readonly></input>
<span class="input-group-addon"><i class="glyphicon glyphicon-calendar"></i></span>
</span>
</div>
</div>
Thanks Emmanuel for your answer ... but i think i wasnt clear enough and misled you to think that the "key" would be static ... As your logic would expect the static value "key" ..... The proper structure of the map is below ...
tempMap = [key_1:v1,anotherkey_1:v2,yetanotherkey_1:v3,key_2:v4,anotherkey_2:v5,yetanotherkey_2:v6]
I havent tried out the solution posted by you but got another solution to work.... code for which is below ...
<div class="col-sm-6" id="key_${counter}">
<div class="form-group">
<label>Departure Date</label>
<span class="input-icon-right input-group">
<input type="text" name="key_${counter}" class="form-control" value='${tempMap?."${'key_' + counter}"}' readonly></input>
<span class="input-group-addon"><i class="glyphicon glyphicon-calendar"></i></span>
</span>
</div>
</div>
<div class="col-sm-6" id="anotherkey_${counter}">
<div class="form-group">
<label>Return Date</label>
<span class="input-icon-right input-group">
<input type="text" name="anotherkey_${counter}" class="form-control" value='${tempMap?."${'another_' + counter}"}' readonly></input>
<span class="input-group-addon"><i class="glyphicon glyphicon-calendar"></i></span>
</span>
</div>
</div>
</div>
The problem was that i was not referencing the value in the Map properly... The code that fails is stated below.
<div class="col-sm-6" id="departureDate_${counter}">
<div class="form-group">
<label>Departure Date</label>
<span class="input-icon-right input-group">
**<input type="text" name="departureDate_${counter}" class="form-control" value="${tempMap?.${departureDate_counter}"} readonly></input>** // THIS CODE DOES NOT WORK. This will look for a key ${departureDate_counter} and will through a gsp error that tags have not been closed
<span class="input-group-addon"><i class="glyphicon glyphicon-calendar"></i></span>
</span>
</div>
</div>
Although i have found a solution to my problem it would be nice if we posted more solutions as i feel that not a lot of solutions are present on the net for grails and gsp ...

angularjs ng-required not working on ios

I am trying to use the ng-required in a form.
All I did was add ng-required="true" on my input.
In Chrome, when clicking submit it prevents submission and asks the user to fill the field, as expected. On an iPhone, it doesn't show any error and it executes the submit function.
<form name="addGuest" ng-submit="GLCtrl.addGuest()">
<div class="form-group">
<label for="newGuestFirstName">First Name</label>
<input type="text" id="newGuestFirstName" ng-model="GLCtrl.newGuest.firstName" class="form-control" required="true"/>
</div>
<div class="form-group">
<label for="newGuestLastName">Last Name</label>
<input type="text" id="newGuestLastName" ng-model="GLCtrl.newGuest.lastName" class="form-control" required="true"/>
</div>
<div class="form-group">
<label for="arrivalDate">Arrival Date</label>
<div class="input-group">
<input type="text" id="arrivalDate" class="form-control" datepicker-popup="yyyy-MM-dd" ng-model="GLCtrl.newGuest.arrivalDate" is-open="opened" required="true" close-text="Close"
/>
<span class="input-group-btn">
<button type="button" class="btn btn-default" ng-click="open($event)"><i class="glyphicon glyphicon-calendar"></i></button>
</span>
</div>
</div>
<button type="button" class="btn btn-default" ng-click="GLCtrl.cancelAdd()"><i class="glyphicon glyphicon-remove"></i></button>
<button type="submit" class="btn btn-default"><i class="glyphicon glyphicon-ok"></i></button>
</form>
You need to check if the form is valid before proceeding to your form submission process. In regards to your problem, you are probably relying on HTML5's required attribute which is added when ng-required is true. This might work on chrome but it partially works in IOS.
See the note on this link
Partial support in Safari refers to lack of notice when form with required fields is attempted to be submitted. Partial support in IE10 mobile refers to lack of warning when blocking submission.
Solution:
Add novalidate in your form, don't use the HTML5 required attribute messaging which is only useful for some browsers. Show required error message explicitly.
Sample HTML implementation:
<form name="form" ng-submit="submit(form, user)">
<input type="email" required name="email" ng-model="user.email">
<div ng-show="form.email.$error.required>This field is required</div>
<input type="password" required name="password" ng-model="user.password">
<div ng-show="form.password.$error.required>This field is required</div>
<button type="submit">Login</button>
</form>
Sample Controller implementation:
$scope.submit = function(form, user) {
if(form.$valid) { // guard against any errors
// do you login process here..
}
};
Additionally, you can also use the ng-disabled approach to disable the submit button when when form is invalid.
<button type="submit" ng-disabled="form.$invalid">Login</button>
UPDATE:
This update takes into consideration that you are using twitter bootstrap3. By using the following classes: 'has-error' for form-groups and 'help-block' for showing the error messages. By using the ng-class and ng-show directives in showing the errors with angular form validation indicators mentioned in each angular input directives and the FormController and NgModelController documentation and also the guides shown in the developer's guide.
DEMO
HTML
<form name="form" ng-submit="submit(form, guest)" novalidate>
<div class="form-group" ng-class="{'has-error': form.firstName.$invalid && form.firstName.$dirty}">
<label class="control-label" for="newGuestFirstName">First Name</label>
<input type="text" id="newGuestFirstName" ng-model="guest.firstName" name="firstName" class="form-control" required="" />
<div ng-if="form.firstName.$invalid && form.firstName.$dirty">
<span class="help-block" ng-show="form.firstName.$error.required">This field is required</span>
</div>
</div>
<div class="form-group" ng-class="{'has-error': form.lastName.$invalid && form.lastName.$dirty}">
<label class="control-label" for="newGuestLastName">Last Name</label>
<input type="text" id="newGuestLastName" ng-model="GLCtrl.newGuest.lastName" name="lastName" class="form-control" required="" />
<div ng-if="form.lastName.$invalid && form.lastName.$dirty">
<span class="help-block" ng-show="form.lastName.$error.required">This field is required</span>
</div>
</div>
<div class="form-group" ng-class="{'has-error': form.arrivalDate.$invalid && form.arrivalDate.$dirty}">
<label class="control-label" for="arrivalDate">Arrival Date</label>
<div class="input-group">
<input type="text" id="arrivalDate" class="form-control" datepicker-popup="yyyy-MM-dd" ng-model="arrivalDate" is-open="opened" name="arrivalDate" required close-text="Close" />
<span class="input-group-btn">
<button type="button" class="btn btn-default" ng-click="open($event)">
<i class="glyphicon glyphicon-calendar"></i>
</button>
</span>
</div>
<div ng-if="form.arrivalDate.$invalid && form.arrivalDate.$dirty">
<span class="help-block" ng-show="form.arrivalDate.$error.required">This field is required</span>
</div>
</div>
<button type="button" class="btn btn-default">
<i class="glyphicon glyphicon-remove"></i>
</button>
<button type="submit" class="btn btn-default">
<i class="glyphicon glyphicon-ok"></i>
</button>
</form>
JAVSCRIPT
Controller Logic submit()
var fields = ['firstName', 'lastName', 'arrivalDate'];
$scope.submit = function(form, guest) {
if(form.$valid) {
// form is valid, do you form submission processhere..
} else {
angular.forEach(fields, function(field) {
form[field].$dirty = true;
});
}
};

Resources