register an angular form in a nested json - html

I am trying to convert a html form to a nested json.
These are my classes :
export class Config {
id: string;
name: string;
email: string;
lchart:ComponentLinechart;
}
export class ComponentLinechart {
name_linechart : String;
xAxis_linechart : String;
yAxis_linechart : String;
}
The formcomponent.ts:-
export class FormsComponent implements OnInit {
newConfig: Config = new Config();
constructor(private service : MyserviceService, private configservice:ConfigurationService) {
}
email = new FormControl('', [Validators.required, Validators.email]);
xAxisControl = new FormControl('', Validators.required);
yAxisControl = new FormControl('', Validators.required);
name_linechart = new FormControl('', Validators.required);
name = new FormControl('', Validators.required);
getConfig(): void {
this.configservice.getConfig()
.subscribe(data => this.configs = data );
}
createConfiguration(todoForm: NgForm): void {
this.configservice.createConfig(this.newConfig)
.subscribe(createconfig => {
todoForm.reset();
this.newConfig = new Config();
this.configs.unshift(createconfig)
});
}
The formcomponent.html :-
<form #todoForm="ngForm" (ngSubmit)="createConfiguration(todoForm)" novalidate>
<div class="example-container">
<mat-form-field appearance="fill">
<mat-label>Enter your name</mat-label>
<input matInput [(ngModel)]="newConfig.name" name="name" [formControl]="name" required>
</mat-form-field>
<br>
<mat-form-field appearance="fill">
<mat-label>Enter your email</mat-label>
<input matInput placeholder="pat#example.com" [(ngModel)]="newConfig.email" name="email"
[formControl]="email" required>
<mat-error *ngIf="email.invalid">{{getErrorMessage()}}</mat-error>
</mat-form-field>
<br>
<mat-form-field appearance="fill">
<mat-label>Name-linechart</mat-label>
<input matInput [(ngModel)]="newConfig.name_linechart" name="name_linechart"
[formControl]="name_linechart" required>
</mat-form-field>
<br>
<mat-form-field *ngIf = "sales" >
<mat-label>xAxis-linechart</mat-label>
<mat-select [(ngModel)]="newConfig.xAxis-linechart" name="xAxis-linechart"
[formControl]="xAxisControl" required>
<mat-option *ngFor="let field of fields" [value] = "field">
{{field}}
</mat-option>
</mat-select>
<mat-error *ngIf="xAxisControl.hasError('required')">Please choose a field</mat-error>
</mat-form-field>
<br>
<mat-form-field *ngIf = "sales" >
<mat-label>yAxis-linechart</mat-label>
<mat-select [(ngModel)]="newConfig.yAxis-linechart" name="yAxis-linechart"
[formControl]="yAxisControl" required>
<mat-option *ngFor="let field of fields" [value] = "field">
{{field}}
</mat-option>
</mat-select>
<mat-error *ngIf="yAxisControl.hasError('required')">Please choose a field</mat-error>
</mat-form-field>
Expected result :
{
"name": "adam",
"email": "adam#gmail.com",
"lchart": {
"name_linechart": "books",
"xAxis_linechart": "library",
"yAxis_linechart": "percentage"
}
}
But this is what I get :
{
"name": "adam",
"email": "adam#gmail.com",
"lchart": null
}
I tried to write newConfig.lchart.name_linechart in the formcomponent.html but it gives me the error :
TypeError : cannot read property name_linechart of undefined.

Foufa, NEVER, NEVER, NEVER, NEVER use [(ngModel)] and formControlName (or formControl) in the same tag. One is for template Form, another for ReactiveForms, see the docs
Well. You has an object that has properties, one of them is an object, so, you has a FormGroup with somes FormControls and one FormGroup, (again the docs)
myForm=new FormGroup({
name:new FormControl(),
email:new FormControl(),
lchart:new FormGroup({
name_linechart: new FormControl(),
xAxis_linechart: new FormControl(),
yAxis_linechart: new FormControl(),
})
})
And the .html
<form [formGroup]="myForm">
<!--see, under the formGroup, we using formControlName for the formControl-->
<input formControlName="name">
<input formControlName="email">
<!--when we has a FomgGroup, we use formGrpupName in a div-->
<div formGroupName="lchart">
<!--and formControlName under the div -->
<input formControlName="name_linechart">
<input formControlName="xAxis_linechart">
<input formControlName="yAxis_linechart">
</div>
</form>
<!--we can add, only for check-->
<pre>
{{myForm?.value|json}}
</pre>
Update as always, is util use a function that received an object and create the form
getForm(data:any)
{
data=data || { name:null,
email:null,
lchart:{
name_linechart:null,
xAxis_linechart:null,
yAxis_linechart:0
}
}
return new FormGroup({
name:new FormControl(data.name,Validator.required),
email:new FormControl(data.email,[Validator.required,Validators.emailValidator),
lchart:new FormGroup({
name_linechart: new FormControl(data.lchart.name_linechart),
xAxis_linechart: new FormControl(data.lchart.xAxis_linechart),
yAxis_linechart: new FormControl(data.lchart.yAxis_linechart),
})
}
And use as
myForm=this.getForm(data) //<--if we has an object "data"
//or
myForm=this.getForm(null) //if we want a empty form

I guess your [(ngModel)] binding wrong for name_linechart,xAxis_linechart,yAxis_linechart fields.
It should be
[(ngModel)]="newConfig.lchart.name_linechart"
[(ngModel)]="newConfig.lchart.xAxis_linechart"
[(ngModel)]="newConfig.lchart.yAxis_linechart"
change your constructor to-
constructor(private service : MyserviceService, private configservice:ConfigurationService) {
this.newConfig.lchart=new ComponentLinechart(); //add this line
}

Related

Angular Material mat-stepper not working with 4 child items

I'm trying to create a mat-stepper on a new, empty page in Angular
it does work generally, but disappears when I add the 4th mat-from-field (in step 2)
the whole mat-stepper won't show up anymore after refreshing the page
input fields are all bound to a variable through "[(ngModel)]"
every mat-step has it's own "[stepControl]"
every form has it's own "[formGroup]"
HTML:
<mat-stepper linear labelPosition="bottom" #stepper>
<mat-step [stepControl]="firstFormGroup" [editable]="true">
<form [formGroup]="firstFormGroup" class="groupFields">
<ng-template matStepLabel>Fill out Project Info</ng-template>
<mat-form-field appearance="fill">
<mat-label>Project Name</mat-label>
<input matInput formControlName="firstCtrl" [(ngModel)]="projectName" required>
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>Requirements</mat-label>
<textarea [(ngModel)]="requirements"
matInput
cdkTextareaAutosize
#autosize="cdkTextareaAutosize"
cdkAutosizeMinRows="5"
cdkAutosizeMaxRows="15"></textarea>
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>Employee Email</mat-label>
<input matInput [(ngModel)]="email" required>
</mat-form-field>
<div>
<button mat-button matStepperNext>Next</button>
</div>
</form>
</mat-step>
<mat-step [stepControl]="secondFormGroup" [editable]="true">
<form [formGroup]="secondFormGroup">
<div class="customerFrom">
<div class="groupFields">
<ng-template matStepLabel>Fill out Customer Info</ng-template>
<mat-form-field appearance="fill">
<mat-label>Customer Name</mat-label>
<input matInput formControlName="secondCtrl" [(ngModel)]="company" required>
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>Address</mat-label>
<input [(ngModel)]="customerAddress" matInput>
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>City</mat-label>
<input [(ngModel)]="customerCity" matInput>
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>Customer Type</mat-label>
<input [(ngModel)]="customerType" matInput>
</mat-form-field>
</div>
</div>
<div>
<button mat-button matStepperPrevious>Back</button>
<button mat-button matStepperNext>Next</button>
</div>
</form>
</mat-step>
<mat-step [stepControl]="thirdFormGroup" [editable]="true">
<form [formGroup]="thirdFormGroup">
<div class="customerFrom">
<div class="groupFields">
<ng-template matStepLabel>Add Contacts</ng-template>
<mat-form-field appearance="fill">
<mat-label>Contact Stuff</mat-label>
<input formControlName="thirdCtrl" matInput>
</mat-form-field>
</div>
</div>
<div>
<button mat-button matStepperPrevious>Back</button>
<button mat-button matStepperNext>Next</button>
</div>
</form>
</mat-step>
<mat-step>
<ng-template matStepLabel>Create Project</ng-template>
Create the Project or go back and edit!
<div>
<button mat-button matStepperPrevious>
<mat-icon>edit</mat-icon> back
</button>
<button mat-button (click)="createProject()">
<mat-icon>done</mat-icon> create Project
</button>
</div>
</mat-step>
</mat-stepper>
TS:
export class ProjectCreationComponent implements OnInit {
projectName: string = '';
selectedStatus: string = '';
requirements: string = '';
company: string = '';
customerAddress: string = '';
customerCity: string = '';
customerType: string = '';
forename: string = '';
surname: string = '';
address: string = '';
city: string = '';
email: string = '';
mobile: string = '';
contacts: Contact[] = [];
unsubscribe$: Subject<void> = new Subject<void>();
firstFormGroup = this._formBuilder.group({
firstCtrl: ['', Validators.required],
});
secondFormGroup = this._formBuilder.group({
secondCtrl: ['', Validators.required],
});
thirdFormGroup = this._formBuilder.group({
thirdCtrl: ['', Validators.required],
});
constructor(
private service: ProjectService,
private router: Router,
private _formBuilder: FormBuilder) { }
ngOnInit(): void {
}
addContact() {
let contact = {} as Contact;
contact.forename = this.forename;
contact.surname = this.surname;
contact.address = this.address;
contact.city = this.city;
contact.email = this.email;
contact.mobile = this.mobile;
this.contacts.push(contact);
}
deleteContact(contact: Contact) {
const index: number = this.contacts.indexOf(contact);
if(index !== -1) {
this.contacts.splice(index, 1);
}
}
createProject() {
const customer: Customer = {
name: this.company,
contacts: this.contacts,
address: this.customerAddress,
city: this.customerCity,
customerTyp: this.customerType
}
const announcement: Announcement = {
requirements: this.requirements,
customers: [customer],
offers: [],
}
const project: ProjectCreationRequest = {
name: this.projectName,
employeeEmail: this.email,
announcements: [announcement],
offers: []
};
this.service.createProject(project)
.pipe(takeUntil(this.unsubscribe$))
.subscribe();
this.router.navigateByUrl('/');
}
ngOnDestroy() {
this.unsubscribe$.next();
this.unsubscribe$.complete();
}
}
I've also exactly tried removing a mat-form-field (so that I only have 3 in the form), for every single one of them, so there is not a specific one that's causing the problem.
One more thing I've tried is changing "[(ngModel)]" to "[value]", because 2 way binding isn't necessarily needed, but with that the value of the textfield can't be stored in the variable.
Also I didn't find anything in the material documentation about a maximum size of step child items or anything.
Stackblitz (not 1:1 because of too many classes): https://stackblitz.com/edit/angular-buspzu?file=src/app/app.component.ts

How to read JSON file in Angular cli?

I have an Angular cli project where I want to read data from a JSON file. These datas should be displayed on form's fields when the form is opened by user. What I have tried so far:
EmailSettingsComponent.ts
import { Component, OnInit, ViewChild, ViewEncapsulation, ChangeDetectorRef, Inject } from '#angular/core';
import * as FileSaver from 'file-saver';
import { MatDialog, MAT_DIALOG_DATA } from '#angular/material';
#Component({
selector: 'app-email-settings',
templateUrl: './email-settings.component.html',
styleUrls: ['./email-settings.component.css']
})
export class EmailSettingsComponent implements OnInit {
constructor() { }
smtpSettings: any;
saveJSON() {
var saveData = (function () {
var a = document.createElement("a");
document.body.appendChild(a);
// a.style = "display: none";
return function (data, fileName) {
//saving JSON code
};
}());
let smtpHost = (document.getElementById("smtpHost") as HTMLInputElement).value;
let smtpPort = (document.getElementById("smtpPort") as HTMLInputElement).value;
let smtpUserName = (document.getElementById("smtpUserName") as HTMLInputElement).value;
let smtpPassword = (document.getElementById("smtpPassword") as HTMLInputElement).value;
let smtpFrommtpHost = (document.getElementById("smtpFrom") as HTMLInputElement).value;
let smtpDisplayName = (document.getElementById("smtpDisplayName") as HTMLInputElement).value;
let smtpRecipients = (document.getElementById("smtpRecipients") as HTMLInputElement).value;
var data = { "Host": smtpHost, "Port": smtpPort, "UserName": smtpUserName, "UserPassword": smtpPassword, "From": smtpFrommtpHost, "DisplayName": smtpDisplayName, "Recipients":smtpRecipients, d: new Date() },
fileName = "my-download.json";
saveData(data, fileName);
}
ngOnInit(): void {
fetch('./assets/my-download.json').then(res => res.json())
.then(json => {
this.smtpSettings = json;
});
}
}
EmailSettingsComponent.html
<h1 mat-dialog-title>Email Settings</h1>
<div mat-dialog-content style="width: auto; height: auto">
<form id="formID" class="example-form" *ngFor="let item of smtpSettings">
<mat-form-field class="example-full-width" appearance="fill">
<mat-label>SMTP Host</mat-label>
<textarea id="smtpHost" matInput placeholder="Ex: smtp.gmail.com">{{item.Host}}</textarea>
</mat-form-field>
<br />
<mat-form-field class="example-full-width" appearance="fill">
<mat-label>SMTP Port</mat-label>
<textarea id="smtpPort" matInput placeholder="Ex: 587"></textarea>
</mat-form-field>
<br />
<mat-form-field class="example-full-width" appearance="fill">
<mat-label>SMTP User Name</mat-label>
<textarea id="smtpUserName" matInput placeholder="Ex: example#gmail.com"></textarea>
</mat-form-field>
<br>
<mat-form-field class="example-full-width" appearance="fill">
<mat-label>SMTP User Password</mat-label>
<textarea id="smtpPassword" matInput placeholder="Ex: password"></textarea>
</mat-form-field>
<br>
<mat-form-field class="example-full-width" appearance="fill">
<mat-label>SMTP From</mat-label>
<textarea id="smtpFrom" matInput placeholder="Ex: example#gmail.com"></textarea>
</mat-form-field>
<br>
<mat-form-field class="example-full-width" appearance="fill">
<mat-label>SMTP Display Name</mat-label>
<textarea id="smtpDisplayName" matInput placeholder="Ex: Jhon"></textarea>
</mat-form-field>
<br>
<mat-form-field class="example-full-width" appearance="fill">
<mat-label>Recipients</mat-label>
<textarea id="smtpRecipients" matInput placeholder="Ex: someone#email.com; somebody#test.com"></textarea>
</mat-form-field>
<br>
<button mat-button (click)="saveJSON()">Save</button>
</form>
</div>
With the above code, I'm getting Error: Cannot find a differ supporting object '[object Object]' of type 'object'. NgFor only supports binding to Iterables such as Arrays..
Based on kva's reply on accepted answer of this post, I have replaced smtpSettings: any; with smtpSettings: any=[];. Following this action, I get rid of the above error, but I get another one which is Error trying to diff '[object Object]'. Only arrays and iterables are allowed.
How could I read the data from JSON and populate the form with it when the form is opened?

ERROR TypeError: can't assign to property "validator" on "12345": not an object

I want to build a pre filled form, as of now I am getting this error when i try to display the form page. I have tried various solutions that was given but that doesn't seem to work here.
My hardwareRequest.ts
hardwareReviewForm: FormGroup;
assetSerialNumber = new FormControl('');
modelType = new FormControl('');
ngOnInit(): void {
this.data = []
this.service.loadRequestData(this.requestId).subscribe(
(response: any) => {
this.data = response
console.log(this.data)
this.assetSerialNumber = this.data.assetSerialNumber
this.modelType = this.data.modelType
},
(error) => {
}
)
}
My HTML file
<form class="example-container" [formGroup]="hardwareReviewForm" (ngSubmit)="onFormSubmit()">
<div class="ds-col-12" style="margin-bottom: 10px;">
<div class="ds-col-6">
<mat-form-field appearance="outline">
<mat-label>Asset Serial Number: </mat-label>
<input formControlName="assetSerialNumber" readonly matInput type="text">
</mat-form-field>
</div>
<div class="ds-col-6">
<mat-form-field appearance="outline">
<mat-label>Part No./Model Type: </mat-label>
<input formControlName="modelType" readonly matInput type="text">
</mat-form-field>
</div>
</div>
</form>
You can make a 'View Model' of your fields and then reset your form with it.
export class testVm {
assetSerialNumber : number;
modelType : string;
}
var model: testVm = this.data;
this.hardwareReviewForm.reset(model)
Or if you want to assign value separately you should act like this:
this.hardwareReviewForm.controls["assetSerialNumber"].reset(this.data.assetSerialNumber.toString())
Firstly, you have to define form controls inside formGroup;
hardwareReviewForm = new FormGroup({
assetSerialNumber = new FormControl('');
modelType = new FormControl('');
});
Secondly, you set the values to controls like below;
this.hardwareReviewForm.get('assetSerialNumber').setValue(this.data.assetSerialNumber);
I figured this out.. It was a silly mistake of .setValue for form controls.
setting my value like below works fine.
this.Number.setValue(this.data.Number)
this.Type.setValue(this.data.Type)

Angular filter and binding (ngModelChange)

I'm working on the hotel project. I have a reservation screen. Here I ask the hotel name, region name, check-in and check-out dates, the number of adults and children. When the necessary information is entered, when I press the search button, I filter according to the values ​​there. I connected the date filter with html using the (NgModelChange) method, but I couldn't connect the html with the hotel and region methods correctly. I made a filter as an experiment, but I got the wrong result. I don't know where I'm making a mistake. How can I fix this?
.html
<form [formGroup]="form">
<mat-form-field>
<label>Which Hotel?</label>
<input type="text" matInput [matAutocomplete]="name" formControlName="name" (change)="changeHotel()" />
<mat-autocomplete #name="matAutocomplete">
<mat-option *ngFor="let hotel of filteredHotels | async" [value]="hotel">
{{hotel}}
</mat-option>
</mat-autocomplete>
</mat-form-field>
<mat-form-field>
<label>Which Region?</label>
<input type="text" matInput [matAutocomplete]="region" formControlName="region" (change)="changeRegion()" />
<mat-autocomplete #region="matAutocomplete">
<mat-option *ngFor="let region of filteredRegions | async" [value]="region">
{{region}}
</mat-option>
</mat-autocomplete>
</mat-form-field>
<mat-form-field>
<label>Entry Date?</label>
<input matInput [matDatepicker]="mdpStartDate" formControlName="startDate" (ngModelChange)="changeDate()">
<mat-datepicker-toggle matSuffix [for]="mdpStartDate"></mat-datepicker-toggle>
<mat-datepicker #mdpStartDate></mat-datepicker>
</mat-form-field>
<mat-form-field>
<label>Pay Date?</label>
<input matInput [matDatepicker]="mdpEndDate" formControlName="endDate" (ngModelChange)="changeDate()">
<mat-datepicker-toggle matSuffix [for]="mdpEndDate"></mat-datepicker-toggle>
<mat-datepicker #mdpEndDate></mat-datepicker>
</mat-form-field>
<br />
<mat-form-field>
<label>Adult Number?</label>
<input type="number" min="1" matInput formControlName="adult" (ngModelChange)="filterAge()">
</mat-form-field>
<mat-form-field>
<label>Chd Number?</label>
<input type="number" min="0" max="3" value="0" matInput formControlName="chd" (ngModelChange)="filterAge()">
</mat-form-field>
<button type="button" class="btn btn-success" (click)="search()">Search</button>
.ts
form = new FormGroup({
name: new FormControl(''),
region: new FormControl(''),
adult: new FormControl(1),
chd: new FormControl(0),
startDate: new FormControl(),
endDate: new FormControl(),
});
filtered: any[];
showList = false;
name = '';
regions: string[];
hotels: Hotel[] = [];
filteredHotels: Observable<string[]>;
filteredRegions: Observable<string[]>;
ngOnInit() {
this.regions = this.hotels.reduce((arr: string[], current) => {
if (!arr.includes(current.regionName)) {
arr.push(current.regionName);
}
return arr;
}, []);
this.filteredHotels = this.form.get("name").valueChanges
.pipe(
startWith(''),
map(v => {
return this.filterHotels(v)
})
);
this.filteredRegions = this.form.get("region").valueChanges
.pipe(
startWith(''),
map(value => this.filterRegions(value).map(h => h.regionName))
);
this.form.get("adult").valueChanges.
subscribe(v => {
this.adult = new Array(v).map(e => new Object)
});
this.form.get("chd").valueChanges
.subscribe(v => {
this.children = new Array(v).map(e => new Object)
});
this.hotelservice.getHotels().subscribe(
data => {
this.hotels = data;
this.dsHotels.data = data;
this.dsHotels.paginator = this.paginator;
},
err => {
console.error("Hata oluştu: ", err);
}
);
}
private filterHotels(value: string): string[] {
const name = value.toLowerCase();
return this.hotels
.map(x => x.hotelName)
.filter(option => option.toLowerCase().includes(name));
}
private filterRegions(value: string): Hotel[] {
const region = value.toLowerCase();
return this.hotels
.filter(hotel => hotel.regionName.toLowerCase().includes(region));
}
private isEqual(date1: Date, date2: Date) {
return date1.getDate() == date2.getDate() && date1.getMonth() == date2.getMonth() && date1.getFullYear() == date2.getFullYear();
}
private isDataEqualToDate(value1: any, date2: Date) {
if (value1 == null) return true;
return this.isEqual(new Date(value1), date2);
}
private getFilteredDate(): Hotel[] {
return this.hotels.filter(
x => this.isDataEqualToDate(this.form.get("startDate").value, new Date(x.checkInDate))
&& this.isDataEqualToDate(this.form.get("endDate").value, new Date(x.payDate))
);
}
changeHotel() {
this.dsHotels.data = this.filterHotels("value");
}
changeRegion() {
this.dsHotels.data = this.filterRegions("value");
}
changeDate() {
this.dsHotels.data = this.getFilteredDate();
}
filterAge() {
//this.dsHotels.data = this.hotels.filter(x => x.numberOfAd == this.form.get("adult").value && x.numberOfChd == this.form.get("chd").value);
this.dsHotels.data = this.hotels.filter(x => x.numberOfAd == x.numberOfChd);
}
search() {
this.showList = true;
this.filterHotels("");
this.filterRegions("");
this.changeDate();
}
As you created your form with reactive forms you can switch from event binding in template
< ... (change)="changeHotel()"
< ... (ngModelChange)="changeDate()">
to do it inside class.
ngOnInit() {
// ... initial logic
this.form.get('name').valueChanges.subscribe(this.changeHotel.bind(this))
this.form.get('region').valueChanges.subscribe(this.changeRegion.bind(this))
this.form.get('startDate').valueChanges.subscribe(this.changeDate.bind(this))
this.form.get('endDate').valueChanges.subscribe(this.changeDate.bind(this))
this.form.get('adult').valueChanges.subscribe(this.filterAge.bind(this))
this.form.get('chd').valueChanges.subscribe(this.filterAge.bind(this))
}
Reactive form instances like FormGroup and FormControl have a
valueChanges method that returns an observable that emits the latest
values. You can therefore subscribe to valueChanges to update instance
variables or perform operations.
source

post empty value from autocomplete material typescript

I want to post data from autocomplete material.
My ts code, like this. I used registerUserForm formgroup.
export class AddUserFormComponent implements OnInit {
countryes: Country[];
registerUserForm: FormGroup;
filteredOptionsCountry: Observable<Country[]>;
myControlCountry: FormControl = new FormControl();
constructor(private fb: FormBuilder,
private router: Router,
private cs: CountryService)
{
this.registerUserForm = new FormGroup({
'username': new FormControl(),
'email': new FormControl(),
'country_id': new FormControl(),
});
}
ngOnInit() {
this.registerUserForm = this.fb.group({
'username': ['', Validators.compose([Validators.required, Validators.minLength(5)])],
'country_id': ['', Validators.required],
'email': ['', [Validators.required, ValidationService.emailValidation]],
});
this.filteredOptionsCountry = this.myControlCountry.valueChanges.pipe(
startWith(''),
map(val => this.filterCountry(val))
);
this.cs.getAllCountry().subscribe(
countryes => {
this.countryes = countryes.map((country) => {
return new Country(country);
});
}
);
}
onRegisterUser() {
this.loading = true;
this.invalidInputs = true;
let newUser = new User(
this.registerUserForm.value
);
this.userService.createUser(newUser).subscribe(
);
}
onCancel() {
this.router.navigate(['/main/users']);
}
//Country
filterCountry(val: string): Country[] {
if (val) {
let filterValue = val.toLowerCase();
console.log(this.countryes)
return this.countryes.filter(country => country.name.toLowerCase().startsWith(filterValue));
}
return this.countryes;
}
}
my html code. In this code i have 3 parameters, only email and username i can post, country_id post empty
<form [formGroup]="registerUserForm" (ngSubmit)="onRegisterUser()" class="col s12" materialize>
<div class="row">
<div class="input-field col s12">
<input formControlName="username" id="username" type="text" class="validate" placeholder="Enter Username" minlength="3" maxlength="20"
required="" [ngClass]="{invalid: invalidInputs}">
</div>
</div>
<div class="row">
<div class="input-field col s12">
<input formControlName="email" id="email" type="email" class="validate" placeholder="Enter Email" required="" aria-required="true"
[ngClass]="{invalid: invalidInputs}">
</div>
</div>
<!-- Autocomplete Country Material-->
<input formControlName="country_id" id="country_id" matInput placeholder="Select Country" aria-label="State" [matAutocomplete]="auto"
autoActiveFirstOption [formControl]="myControlCountry">
<mat-autocomplete #auto="matAutocomplete">
<mat-option *ngFor="let country of filteredOptionsCountry | async" [value]="country.name">
{{ country.name }}
</mat-option>
</mat-autocomplete>
<!-- End Autocomplete Country -->
<div id="register_user_button_container" class="row">
<button id="register_user_button" type="submit" class="btn waves-effect waves-light">
Register
</button>
<button id="cancel_button" (click)="onCancel()" class="btn waves-effect waves-light grey lighten-4 black-text">
Cancel
</button>
</div>
</form>
Can you suggest me, how to used this FormControl inside registerUserForm ? Or, something solution.
Your code is litteral chaos.
First, group everything in a single form.
registerUserForm: FormGroup;
Then, instantiate your form only once, you don't need to do it more.
constructor() {
this.registerUserForm = this.fb.group({
username: ['', [Validators.required, Validators.minLength(5)]],
country_id: ['', Validators.required],
email: ['', [Validators.required, ValidationService.emailValidation]],
myControlCountry: ''
});
}
Next, use a getter to get your countries. (This is one of the many ways)
countries: Country[];
get filteredCountries() {
const query = this.registerUserForm.get('country_id').value;
return query ?
this.countries.filter(c => c.name.toLowerCase().includes(query.toLowerCase)) :
this.countries;
}
Now you must bind it to your HTML :
<mat-option *ngFor="let country of filteredCountries" [value]="country.name">
{{ country.name }}
</mat-option>