unable to create a nested Reactive Form - angular6

The code/demo is at https://stackblitz.com/edit/angular-jx7fdu
I am trying to create a nested Reactive Form. It is a simple signup form. It has Firstname, Lastname, email, Password and VerifyPassword Field. I have also created validators for the fields. The html also assigns Bootstrap's classes depending on whether a field has errors or not.
<input id="firstname" type="text" class="form-control" formControlName="firstName" [ngClass]="validateField(signupForm,'firstName')" >
<app-show-errors [control]="signupForm.controls.firstName"></app-show-errors>
validateField in helper.service.ts assigns Bootstraps is-valid and is-invalid classes for visual representation. app-show-errors component gives texttual representation of the error.
For verify password, I want to check that its value is same as that of password field. To do this, I have clubbed them into a FormGroup and am passing that FormGroup to the validator function.
In signup-component.component.ts
createForm(){
this.signupForm = this.fb.group({
firstName:[null,[Validators.required,this.helper.validateName]], lastName:[null,[Validators.required,Validators.pattern(/[A-Za-z]+/)]],
email:[null,[Validators.required,Validators.pattern(this.EMAIL_PATTERN)]],
/*new group for password and verify password. Each of them should match the password criteria and the group should validate that the values of password and verify password is same*/
passwordGroup:this.fb.group({
password:[null,[Validators.required,Validators.minLength(8),this.helper.validatePassword]], confirmPassword:[null,[Validators.required,Validators.minLength(8),this.helper.validatePassword]]
},{validator:this.helper.confirmPasswordValidator})
});
}
Now my main issue is that I am unable to get the nested form (passwordGroup) working. I am seeing the following error in the console.
ERROR Error: formGroup expects a FormGroup instance. Please pass one in.
Example:
<div [formGroup]="myGroup">
<input formControlName="firstName">
</div>
In your class:
this.myGroup = new FormGroup({
firstName: new FormControl()
});

Change your
<div class="form-group" [formGroup]="passwordGroup">
into
<div class="form-group" formGroupName="passwordGroup">
Nested form groups use formGroupName
You can find more documentation here

Related

Negative validation not working in Angular

I have the following HTML Angular tags, which need to trigger a validation error when there is a negative value entered in any of the groups of textboxes (dynamic array).
<tr *ngFor="let order of configWT.get('wtFormArray').controls; let i =index" formArrayName ="wtFormArray">
<input natinput type ="number" [formControlName]="i" id="wtage" ngModelChange="updateWTage(i)" required>
ngOnInit
ngOnInit():void
{
this.configWT = this.formBuilder.group({
wtFormArray: new FormArray(['',[Validators.min(0)]])
}
Here is the error condition which is working for required validation, but not working for min validation.
Working
<nat-error *ngIf="configWT.get('wtFormArray').at(i).hasError('required'))"
error test
<nat-error>
Not Working
<nat-error *ngIf="configWT.get('wtFormArray').at(i).hasError('min')"
error test
<nat-error>
Here is the DOM
I am feeling like I am comparing min value with an array which may be causing this problem? please help!
I think, you should use minlength for minimum validation, it will be easier, because for new FormArray it's not correct to add validation in such way
<input natinput type ="number"
[formControlName]="i"
id="wtage"
ngModelChange="updateWTage(i)"
required
minlength="4">
<nat-error *ngIf="configWT.get('wtFormArray').at(i).hasError('minlength')">
error test
<nat-error>

How do you add a value to datepicker from an Angular Factory?

i have an Angular Factory that gets a single date from the backend of my spring application, and i wanted to add it to an Input so the calendar input is always set with the date obtained from the backend, without the possibility for the user to change it. How could i achieve this? Should i put it on my controller or directly on the button? This is my code:
Factory(concatenated with other .factory):
.factory('DataInizioGeneraCalendario', function ($resource) {
return $resource('rest/anagrafica/dataInizioGeneraCalendario', {
get: {
method: 'GET'
}
});
Controller Function:
$scope.generaCalendario = function () {
$scope.modificaCalendarioDiv = true;
$scope.successMessage = false;
$("#idModificaCalendarioDiv").hide();
$scope.element = new Calendario();
autoScroll('generaCalendario');
$("#idErrorTemplate").hide();
$('#data').attr('disabled', false);
$("#idGeneraCalendarioDiv").show();
};
Input :
<div class="col-xs-12 col-md-2" >
<label for="dataInizio" class="row col-xs-12 control-label" style="text-align: left">da Data</label>
<input class="datepicker form-control" placeholder="gg/mm/aaaa" required type="text" id="data" ng-disabled="true" />
</div>
Edit : forgot to add, the controller function is called by the button that displays the input for the calendar.
Because your factory's GET request will return the date value asynchronously, it's better to have a $scope.date in your controller that will hold the date value that is returned from the server. Also, depending on the format in which you store dates on the backend, you might need to transform the value that is returned from the backend into the string format, so it would be properly consumed by the <input type="date"> as per Angular docs.
In your code, you need to bind the input element to this value, like this: <input ng-model="date">.
What it will do is bind this input to the data model, so that every time when user edits the input the $scope.date would be updated too.
If you do not want users to be able to edit this date, then you need to:
Keep the input field disabled <input disabled> (no need to use ng-disabled here, because you want to keep it always disabled). And also remove this line: $('#data').attr('disabled', false); in your function.
You the one-way binding, instead of two0way binding, like this: <input disabled ng-value="date">
Here is the working DEMO that shows two inputs: one that is editable and another that is not.

How can I use user and password variables in my json request?

Pic 1: Angular 4
In the first picture I have my user input and I can display in the console variables username and password. In the second picture I am sending username and password with my token. How can I use the username and password from first picture and send those with my header? Please help.
Pic 2: json request
Headers class is constant so when you use it only is possible set headers while you are using new statement. i.e.
new Headers({header:value})
new Headers().append('header', 'value');
However this not work because is a constants
let headers = new Header();
headers.append('header','value')
You only can do thing as
new Headers({header:btoa(userna + ':' + password)});
HTML
<form #myForm="ngForm" (submit)="onSubmit(myForm)">
<input type="text" name="username">
<input type="password" name="password"
<input type="submit" value="Submit">
</form>
COMPONENT
onSubmit(form) {
if(form.valid) {
console.log(form.control.username);
console.log(form.control.password);
}
}
Ok if you are looking for your logins data, le proper way is to emit an event like this :
login-form component:
#output
onLogin : EventEmitter<any> = new EventEmitter();
login(e){
***
this.onLogin.emit({username:username,password:password});
}
app component.html
<login-form (onLogin)="getData($event)"></login-form>
here "$event" represent your object "{username:username,password:password}";
otherwise you can store datas in a variable and run "getData" when you want.
Other suggestions:
Use angular reactive-forms like this :https://angular.io/guide/reactive-forms#add-a-formgroup
maybe run your xhr from angular services.

how to bind component variable to form object instance property

I am not quite sure how to bind a variable from my component class to a property value in my form object. The form needs to display this value and add it to the ngModel so that it can become part of the object instance.
I am struggling with the syntax and keep getting the errorNo value accessor for form control with name: 'per_print'
Error: No value accessor for form control with name: I think I need to use the [(ngModel)]="myObject.property" syntax, but I am not getting this from an input into the form, but from a binded variable on the class.
<div class="form-group">
<label class="label-text" >Per Print</label>
<div class="input-group" style="width:150px;">
<h4 [(ngModel)]="job_entry.per_print" name="per_print"
value='pricePerPrint' class="form-control"
>
{{pricePerPrint | currency:'GBP':true:'1.2-2'}}
</h4>
</div>
</div>
job_entry is my object which properties I am setting through the form. pricePerPrint is a variable on the class. I want to set this variable to one of the form instance properties. How to do this? I thought I could do it through value, as in the value of the <h4> tag, but this error persists.
You could use [hidden] input field with the value you want, so that this value will be added to your form. This means though, that you need to use pricePerPrint as the ngModel. But ngModel for your job_entry is possibly not needed. You could build the form as such, so that the object you get from the form can be assigned directly to job_entry:
onSubmit(obj) {
this.job_entry = obj;
}
Also check the Demo for that.
So your code would look like this:
<form #myForm="ngForm" (ngSubmit)="onSubmit(myForm.value)">
<input [hidden]="isHidden" name="per_print"
[(ngModel)]="pricePerPrint" [value]="pricePerPrint"/>
<h4>Price: {{pricePerPrint}}</h4>
<button type="submit">Submit</button>
</form>
where isHidden is set to true.
Other option I see, if you want to use [(ngModel)]="job_entry.per_print, you need to assign whatever value you have in pricePerPrint to job_entry.per_print.

Spring MVC - how to bind HTML checkbox value in a boolean variable

I am very new to spring mvc world. I am trying to send boolean value to from html form checkbox. When a user check the checkbox then it will send true, false otherwise.
<form class="attendanceBook" role="form" method="post" action="/attendances">
<div class="row">
<div class="form-group">
<div class="col-xs-4">
<label class="control-label">Check Here</label>
</div>
<div class="col-xs-4">
<input type="checkbox" name="i" id="i" value="true" />
</div>
<div class="col-xs-4">
<input type="submit" value="Click"/>
</div>
</div>
</div>
</form>
After some googilng I have found this so post, where it said standard behaviour is the value is only sent if the checkbox is checked. So what I have understand that is if the checkbox checked then the form will submit with the value of checkbox, otherwise it will not submit. When there is unchecked checkbox the initialization value in data class will be effective.
But in my case every time I am submitting the form it submitting true.
here is my rest controller for the bind html form submit.
#RestController
#RequestMapping("attendances")
class AttendanceRestController {
val logger = getLogger(AttendanceRestController::class.java)
#PostMapping
fun patchAttendance(#RequestBody attendanceJson: AttendanceJson): ResponseEntity<*> {
logger.info("attendanceJson {}", attendanceJson)
return responseOK(attendanceJson)
}
}
the data class(I am using kotlin)
data class AttendanceJson (
var i: Boolean = false,
var t: String = ""
)
So what will be the method to bind boolean data from a form submission with checkbox. I am also using Thymeleaf. Thanks in advance.
I'm working in Struts and don't know much about Spring. But I faced a similar situation.
What I did was I binded the checkbox with a boolean property in my From class. So for each checkbox, one boolean variable. And at the time of submitting in front end, I'll call a JS function code is below
function verifyCheckboxes() {
document.getElementById("researchPaper").value = document.getElementById("researchPaper").checked;
document.getElementById("researchPaperSeminarProceed").value = document.getElementById("researchPaperSeminarProceed").checked;
document.getElementById("extraActivities").value = document.getElementById("extraActivities").checked;
document.getElementById("studentAchivements").value = document.getElementById("studentAchivements").checked;
}
Here you can see I'm just assigning the value of checked property of that Checkbox just before submitting. It will be either true or false.
You should remove 'value' attribute from the input. If you want the checkbox checked when loading the page, add 'checked' attribute not 'value'.
Replace the input line with this:
<input type="checkbox" name="i" id="i" checked="checked"/>
This is the reason why you always get 'true' in code behind.
It's a bit of a hack, but if you change the type of the input tag from 'checkbox' to 'text' just before the form is posted, you will receive the value, whether it is checked or unchecked.
If you use jQuery:
$("input:checkbox").each(function(){this.type='text'})