Validating an Angular form with 2 dropdowns - html

I am learning to code with a portfolio that I made in Angular frontend, Java Spring Boot backend and SQL database. I added dropdowns to some parts of Angular from tables connected to other tables in the database, with tables and models in backend, and with models in frontend.
This works ok with only 1 dropdown in a form, but now I am trying to have 2 dropdowns in the same form and I can not make it so the submit button is valid.
The component is mixed with english and spanish and is the following:
HTML form only:
<div class="card mat-card" class="section1" id="education">
<div id="education-experience" class="font-fluid" style="padding: 20px;">
<div id="education-experience-header">
<i class="fas fa-book-open"></i>
<h2 class="section-header">Educación</h2>
</div>
<div *ngIf="isAdmin">
<h3>Agregar o editar educación
<i class="fa-solid fa-plus add-btn" data-bs-toggle="modal" data-bs-target="#educacionModal"></i>
<br>Modo: {{accion}}
<br>Resetear modo <i class="fa-solid fa-rotate-left" (click)="cancelar()" type="reset"></i>
</h3>
<div class="modal fade" id="educacionModal" tabindex="-1" role="dialog" aria-labelledby="educacionModalLabel">
<div class="modal-dialog modal-xl" role="document" style="width: 100%; max-width: 1500px">
<div class="modal-content">
<div class="modal-header">
<div style="flex-direction: column-start;">
<h3 class="modal-title" id="educacionModalLabel">Modo: {{accion}}</h3>
<p class="modal-subtitle">Cada educación que se agrega, queda primera en la lista.</p>
</div>
</div>
<div class="modal-body">
<form [formGroup]="form" (ngSubmit)="crearEducacion()">
<div class="input-group mb-3">
<label class="input-group-text">Institución</label>
<input formControlName="schoolName" type="text" class="form-control" placeholder="Nombre de la institución"
[ngClass]="{'is-invalid':SchoolName?.errors && SchoolName?.touched, 'is-valid':!SchoolName?.errors && SchoolName?.touched}">
<div *ngIf="SchoolName?.errors && SchoolName?.touched">
<p *ngIf="SchoolName?.hasError('required')" class="text-danger" style="background-color: black;">
Ponga la institución.
</p>
</div>
</div>
<div class="input-group mb-3">
<label class="input-group-text">Título</label>
<input formControlName="title" type="text" class="form-control" placeholder="Título"
[ngClass]="{'is-invalid':Title?.errors && Title?.touched, 'is-valid':!Title?.errors && Title?.touched}">
<div *ngIf="Title?.errors && Title?.touched">
<p *ngIf="Title?.hasError('required')" class="text-danger" style="background-color: black;">
Ponga el título.
</p>
</div>
</div>
<div class="input-group mb-3">
<label class="input-group-text">Logo</label>
<input formControlName="logo" type="text" class="form-control"
placeholder="URL del logo (tiene que estar previamente en alguna página)">
</div>
<div class="row">
<div class="col-lg-3">
<div class="input-group mb-3">
<label class="input-group-text">Fecha de inicio</label>
<input formControlName="startDate" type="date" class="form-control" placeholder="Fecha de inicio"
[ngClass]="{'is-invalid':StartDate?.errors && StartDate?.touched, 'is-valid':!StartDate?.errors && StartDate?.touched}">
<div *ngIf="StartDate?.errors && StartDate?.touched">
<p *ngIf="StartDate?.hasError('required')" class="text-danger" style="background-color: black;">
Ponga la fecha de inicio.
</p>
</div>
</div>
</div>
<div class="col-lg-3">
<div class="input-group mb-3">
<label class="input-group-text">Fecha de fin</label>
<input formControlName="endDate" type="date" class="form-control" placeholder="Fecha de fin"
[ngClass]="{'is-invalid':EndDate?.errors && EndDate?.touched, 'is-valid':!EndDate?.errors && EndDate?.touched}">
<div *ngIf="EndDate?.errors && EndDate?.touched">
<p *ngIf="EndDate?.hasError('required')" class="text-danger" style="background-color: black;">
Ponga la fecha de fin.
</p>
</div>
</div>
</div>
<div class="col-lg-5">
<div class="input-group mb-3">
<div class="input-group-prepend">
<label class="input-group-text">
Educación actual (poner cualquier fecha en fecha de fin y marcar el checkbox)
<input formControlName="currentEducation" type="checkbox" class="form-check-input"
placeholder="Educación actual">
</label>
</div>
</div>
</div>
</div>
<div class="col-lg-5">
<div class="input-group mb-3">
<label class="input-group-text">Tipo de educación</label>
<select formControlName="educacion_tipo">
<option *ngFor="let educacion_tipo of educacion_tipoLista" [value]="educacion_tipo.id" placeholder="Tipo de educación"
[ngClass]="{'is-invalid':Educacion_tipo?.errors && Educacion_tipo?.touched, 'is-valid':!Educacion_tipo?.errors && Educacion_tipo?.touched}">
{{educacion_tipo.educationType}}
</option>
</select>
<p *ngIf="Educacion_tipo?.hasError('required')" class="text-danger" style="background-color: black;">
Ponga el tipo de educación.
</p>
</div>
</div>
<div class="col-lg-5">
<div class="input-group mb-3">
<label class="input-group-text">Estado de educación</label>
<select formControlName="educacion_estado">
<option *ngFor="let educacion_estado of educacion_estadoLista" [value]="educacion_estado.id" placeholder="Estado de educación"
[ngClass]="{'is-invalid':Educacion_estado?.errors && Educacion_estado?.touched, 'is-valid':!Educacion_estado?.errors && Educacion_estado?.touched}">
{{educacion_estado.educationStatus}}
</option>
</select>
<p *ngIf="Educacion_estado?.hasError('required')" class="text-danger" style="background-color: black;">
Ponga el estado de educación.
</p>
</div>
</div>
<div class="input-group mb-3">
<label class="input-group-text">Descripción</label>
<input formControlName="educationDescription" type="text" class="form-control" placeholder="Descripción"
[ngClass]="{'is-invalid':EducationDescription?.errors && EducationDescription?.touched,
'is-valid':!EducationDescription?.errors && EducationDescription?.touched}">
<div *ngIf="EducationDescription?.errors && EducationDescription?.touched">
<p *ngIf="EducationDescription?.hasError('required')" class="text-danger" style="background-color: black;">
Ponga la descripción.
</p>
</div>
</div>
<div class="d-grip gap-2">
<button type="submit" class="btn btn-success btn-lg" [disabled]="!form.valid" data-bs-dismiss="modal">Aceptar</button>
<button type="reset" class="btn btn-danger btn-lg" (click)="cancelar()" data-bs-dismiss="modal" aria-label="Close">Cancelar</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
TypeScript:
import { Component, OnInit } from '#angular/core';
import { FormBuilder, FormGroup, Validators } from '#angular/forms';
import { EducacionEstado } from 'src/app/modelos/educacion-estado.model';
import { EducacionTipo } from 'src/app/modelos/educacion-tipo.model';
import { Educacion } from 'src/app/modelos/educacion.model';
import { EducacionService } from 'src/app/servicios/educacion.service';
import { TokenService } from 'src/app/servicios/token.service';
#Component({
selector: 'app-educacion',
templateUrl: './educacion.component.html',
styleUrls: ['./educacion.component.css']
})
export class EducacionComponent implements OnInit {
educacionLista?:Educacion[];
educacion:Educacion = { id: 0, schoolName: '', title: '', logo: '', startDate: new(Date), endDate: new(Date), educationDescription: '',
currentEducation: false, educacion_tipo: {id: 0, educationType: ''}, educacion_estado:{id: 0, educationStatus: ''},persona: 0 };
accion = 'Agregar';
form: FormGroup;
id: number | undefined;
authority!:string;
isAdmin = false;
educacion_tipo:EducacionTipo = { id: 0, educationType: '' };
educacion_tipoLista?:EducacionTipo[];
educacion_estado:EducacionEstado = { id: 0, educationStatus: '' };
educacion_estadoLista?:EducacionEstado[];
constructor(private educacionService:EducacionService, private fb:FormBuilder, private tokenService: TokenService) {
this.form = this.fb.group({
schoolName: ['',[Validators.required]],
title:['',[Validators.required]],
logo: [''],
startDate: [0,[Validators.required]],
endDate: [0,[Validators.required]],
studiesStatus: ['',[Validators.required]],
educationDescription: ['',[Validators.required]],
currentEducation: false,
educacion_tipo: ['',[Validators.required]],
educacion_estado: ['',[Validators.required]]
})
}
ngOnInit(): void {
this.obtenerEducacion();
this.obtenerEducacionTipo();
this.obtenerEducacionEstado();
this.isAdmin = this.tokenService.isAdmin();
}
obtenerEducacion(){
this.educacionService.obtenerEducacion().subscribe(educacion => {
this.educacionLista=educacion;
}, error => {
console.log(error)
})
}
obtenerEducacionTipo(){
this.educacionService.obtenerEducacionTipo().subscribe(educacion_tipo => {
this.educacion_tipoLista=educacion_tipo;
}, error => {
console.log(error)
});
}
obtenerEducacionEstado(){
this.educacionService.obtenerEducacionEstado().subscribe(educacion_estado => {
this.educacion_estadoLista=educacion_estado;
}, error => {
console.log(error)
});
}
crearEducacion() {
const educacion: Educacion = {
schoolName: this.form.get('schoolName')?.value,
title: this.form.get('title')?.value,
logo: this.form.get('logo')?.value,
startDate: this.form.get('startDate')?.value,
endDate: this.form.get('endDate')?.value,
educationDescription: this.form.get('educationDescription')?.value,
currentEducation: this.form.get('currentEducation')?.value,
educacion_tipo: this.educacion_tipoLista!.find(et=>et.id==this.form.get('educacion_tipo')?.value),
educacion_estado: this.educacion_estadoLista!.find(es=>es.id==this.form.get('educacion_estado')?.value)
}
if(this.id == undefined) {
this.educacionService.crearEducacion(educacion).subscribe(educacion => {
this.obtenerEducacion();
this.form.reset();
}, error => {
console.log(error);
})
} else {
educacion.id = this.id;
this.educacionService.actualizarEducacion(this.id, educacion).subscribe(educacion => {
this.form.reset();
this.accion = 'Agregar';
this.id = undefined;
this.obtenerEducacion();
}, error => {
console.log(error);
})
}
}
borrarEducacion(id: number) {
this.educacionService.borrarEducacion(id).subscribe(educacion =>{
this.obtenerEducacion()
}, error => {
console.log(error);
})
}
actualizarEducacion(educacion: Educacion) {
this.accion = 'Editar educación: ' + educacion.title + ' en ' + educacion.schoolName;
this.id = educacion.id;
this.form.patchValue({
schoolName: educacion.schoolName,
title: educacion.title,
logo: educacion.logo,
startDate: educacion.startDate,
endDate: educacion.endDate,
educationDescription: educacion.educationDescription,
currentEducation: educacion.currentEducation,
educacion_tipo: educacion.educacion_tipo?.id,
educacion_estado: educacion.educacion_estado?.id
})
}
cancelar(){
this.form.reset();
this.accion = 'Agregar';
this.id = undefined;
this.obtenerEducacion();
}
get SchoolName(){
return this.form.get('schoolName');
}
get Title(){
return this.form.get('title');
}
get StartDate(){
return this.form.get('startDate');
}
get EndDate(){
return this.form.get('endDate');
}
get EducationDescription(){
return this.form.get('educationDescription');
}
get Educacion_tipo(){
return this.form.get('educacion_tipo');
}
get Educacion_estado(){
return this.form.get('educacion_estado')
}
}
There is a service for HTTP, models for educacion, educacion_tipo and educacion_estado and JWT for editing. I had educacion_tipo and it worked, but I added educacion_estado and the form will not become valid. Removing validators from HTML and TypeScript also does not work. The only workaround is removing is valid from submit, but I would like to keep that validation in the component.

Related

how can i edit a form array

I have an application where I want to edit the information of a FormArray, but I input!
I can create data, but I cannot edit it.
I've already tried to create another matrix form, but it still doesn't have any connection form when trying to edit data that already exists within this one.
my typescript code:
ngOnInit(): void {
this.projectInfoService.retrieveById(+this.activatedRoute.snapshot.paramMap.get('id')!).subscribe({
next: project => {
console.log(project)
this.project = project
this.rgForm = this.fb.group({
id: [this.project.id],
name: [this.project.name, Validators.required],
team: [this.project.team,],
description: [this.project.description, Validators.required],
tasks: this.fb.array([])
})
},
error: err => console.log('Error:', err)
});
}
get name() {
return this.rgForm.get('name')
}
get description() {
return this.rgForm.get('description')
}
get team() {
return this.rgForm.get('team')
}
get tasks(): FormArray {
return <FormArray>this.rgForm.get('tasks');
}
my html code:
<ng-container formArrayName="tasks" *ngFor="let task of tasks.controls; let i=index">
<div [formGroupName]="i" class="d-flex justify-content-center aling-items-center my-2">
<div class="col-md-5">
<div class="form-floating">
<input type="text" formControlName="nameTask" [attr.id]="'task' + i" id="floatingInputGridT"
class="form-control" placeholder="Nome da tarefa" required>
<label [attr.for]="'task' + i" for="floatingInputGridT">Tarefa</label>
</div>
</div>
<div class="col-md-5">
<div class="form-floating">
<select class="form-select" formControlName="member" [attr.id]="'taskMember' + i">
<option *ngFor="let member of _members" [value]="member.nameMember">{{ member.nameMember }}</option>
</select>
<label [attr.for]="'taskMember' + i">Membro da task</label>
</div>
</div>
<div class="d-flex justify-content-center aling-items-center flex-column">
<div class="col-md-1">
<button type="button" class="btn btn-danger" (click)="deleteTask(i)"><i
class="fa-solid fa-trash-can"></i></button>
</div>
</div>
</div>
</ng-container>
How can I edit the values ​​contained in this FomrArray?

How to verify validion of form inside form?

I'm trying to verify a form that's inside a form.
The idea is to create a user's html page with the option to create a contact list.
My goal is to verify both forms with one click on the 'Save User Profile' button.
My question is How to verify the validion of the inner form inside the main form?
NO BOOTSTRAP AND OTHERS.
Main form:
HTML:
<div class="container"
style="width: 60%;">
<h5>User Profile</h5>
<div>
<form (ngSubmit)="onSubmit()"
#f=ngForm>
<!-- Name -->
<div class="column">
<label for="name"
style="margin-left: 5px;">Name</label><br>
<input type="text"
[(ngModel)]="user.name"
name="name"
id="name"
required
minlength="2"
maxlength="30"
#n="ngModel">
<p *ngIf="!n.valid && n.touched"
style="color: red;"> Please insert a name with 2-30 chars</p>
</div>
<!-- Organization -->
<div class="column">
<label for="orga"
style="margin-left: 5px;">Organization</label><br>
<input type="text"
[(ngModel)]="user.organization"
name="orga"
id="orga">
</div>
<br><br><br><br><br>
<h5>Contact Information</h5>
<div class="box">
<app-user-card *ngFor="let c of contacts; let i = index"
[id]="i"
[user]="user"></app-user-card>
<br><br>
</div>
<button type="button"
class="btn-add"
(click)="addContact()">Add Contact</button>
<button class="btn-save"
type="submit"
[disabled]="!f.valid">Save User Profile
</button>
</form>
</div>
TS:
export class UsersListComponent implements OnInit {
users: User[] = []
user: User = {
name: '',
organization: '',
contacts: []
}
id: number
contacts: Contact[] = []
contact: Contact = {
id: 0,
type: '',
label: '',
contact: ''
}
constructor() { }
ngOnInit(): void {
this.user.contacts = this.contacts
}
addContact() {
this.contacts.push(new Contact(this.id, this.contact.type, this.contact.label, this.contact.contact))
}
onSubmit() {
/* Upgrade option: Check if a user exists on the system and view his contacts*/
this.users.push(new User(this.user.name, this.user.organization, this.contacts))
console.log(this.users);
}
}
inner form:
HTML:
<div class="card">
<form #f = "ngForm">
<div class="column">
<label for="contactType">Type of Contact</label><br>
<select id="contactType"
[(ngModel)]=contact.type
name="cotactType"
style="width: 95%;"
required>
<option value="email">Email</option>
<option value="phone">Phone</option>
</select>
</div>
<div class="column">
<label for="label">Contact Label</label><br>
<input type="text"
[(ngModel)]="contact.label"
id="label"
name="lable"
style="width: 95%;"
required
minlength="2"
maxlength="20"
#l>
<p *ngIf="!l.valid && l.touched"
style="color: red;">Label is required!</p>
</div>
<div>
<label for="contact"
style="margin-left: 5px;">Email/Phon No.</label><br>
<input type="text"
[(ngModel)]=contact.contact
required
id="contact"
name="contact"
style="width: 98%;"
#c>
<p *ngIf="!c.valid && c.touched"
style="color: red;">Email/Phon No is required!</p>
</div>
<button type="button"
class="btn-remove"
style="left: 69%;position: relative;">Remove</button>
</form>
TS:
#Component({
selector: 'app-user-card',
templateUrl: './user-card.component.html',
styleUrls: ['./user-card.component.css']
})
export class UserCardComponent implements OnInit {
contact: Contact = {
id: 0,
type: '',
label: '',
contact: ''
}
#ViewChild("f") contactDetails: NgForm
#Input() id: number
constructor() { }
ngOnInit(): void {}
}

Angular validations showing during the page load

We are working on the Angular 4 form and set some validations on the input field but the validation is showing when the page load's but we want the validation when the form is submitted or the field is not valid or filled.
Component.html
<div class="headerbutton-group row">
<i class="fa fa-save header-buttons" tooltip ="Save" tabindex="1" (click)="onSave($event)"></i>
<i class="fa fa-close header-buttons" tooltip ="Close" (click)="onCancel($event)"></i>
</div>
<form [formGroup]="editForm" class="col-md-12 ">
<div class="form-group row">
<div class="col-md-6 padding-Mini">
<label class="col-md-12 col-form-label padding-bottom-Mini" for="txtName">Name</label>
<div class="col-md-12">
<input type="text" id="txtName" name="txtName" class="form-control" placeholder="Name" formControlName="name" [class.is-invalid]="!editForm.controls.name.valid" [class.is-valid]="editForm.controls.name.valid" required>
<div class="invalid-feedback" [style.visibility]=
"editForm.controls.name.valid ? 'hidden':'visible'"> Name is required</div>
</div>
</div>
<div class="col-md-6 padding-Mini">
<label class="col-md-12 col-form-label padding-bottom-Mini" for="txtName">Description</label>
<div class="col-md-12">
<input type="text" id="txtDescription" name="txtDescription" class="form-control"
placeholder="Description" formControlName="description">
</div>
</div>
</div>
</form>
Component.ts
#Component({
selector: 'app-edit-form',
templateUrl: './component.html'
})
export class LoginFormComponent implements OnInit {
constructor(fb:FormBuilder) {
public editForm: FormGroup = new FormGroup({
name : new FormControl('', Validators.required),
description : new FormControl(''),
});
}
public onSave(e): void {
if (this.editForm.valid) {
e.preventDefault();
this.save.emit(this.editForm.value);
} else {
this.validateAllFormFields(this.editForm);
}
}
public onCancel(e): void {
e.preventDefault();
this.closeForm();
}
private validateAllFormFields(formGroup: FormGroup) {
Object.keys(formGroup.controls).forEach(field => {
const control = formGroup.get(field);
if (control instanceof FormControl) {
control.markAsTouched({ onlySelf: true });
} else if (control instanceof FormGroup) {
this.validateAllFormFields(control);
}
});
}
}
// Tried this too editForm.controls.name.pristine
We don't know what we are missing. Kindly help us, with useful documents/ Demo's.
try changing this
<div class="invalid-feedback" [style.visibility]="editForm.controls.name.valid ? 'hidden':'visible'">
Name is required
</div>
to this
<div class="invalid-feedback" *ngIf="!editForm.controls.name.valid && editForm.controls.name.touched">
Name is required
</div>
adding a test on "touched" will fix your problem !

Error + JSON + <select> + <option>

I'm getting a very strange error after I upgraded to Angular 6.0.9. My template has a select, where there is an opnion with a value of "" and an "Select an Option" label, and the other options are generated by a list that comes from the bank.
So when I need to clear the form I call the formBuilder again. However, when I clean the form, a request occurs to api and consequently a json error, warning that it can not serialize a null value.
During the reset of the form I do not call any method that triggers the API, so I'm not sure what to do.
It is worth mentioning that the application still works, but it presents the user with an error message, since I have an interceptor that receives all errors and prints in a snack bar...
Template:
<select class="form-control" id="selectTipoDocumento" formControlName="tipoDocumento" [compareWith]="equals"
[class.is-valid]="this.docForm.controls['tipoDocumento'].valid &&
(this.docForm.controls['tipoDocumento'].touched || this.docForm.controls['tipoDocumento'].dirty)"
[class.is-invalid]="!this.docForm.controls['tipoDocumento'].valid &&
(this.docForm.controls['tipoDocumento'].touched || this.docForm.controls['tipoDocumento'].dirty)">
<option value="">Selecione um tipo</option>
<option *ngFor="let tipo of tiposDocumento" [ngValue]="tipo">{{tipo?.nome}}</option>
</select>
Component:
export class DocumentoDetalheComponent implements OnInit {
docForm: FormGroup;
tiposDocumento: TipoDocumento[];
documento: Documento = new Documento();
constructor(
private fb: FormBuilder,
private tipoDocumentoService: TipoDocumentoService,
private documentoService: DocumentoService,
private route: ActivatedRoute
) {}
ngOnInit() {
const idRota: string = this.route.snapshot.params["id"];
this.createFormGroup();
this.tipoDocumentoService.findAll().subscribe(
obj => {
this.tiposDocumento = obj;
},
error => { }
).unsubscribe;
if (idRota != null){
this.documentoService.findById(idRota).subscribe(
obj => {
this.documento = obj;
this.docForm.setValue({
tipoDocumento: this.documento.tipoDocumento,
resumo: this.documento.resumo,
observacao: this.documento.observacao
});
},
error => { }
);}
}
onSubmit() {
let docTemp: Documento = this.docForm.value;
this.documento.tipoDocumento = docTemp.tipoDocumento;
this.documento.resumo = docTemp.resumo;
this.documento.observacao = docTemp.observacao;
if (this.documento.id == null) {
this.save(this.documento);
} else {
this.update(this.documento);
}
}
save(documento: Documento) {
this.documentoService
.insert(documento)
.subscribe(response => console.log(response));
}
update(documento: Documento) {
this.documentoService.update(documento).subscribe(response => console.log(response));
}
createFormGroup() {
this.docForm = this.fb.group({
tipoDocumento: ["", [Validators.required]],
resumo: ["",[Validators.required, Validators.minLength(5), Validators.maxLength(60)]],
observacao: ["", [Validators.maxLength(500)]]
});
}
limparForm() {
this.createFormGroup();
}
equals(tp1: TipoDocumento, tp2: TipoDocumento) {
return tp1.id === tp2.id
}
voltar() {}
}
API error:
2018-07-16 10:05:43.186 WARN 4996 --- [ tomcat-http--5] .w.s.m.s.DefaultHandlerExceptionResolver : Failed to read HTTP message: org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot construct instance of `br.mp.mpce.sge.domain.TipoDocumento` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value (''); nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `br.mp.mpce.sge.domain.TipoDocumento` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('')
at [Source: (PushbackInputStream); line: 1, column: 579] (through reference chain: br.mp.mpce.sge.domain.Documento["tipoDocumento"])
I found the solution. The problem was in my formGroup, where I was using ngSubmit, so all buttons in my form were submitting API requests. So, the solution was to remove ngSubmir from the form, as well as manually set, in the event (click), the necessary methods.
<form [formGroup]="docForm" novalidate>
<div class="card">
<div class="card-body">
<div class="form-group row" *ngIf="documento?.id != null">
<div class="form-group col-md-3">
<label for="setor">Nº Protocolo: </label>
</div>
<div class="form-group col-md-6">
{{documento?.codigo}}/{{documento?.ano}}
</div>
</div>
<div class="form-group row" *ngIf="documento?.id != null">
<div class="form-group col-md-3">
<label for="setor">Setor cadastro: </label>
</div>
<div class="form-group col-md-6">
{{documento?.setorCadastro?.nome}}
</div>
</div>
<div class="form-group row">
<div class="form-group col-md-3">
<label for="selectTipoDocumento">Tipo de Documento: </label>
</div>
<div class="form-group col-md-6">
<select class="form-control" id="selectTipoDocumento" formControlName="tipoDocumento" [compareWith]="equals"
[class.is-valid]="this.docForm.controls['tipoDocumento'].valid &&
(this.docForm.controls['tipoDocumento'].touched || this.docForm.controls['tipoDocumento'].dirty)"
[class.is-invalid]="!this.docForm.controls['tipoDocumento'].valid &&
(this.docForm.controls['tipoDocumento'].touched || this.docForm.controls['tipoDocumento'].dirty)">
<option value="">Selecione um tipo</option>
<option *ngFor="let tipo of tiposDocumento" [ngValue]="tipo">{{tipo?.nome}}</option>
</select>
</div>
<div class="form-group col-md-3 invalid-feedback d-block"
*ngIf="!this.docForm.controls['tipoDocumento'].valid && (this.docForm.controls['tipoDocumento'].touched || this.docForm.controls['tipoDocumento'].dirty)">
Tipo dodocumento é obrigatório
</div>
</div>
<div class="form-group row">
<div class="form-group col-md-3">
<label for="inputResumo">Resumo: </label>
</div>
<div class="form-group col-md-6">
<input type="text" class="form-control" id="inputResumo" formControlName="resumo" placeholder="Resumo do documento" maxlength="60"
autocomplete="off"
[class.is-valid]="this.docForm.controls['resumo'].valid && (this.docForm.controls['resumo'].touched || this.docForm.controls['resumo'].dirty)"
[class.is-invalid]="!this.docForm.controls['resumo'].valid && (this.docForm.controls['resumo'].touched || this.docForm.controls['resumo'].dirty)">
</div>
<div class="form-group col-md-3 invalid-feedback d-block"
*ngIf="!this.docForm.controls['resumo'].valid && (this.docForm.controls['resumo'].touched || this.docForm.controls['resumo'].dirty)">
Resumo é obrigatório (5 a 60 caracteres)
</div>
</div>
<div class="form-group row">
<div class="form-group col-md-3">
<label for="inputObservacao">Observação: </label>
</div>
<div class="form-group col-md-6">
<textarea type="text" class="form-control" id="inputObservacao" formControlName="observacao" rows="5">
</textarea>
</div>
</div>
<div class="form-group row">
<div class="form-group col-md-3">
</div>
<div class="form-group col-md-2">
<button class="btn btn-primary btn-block" (click)="limparForm()">Limpar</button>
</div>
<div class="form-group col-md-2">
<button class="btn btn-success btn-block"[disabled]="!docForm.valid" (click)="onSubmit()">Salvar</button>
</div>
<div class="form-group col-md-2">
<a class="btn btn-primary btn-block" [routerLink]="['/']">Voltar</a>
</div>
</div>
</div>
</div>
</form>

No provider for ControlContainer AngularJS2

I am doing a job and I am not getting out of this error 2 days ago I will be posting the html code and TypeScript.
Code Index
<html>
<head>
<base href="/angular-21-menu-busca-alteracao-inclusao-remocao-selecao-inc/">
<title>Angular 2</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="app/css/bootstrap.css">
<link rel="stylesheet" href="app/css/site.css">
<!-- 1. Load libraries -->
<!-- Polyfill(s) for older browsers -->
<script src="node_modules/core-js/client/shim.min.js"></script>
<script src="node_modules/zone.js/dist/zone.js"></script>
<script src="node_modules/reflect-metadata/Reflect.js"></script>
<script src="node_modules/systemjs/dist/system.src.js"></script>
<!-- 2. Configure SystemJS -->
<script src="systemjs.config.js"></script>
<script src="app/js/jquery-1.12.4.js"></script>
<script src="app/js/bootstrap.js"></script>
<script src="app/js/script.js"></script>
<script src="app/js/web-animations.min.js"></script>
<script>
System.import('app').catch(function(err){ console.error(err); });
</script>
</head>
<!-- 3. Display the application -->
<body>
<angular-app>Loading...</angular-app>
</body>
</html>
Code Html
<h2 class="text-center">Cadastro de Clientes</h2>
<!-- Adicionar -->
<h4 id="mensagem" class="text-center" [style.color]="getCor()" [style.visibility]="getVisibilidade()">{{mensagem}}</h4>
<!-- Fim adicionar -->
<div class="container">
<div class="row">
<div class="col-xs-12">
<div *ngIf="aluno">
<div class="media-list">
<div class="row">
<div class="col-xs-12">
<div class="media">
<div class="media-body">
<form class="form-horizontal" [formGroup]="usuarioGroup" role="form" (ngSubmit)="onSubmit(usuarioGroup.valid)" novalidate>
<fieldset [disabled]="isDesabilitado">
<legend>Inf. Básicas</legend>
<div class="form-group form-group-sm">
<label class="col-sm-2 control-label" for="nome">Nome</label>
<div class="col-sm-9">
<input type="text"
id="nome"
[ngClass]="{'form-control': true, 'input-sm': true, 'submitted': submitted}"
>
</div>
<div class="col-sm-9 col-sm-offset-2">
<div *ngIf="formErrors.nome && submitted" class="alert alert-danger">
{{ formErrors.nome }}
</div>
</div>
<div class="col-sm-1"></div>
</div>
<!--
<div class="form-group form-group-sm">
<label class="control-label col-sm-2">Sexo</label>
<div class="col-sm-10">
<input type="radio" [(ngModel)]="aluno.sexo" name="sexo" value="M"> Masculino
</div>
<div class="col-sm-10 col-sm-offset-2">
<input type="radio" [(ngModel)]="aluno.sexo" name="sexo" value="F"> Feminino
</div>
</div>
<div class="form-group form-group-sm">
<label class="control-label col-xs-12 col-sm-2" for="sus">Num.SUS</label>
<div class="col-xs-9 col-sm-3">
<input [(ngModel)]="aluno.sus" maxlength="15" name="sus" class="form-control" id="sus">
</div>
<div class="col-xs-3 col-sm-7"></div>
</div>
</fieldset>
<br/>
<fieldset [disabled]="isDesabilitado">
<legend>Endereço</legend>
<div class="form-group form-group-sm">
<label class="col-sm-2 control-label" for="endereco">Logradouro</label>
<div class="col-sm-9">
<input [(ngModel)]="aluno.endereco" name="endereco" class="form-control"
type="text"
id="endereco">
</div>
<div class="col-sm-1"></div>
</div>
<div class="form-group form-group-sm">
<label class="col-sm-2 control-label" for="bairro">Bairro</label>
<div class="col-sm-9">
<input [(ngModel)]="aluno.bairro" name="bairro" class="form-control" type="text"
id="bairro">
</div>
<div class="col-sm-1"></div>
</div>
<div class="form-group form-group-sm">
<label class="col-sm-2 control-label" for="cidade">Cidade</label>
<div class="col-sm-9">
<input [(ngModel)]="aluno.cidade" name="cidade" class="form-control" type="text"
id="cidade">
</div>
<div class="col-sm-1"></div>
</div>
<div class="form-group form-group-sm">
<label class="col-xs-12 col-sm-2 control-label" for="estado">Estado</label>
<div class="col-xs-5 col-sm-2">
<input [(ngModel)]="aluno.estado" maxlength="2" name="estado" class="form-control" type="text"
id="estado">
</div>
<div class="col-xs-7 col-sm-8"></div>
</div>
-->
</fieldset>
</form>
</div>
</div>
</div>
</div>
</div>
<div class="wrapper">
<!-- Adicionar -->
<button *ngIf="exibirEditar" class="btn btn-primary" (click)="editavel()">
<span class="glyphicon glyphicon-edit"></span> Editar
</button>
<button *ngIf="exibirAlterar" [disabled]="!f.valid" class="btn btn-primary" (click)="alterar(aluno)">
<span class="glyphicon glyphicon-save"></span> Alterar
</button>
<button *ngIf="exibirCadastrar" [disabled]="!usuarioGroup.valid" class="btn btn-primary" (click)="cadastrar(aluno)">
<span class="glyphicon glyphicon-save"></span> Salvar
</button>
<!-- Fim adicionar -->
<button class="btn btn-warning" (click)="voltar()">
<span class="glyphicon glyphicon-backward"></span> Voltar
</button>
</div>
<br/>
<br/>
<br/>
</div>
</div>
</div>
</div>
Code TS
import { Component, OnInit } from '#angular/core';
import { ActivatedRoute, Params } from '#angular/router';
import { AlunoService } from './aluno.service';
import { Aluno } from './aluno';
import { Router } from '#angular/router';
import {FormBuilder, FormGroup, Validators} from "#angular/forms";
import {AutoValida} from "./auto.valida";
interface UsuarioForm {
nome: string,
sexo: string,
endereco: string,
bairro: string,
cidade: string,
estado: string,
sus: string,
}
#Component({
selector: 'exibir-aluno',
templateUrl: 'app/partials/exibir-aluno.component.html',
styleUrls: ['app/css/exibir-aluno.css']
})
export class ExibirAlunoComponent implements OnInit{
usuarioForm: UsuarioForm = {nome: '', sexo: '', endereco: '', bairro: '', cidade: '', estado: '', sus: '',};
usuarioGroup: FormGroup;
alunos: Aluno[];
aluno: Aluno = null;
isDesabilitado: boolean = true;
// Adicionar campos aqui!
exibirEditar: boolean = true;
exibirAlterar: boolean = false;
mensagem: string = "Esta mensagem será alterada ao exibir!";
visibilidade: string = "hidden";
cor: string = "blue";
exibirCadastrar: boolean = false;
constructor(private fb: FormBuilder,
private alunoService:AlunoService,
private route:ActivatedRoute,
private router: Router) { }
ngOnInit():void {
this.buildForm();
console.log('executando ngOninit de ExibirAlunoComponent');
let id = +this.route.snapshot.params['id'];
console.log('id = ', id);
// id = NaN
if (isNaN(id)) {
this.novo();
}
else {
this.alunoService.getAluno(id)
.subscribe(
data => {
this.aluno = data;
},
err => {
this.mensagem = "Aluno NÃO encontrado! Status:" + err.status;
this.cor = "red";
this.visibilidade = "visible";
}
);
}
}
novo() {
this.isDesabilitado = false;
this.exibirEditar = false;
this.exibirCadastrar = true;
this.exibirAlterar = false;
this.visibilidade = "hidden";
this.aluno = {
id: null,
nome: '',
sexo: '',
endereco: '',
bairro: '',
cidade: '',
estado: '',
sus: '',
}
}
editavel() {
this.isDesabilitado = false;
this.exibirEditar = false;
this.exibirAlterar = true;
this.visibilidade = "hidden";
this.exibirCadastrar = false;
}
salvo() {
this.isDesabilitado = true;
this.exibirEditar = true;
this.exibirAlterar = false;
this.exibirCadastrar = false;
}
cadastrar(aluno: Aluno) {
this.salvo();
this.alunoService.cadastrar(aluno)
.subscribe(
resposta => {
console.log (resposta);
this.mensagem = "Aluno cadastrado com sucesso!";
this.cor = "blue";
this.visibilidade = "visible";
},
err => {
this.mensagem = "Aluno NÃO cadastrado! Status:" + err.status;
this.cor = "red";
this.visibilidade = "visible";
}
);
}
alterar(aluno: Aluno) {
this.salvo();
this.alunoService.atualizar(aluno)
.subscribe(
resposta => {
console.log (resposta);
this.mensagem = "Aluno alterado com sucesso!";
this.cor = "blue";
this.visibilidade = "visible";
},
err => {
this.mensagem = "Aluno NÃO alterado! Status:" + err.status;
this.cor = "red";
this.visibilidade = "visible";
}
);
}
voltar(): void {
let link = ['/alunos/exibirtodos'];
this.router.navigate(link);
}
getVisibilidade() {
return this.visibilidade;
}
getCor() {
return this.cor;
}
buildForm(): void {
this.usuarioGroup = this.fb.group({
'nome': [this.usuarioForm.nome, [Validators.required, AutoValida.validaNome]],
'sexo': [this.usuarioForm.sexo, [Validators.required]],
'sus': [this.usuarioForm.sus, [Validators.required]],
'endereco': [this.usuarioForm.endereco, [Validators.required]],
'bairro': [this.usuarioForm.bairro, [Validators.required]],
'cidade': [this.usuarioForm.cidade, [Validators.required]],
'estado': [this.usuarioForm.estado, [Validators.required]]
});
}
formErrors = {
nome: '',
sexo: '',
endereco: '',
bairro: '',
cidade: '',
estado: '',
sus: '',
}
submitted: boolean = false;
onSubmit(){
this.submitted = true;
if (!this.usuarioGroup.valid){
return;
}
}
}
Error
Can't bind to 'formGroup' since it isn't a known property of 'form'. (" <div class="media-body">
<form class="form-horizontal" [ERROR ->][formGroup]="usuarioGroup" role="form" (ngSubmit)="onSubmit(usuarioGroup.valid)" novalidate>
"): ExibirAlunoComponent#14:57
No provider for ControlContainer ("
<div class="media-body">
[ERROR ->]<form class="form-horizontal" [formGroup]="usuarioGroup" role="form" (ngSubmit)="onSubmit(usuarioGrou"): ExibirAlunoComponent#14:27 ; Zone: <root> ; Task: Promise.then ; Value: Error: Template parse errors:
Can't bind to 'formGroup' since it isn't a known property of 'form'. (" <div class="media-body">
<form class="form-horizontal" [ERROR ->][formGroup]="usuarioGroup" role="form" (ngSubmit)="onSubmit(usuarioGroup.valid)" novalidate>
"): ExibirAlunoComponent#14:57
No provider for ControlContainer ("
<div class="media-body">
[ERROR ->]<form class="form-horizontal" [formGroup]="usuarioGroup" role="form" (ngSubmit)="onSubmit(usuarioGrou"): ExibirAlunoComponent#14:27
I tried in various ways that came from my head, but I did not succeed.
Thank you very much in advance
The [] are missing in
formGroup="usuarioGroup"
It should be
[formGroup]="usuarioGroup"
The former creates an attribute with the string value 'usuarioGroup',
while the later binds the usuarioGroup field of the component to the formGroup property of the FormGroup directive.
Check if you has the ReactiveFormsModule imported in your module