No provider for ControlContainer and No provider for ControlContainer - html

I am working on an application using Angular2.
I am trying to use Reactive Forms in my application but I am running into some errors :
The first error is about NgControl as below:
No provider for NgControl ("
div class="col-md-8"
[ERROR ->]input class="form-control"
id="productNameId"
"): ProductEditComponent#16:24
The second error is about ControlContainer as below:
No provider for ControlContainer ("
div
[ERROR ->]div formArrayName="tags">
div class="row">
button cl"):
Htmm file is as below:
<div class="panel panel-primary">
<div class="panel-heading">
{{pageTitle}}
</div>
<div class="panel-body">
<form class="form-horizontal"
novalidate
(ngSubmit)="saveProduct()"
formGroup="productForm" >
<fieldset>
<div class="form-group"
[ngClass]="{'has-error': displayMessage.productName }">
<label class="col-md-2 control-label" for="productNameId">Product Name</label>
<div class="col-md-8">
<input class="form-control"
id="productNameId"
type="text"
placeholder="Name (required)"
formControlName="productName" />
<span class="help-block" *ngIf="displayMessage.productName">
{{displayMessage.productName}}
</span>
</div>
</div>
<div formArrayName="tags">
<div class="row">
<button class="col-md-offset-1 col-md-1 btn btn-default"
type="button"
(click)="addTag()">Add Tag
</button>
</div>
<div class="form-group"
*ngFor="let tag of tags.controls; let i=index" >
<label class="col-md-2 control-label" [attr.for]="i">Tag</label>
<div class="col-md-8">
<input class="form-control"
[id]="i"
type="text"
placeholder="Tag"
formControlName="i" />
</div>
</div>
</div>
<!--more piece of code here -->
My component file is as below:
import { Component, OnInit, AfterViewInit, OnDestroy, ViewChildren, ElementRef } from '#angular/core';
import { FormBuilder, FormGroup, FormControl, FormArray, Validators, FormControlName,NgForm } from '#angular/forms';
import { ActivatedRoute, Router } from '#angular/router';
import 'rxjs/add/operator/debounceTime';
import 'rxjs/add/observable/fromEvent';
import 'rxjs/add/observable/merge';
import { Observable } from 'rxjs/Observable';
import { Subscription } from 'rxjs/Subscription';
import { IProduct } from './product';
import { ProductService } from './product.service';
import { NumberValidators } from '../shared/number.validator';
import { GenericValidator } from '../shared/generic-validator';
#Component({
templateUrl: './product-edit.component.html'
})
export class ProductEditComponent implements OnInit, AfterViewInit, OnDestroy {
#ViewChildren(FormControlName, { read: ElementRef }) formInputElements: ElementRef[];
pageTitle: string = 'Product Edit';
errorMessage: string;
productForm: FormGroup;
product: IProduct;
private sub: Subscription;
// Use with the generic validation message class
displayMessage: { [key: string]: string } = {};
private validationMessages: { [key: string]: { [key: string]: string } };
private genericValidator: GenericValidator;
get tags(): FormArray {
return <FormArray>this.productForm.get('tags');
}
constructor(private fb: FormBuilder,
private route: ActivatedRoute,
private router: Router,
private productService: ProductService) {
// Defines all of the validation messages for the form.
// These could instead be retrieved from a file or database.
this.validationMessages = {
productName: {
required: 'Product name is required.',
minlength: 'Product name must be at least three characters.',
maxlength: 'Product name cannot exceed 50 characters.'
},
productCode: {
required: 'Product code is required.'
},
starRating: {
range: 'Rate the product between 1 (lowest) and 5 (highest).'
}
};
// Define an instance of the validator for use with this form,
// passing in this form's set of validation messages.
this.genericValidator = new GenericValidator(this.validationMessages);
}
ngOnInit(): void {
this.productForm = this.fb.group({
productName: ['', [Validators.required,
Validators.minLength(3),
Validators.maxLength(50)]],
productCode: ['', Validators.required],
starRating: ['', NumberValidators.range(1, 5)],
tags: this.fb.array([]),
description: ''
});
// Read the product Id from the route parameter
this.sub = this.route.params.subscribe(
params => {
let id = +params['id'];
this.getProduct(id);
}
);
}
ngOnDestroy(): void {
this.sub.unsubscribe();
}
ngAfterViewInit(): void {
// Watch for the blur event from any input element on the form.
let controlBlurs: Observable<any>[] = this.formInputElements
.map((formControl: ElementRef) => Observable.fromEvent(formControl.nativeElement, 'blur'));
// Merge the blur event observable with the valueChanges observable
Observable.merge(this.productForm.valueChanges, ...controlBlurs).debounceTime(800).subscribe(value => {
this.displayMessage = this.genericValidator.processMessages(this.productForm);
});
}
addTag(): void {
this.tags.push(new FormControl());
}
getProduct(id: number): void {
this.productService.getProduct(id)
.subscribe(
(product: IProduct) => this.onProductRetrieved(product),
(error: any) => this.errorMessage = <any>error
);
}
onProductRetrieved(product: IProduct): void {
if (this.productForm) {
this.productForm.reset();
}
this.product = product;
if (this.product.id === 0) {
this.pageTitle = 'Add Product';
} else {
this.pageTitle = `Edit Product: ${this.product.productName}`;
}
// Update the data on the form
this.productForm.patchValue({
productName: this.product.productName,
productCode: this.product.productCode,
starRating: this.product.starRating,
description: this.product.description
});
this.productForm.setControl('tags', this.fb.array(this.product.tags || []));
}
deleteProduct(): void {
if (this.product.id === 0) {
// Don't delete, it was never saved.
this.onSaveComplete();
} else {
if (confirm(`Really delete the product: ${this.product.productName}?`)) {
this.productService.deleteProduct(this.product.id)
.subscribe(
() => this.onSaveComplete(),
(error: any) => this.errorMessage = <any>error
);
}
}
}
saveProduct(): void {
if (this.productForm.dirty && this.productForm.valid) {
// Copy the form values over the product object values
let p = Object.assign({}, this.product, this.productForm.value);
this.productService.saveProduct(p)
.subscribe(
() => this.onSaveComplete(),
(error: any) => this.errorMessage = <any>error
);
} else if (!this.productForm.dirty) {
this.onSaveComplete();
}
}
onSaveComplete(): void {
// Reset the form to clear the flags
this.productForm.reset();
this.router.navigate(['/products']);
}
}
I am trying to solve this problem for more than 2 days but I still do not have a solution. I have seen many other answers in stackoverflow but none of them is solving my problem.

Import both Forms Module and ReactiveFormsModule from #angular/forms in the file app.module.ts

Related

My codes are not doing get,set,post so what is my codes error how can i fix it?

these are my .ts codes i write these becasue i want to get product details and delete
import { Component, OnInit } from '#angular/core';
import {FormGroup,FormBuilder, FormControl, Validators} from "#angular/forms"
import { ToastrService } from 'ngx-toastr';
import { Product } from 'src/app/models/product';
import { ProductService } from 'src/app/services/product.service';
import { LocalStorageService } from 'src/app/services/local-storage.service';
import { Router } from '#angular/router';
#Component({
selector: 'app-product-delete',
templateUrl: './product-delete.component.html',
styleUrls: ['./product-delete.component.css']
})
export class ProductDeleteComponent implements OnInit {
products: Product[] = [];
dataLoaded = false;
deleteProductForm:FormGroup;
product :Product
productId :number;
constructor(private formBuilder:FormBuilder,
private productService:ProductService
, private toastrService:ToastrService
,private router:Router,
private localStorageService:LocalStorageService) { }
ngOnInit(): void {
this.createdeleteProductForm();
}
createdeleteProductForm(){
this.deleteProductForm = this.formBuilder.group({
productId:["", Validators.required],
})
}
getbyid() {
Number(localStorage)
Number(this.productService)
this.productService.getbyid(Number(localStorage.getItem("productId"))).subscribe(
(response) => {
this.products = response.data;
this.dataLoaded = true;
this.deleteProductForm.setValue({
productId: this.product,
categoryId: this.product.categoryId,
productName: this.product.productName,
unitPrice: this.product.unitPrice
});
},
(responseError) => {
this.toastrService.error(responseError.error);
}
)
}
deleteProduct() {
if (this.deleteProductForm.valid) {
let productModel = Object.assign({}, this.deleteProductForm.value);
productModel.productId=parseInt(productModel.productId);
this.productService.delete(productModel).subscribe(
(response) => {
this.toastrService.success('Lütfen tekrar giriş yapınız');
this.router.navigate(['/login']);
},
(responseError) => {
this.toastrService.error(responseError.error);
}
);
} else {
this.toastrService.error('Bir hata oluştu.');
}
}
}
these are my html codes i trying to do when user sign in a productId after that click the button delete the product in that ıd
<div class="card">
<div class="card-header"><h5 class="title">Ürün Sil</h5></div>
<div class="card-body">
<form [formGroup]="deleteProductForm">
<div class="mb-3">
<label for="productId">ÜrünId'si</label>
<div class="form-group">
<input type="number"
id="productId"
formControlName="productId" class="form-control"
placeholder="productId"/>
</div>
<div class="card-footer" style="background-color: rgb(4, 62, 255)">
<button
class="btn btn-lg btn-outline-success float-end"
(click)="deleteProduct()"
>
Sils
</button>
</div>
and these are my service
delete(product:Product):Observable<ResponseModel>{
let newPath = this.apiUrl + 'products/delete';
return this.httpClient.post<ResponseModel>(newPath, product );
}
getbyid(productId:number) : Observable<ListResponseModel<Product>> {
let newPath = this.apiUrl + 'products/getbyid?productId=' + productId;
return this.httpClient.get<ListResponseModel<Product>>(newPath);
}
what i'm going for is that when the user goes on a productId click the button, I want to delete the data including the Id first, but what's the null time on main at the moment?
note:Value cannot be null. says back-end
in html POST https://localhost:44314/api/products/delete
[HTTP/2 500 Internal Server Error 9591ms gives this error
First of all, have you checked the value of product in the call of delete ?
Also, maybe it's the httpClient.delete you need since it's the best way to delete an object to the back end. I suggest this:
https://angular.io/guide/http#making-a-delete-request

Angular: json to formBuilder to json

From my server I am receiving a json that contains questions and different options:
[
{"description":"what is a color","questionID":"1","options":[{"response":"blue","optionID":"1"},{"response":"red","optionID":"2"},{"response":"football","optionID":"3"}]},
{"description":"what is a sport","questionID":"2","options":[{"response":"working","optionID":"4"},{"response":"playing","optionID":"5"},{"response":"dad","optionID":"6"},{"response":"chess","optionID":"7"}]}
]
With the formbuilder I created a form for this:
If I press submit I would like to send this json to my server:
{
"answers": [{"questionID":"1", "selectedoptionIDS":[{"selectedOptionID":"2"}]},
{"questionID":"2", "selectedoptionIDS":[{"selectedOptionID":"1"},{"selectedOptionID":"3"}]}
],
"email": "test#test.com"
}
I know how I can build my form with the formbuilder but when I press submit I am having troubles with responding the right JSON. Certainly because I can not work with this checkboxes. Can somebody help me with this?
Html page
<form [formGroup]="examForm" (ngSubmit)="onSubmit(examForm.value)">
<div formArrayName="answers">
<div *ngFor="let question of questions; let i=index">
<label>{{i+1}}) {{question.description}}</label>
<br />
<div *ngFor="let response of question.options">
<input type="checkbox" value="response.optionID" />
{{response.response}}
</div>
</div>
</div>
<label>Email:</label>
<input class="form-control" id="email" type="text" formControlName="email">
<div class="block-content block-content-full block-content-sm bg-body-light font-size-sm">
<button class="btn btn-primary" type="submit">Submit</button>
</div>
</form>
TS Page
import { Component, OnInit } from '#angular/core';
import { ExamSimulatorService } from '../services/exam-simulator.service';
import { ActivatedRoute } from '#angular/router';
import { FormBuilder, FormArray } from '#angular/forms';
#Component({
selector: 'app-exam',
templateUrl: './exam.component.html'
})
export class ExamComponent implements OnInit {
software;
questions;
examForm;
constructor(
private examSimulatorService: ExamSimulatorService,
private formBuilder: FormBuilder
) {
this.examForm = this.formBuilder.group({
email: "",
answers: this.formBuilder.array([
this.initAnswer()])
})
}
buildForm() {
for (var i = 0; i < this.questions.length() + 1; i++) {
this.addAnswer();
}
}
initAnswer() {
return this.formBuilder.group({
questionID: "",
selectedOptionIDs: this.formBuilder.array([
this.initOptions()
])
})
}
initOptions() {
return this.formBuilder.group({
selectedOptionID: ""
})
}
addAnswer() {
const answers = <FormArray>this.examForm["controls"]["answers"];
answers.push(this.initAnswer())
console.log(this.examForm);
}
addOption(i) {
const options = <FormArray>this.examForm["controls"]["answers"]["controls"][i]["controls"]["selectedOptionIDs"]
options.push(this.initOptions())
}
ngOnInit() {
this.activatedRoute.paramMap
.subscribe(params => {
this.software = params['params']['software'];
this.examSimulatorService.getExam(this.software).subscribe(response =>
this.questions = response["questions"]["questionList"]);
})
setTimeout(() => this.buildForm(), 200)
}
onSubmit(values) {
//this.examSimulatorService.addQuestion(values).subscribe(
// (responses) => {
// console.log(responses);
// });
//this.options.clear();
console.log(values);
}
}
Instead of using your own model you can use full help from the Reactive form. The final model is not exactly you required but you can make workaround from it. You can see the working example at here https://stackblitz.com/edit/angular-1gtfmf
Component
export class ExamComponent implements OnInit {
#Input() name: string;
questionsList;
examForm: FormGroup;
dataModel: any; //active model
constructor(
private examSimulatorService: QuestionService,
private formBuilder: FormBuilder
) { }
get question(): FormGroup {
return this.formBuilder.group(
{
questionID: "",
description: "",
options: this.formBuilder.array([])
}
);
}
get option(): FormGroup {
return this.formBuilder.group({
optionID: "",
response: "",
selected: false
});
}
ngOnInit() {
this.dataModel = Object.create(null);
this.examForm = this.formBuilder.group({
email: ['', [Validators.required]],
questions: this.formBuilder.array([])
});
this.examSimulatorService.getAllQuestion().subscribe(response => {
this.questionsList = response.data;
this.loadForm(this.questionsList);
console.log(this.questionsList);
});
this.examForm.valueChanges.subscribe(data => {
this.dataModel = data;
});
}
loadForm(data) {
for (let ques = 0; ques < data.length; ques++) {
const questionsFormArray = this.examForm.get("questions") as FormArray;
questionsFormArray.push(this.question);
for (let opt = 0; opt < data[ques].options.length; opt++) {
const optionsFormsArray = questionsFormArray.at(ques).get("options") as FormArray;
optionsFormsArray.push(this.option);
}
}
this.examForm.controls.questions.patchValue(data);
}
showSavedValue() {
return this.dataModel;
}
showValue() {
return this.examForm.getRawValue();
}
onSubmit(values) {
console.log(values);
}
}
Html
<form [formGroup]="examForm" (ngSubmit)="onSubmit(examForm.value)">
<div>
<label>Email:</label>
<input class="form-control" id="email" type="text" formControlName="email">
</div>
<div formArrayName="questions">
<div *ngFor="let question of examForm.get('questions').controls;let questionIndex=index" [formGroupName]="questionIndex">
<label>{{questionIndex+1}} </label> {{examForm.value.questions[questionIndex].description}}
<div formArrayName="options">
<div *ngFor="let option of question.get('options').controls; let optionIndex=index" [formGroupName]="optionIndex">
<input type="checkbox" formControlName="selected" value="" /> {{examForm.value.questions[questionIndex].options[optionIndex].response}}
</div>
</div>
</div>
<div class="block-content block-content-full block-content-sm bg-body-light font-size-sm">
<button class="btn btn-primary" type="submit">Submit</button>
</div>
</div>
</form>
<pre> {{showSavedValue() | json }}
<pre>{{showValue() | json}}</pre>

My PUT method isn't working in angular even though it works in spring

I have a webpage that displays a logged in user information which is called from database using a spring REST API. Next to each user property there's an edit button when clicked displays an input field which the user can use to edit that property (I've only added it the password field so far).
For some reason after I click on the button and edit the property nothing happens even though it's supposed to display 'works' in the console.
Here's the spring controller method that handles the update:
#PutMapping("myProfile/edit")
public ResponseEntity<Object> updateProfile(#CurrentUser User currentUser, #RequestBody EditUserProfileRequest user){
User updatedUser = userService.updateProfile(currentUser, user);
return ResponseEntity.ok().body("Update Success!");
}
Here's the service method:
#Override
public User updateProfile(User currentUser, EditUserProfileRequest input) {
User user = this.getUserByUsername(currentUser.getUsername());
user.setEditedProfile(input);
if(input.getPassword()!=null){
user.setPassword(passwordEncoder.encode(input.getPassword()));
}
User saveMe = userRepository.save(user);
return saveMe;
}
The EditUserProfileRequest class:
package com.example.demo.contract;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
#AllArgsConstructor
#NoArgsConstructor
#Data
public class EditUserProfileRequest {
private String firstName;
private String lastName;
private String password;
private String email;
private String location;
private String bio;
private Long phoneNumber;
private Long zipCode;
}
Here's the html code for the password field which would display the normal password first then change to input fields after clicking on the edit button:
<div style="margin-top: 3px; margin-bottom: 3px;">
<h5 style="float: left; margin-left: 160px; margin-top: 18px;">
<b>Password: </b>
</h5>
<div id="hashPassword" style="display: block">
<div style="width: 100px; margin-left: 233px; float: left;">
<span style="font-weight: 600">*********</span>
</div>
<mat-icon id="hashPassword" aria-label="EDIT" aria-hidden="false" (click)="editPassword()" style="cursor: pointer; margin-left: 446px">edit</mat-icon>
</div>
<div id="editPassword" style="display: none">
<div style="width: 800px; margin-left: 233px; float: left;">
<form [formGroup]="passwordEditForm" (ngSubmit)="onPasswordSubmit()">
<div class="form-group">
<label>Password</label>
<input type="password" formControlName="password" class="form-control" [ngClass]="{ 'is-invalid': submitted && f.password.errors }" />
<div *ngIf="submitted && f.password.errors" class="invalid-feedback">
<div *ngIf="f.password.errors.required">Password is required</div>
<div *ngIf="f.password.errors.minlength">Password must be at least 4 characters</div>
</div>
</div>
<div class="form-group">
<label>Confirm Password</label>
<input type="password" formControlName="confirmPassword" class="form-control" [ngClass]="{ 'is-invalid': submitted && f.confirmPassword.errors }" />
<div *ngIf="submitted && f.confirmPassword.errors" class="invalid-feedback">
<div *ngIf="f.confirmPassword.errors.required">Confirm Password is required</div>
<div *ngIf="f.confirmPassword.errors.mustMatch">Passwords must match</div>
</div>
</div>
<div class="form-group">
<button type="button" class="btn btn-primary">Confirm Edit</button>
</div>
</form>
</div>
</div>
</div>
Here's my my component that handles the calls the edit function:
import { Component, OnInit, ChangeDetectorRef, OnDestroy } from '#angular/core';
import { FormGroup, FormBuilder, Validators } from '#angular/forms';
import { MediaMatcher } from '#angular/cdk/layout';
import { Router } from '#angular/router';
import { DomSanitizer } from '#angular/platform-browser';
import { Observable } from 'rxjs';
import { HttpHeaders, HttpClient } from '#angular/common/http';
import { MustMatch } from '../must-match.validators';
import { UserService } from '../user.service';
#Component({
selector: 'app-myacc',
templateUrl: './myacc.component.html',
styleUrls: ['./myacc.component.scss']
})
export class MyaccComponent implements OnInit {
loginUser: any = {};
imgSrc: any;
submitted = false;
passwordEditForm: FormGroup;
constructor(private router: Router,
private sanitizer: DomSanitizer,
private http: HttpClient,
private fb: FormBuilder,
private service: UserService) {
}
ngOnInit() {
console.log(window.URL);
this.loginUser = JSON.parse(localStorage.getItem('currentUser'));
console.log(this.loginUser);
this.passwordEditForm = this.fb.group({
password: ['', [Validators.required, Validators.minLength(4)]],
confirmPassword: ['', Validators.required]
}, {
validator: MustMatch('password', 'confirmPassword')
});
}
editPassword() {
document.getElementById('hashPassword').style.display = 'none';
document.getElementById('editPassword').style.display = 'block';
}
get f() {
return this.passwordEditForm.controls;
}
onPasswordSubmit() {
this.submitted = true;
if (this.passwordEditForm.invalid) {
return;
} else {
this.service.editUser(this.passwordEditForm.value, this.loginUser.token).subscribe(res => {
console.log('works');
}, err => {
console.log(err);
});
}
}
}
And finally the User service that has the edit method:
import { Injectable } from '#angular/core';
import { HttpClient, HttpHeaders } from '#angular/common/http';
import { Observable } from 'rxjs';
#Injectable({
providedIn: 'root'
})
export class UserService {
constructor(private http: HttpClient) {
this.http = http;
}
getAllUsers(token: any): Observable<any> {
// tslint:disable-next-line: object-literal-key-quotes
const headers = new HttpHeaders({'Authorization': 'Bearer ' + token});
return this.http.get('http://localhost:8082/users', {headers: headers});
}
getUser(token: any): Observable<any> {
// tslint:disable-next-line: object-literal-key-quotes
const headers = new HttpHeaders({'Authorization': 'Bearer ' + token});
return this.http.get('http://localhost:8082/getuser', {headers: headers});
}
getAllOffer(): Observable<any> {
return this.http.get('http://localhost:8082/getAllOffer');
}
getServices(): Observable<any> {
return this.http.get('http://localhost:8082/services');
}
editUser(user, token): Observable<any> {
const headers = new HttpHeaders({'Authorization': 'Bearer ' + token});
return this.http.put('http://localhost:8082/myProfile/edit', user, token);
}
}
The third argument of HttpClient.put() should be an options object. Update your editUser method so that you are passing an object containing your headers as the third argument instead of token:
editUser(user, token): Observable<any> {
const headers = new HttpHeaders({'Authorization': 'Bearer ' + token});
return this.http.put('http://localhost:8082/myProfile/edit', user, { headers });
}
Hopefully that helps!

Angular 4 : How to use pattern in an input list

I have a form html and the button submit becomes enable only when the form is valid. That is, when a particular input contains the recommended pattern. I need to use this pattern in an inputlist. It works with a simple input but with the input list, the list disappears :
<input list="refNumbers" pattern="[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]" formControlName="refNb" type="text" name="article" maxlength="8" size="15" required title="8 characters" />
<datalist id="refNumbers">
<option *ngFor="let ref of listOfArticles">{{ref.refNumber.input}}</option>
</datalist>
Otherwise, how can i disable button submit if the ref number selected is not in the datalist ? Because it seems that the valid condition on the form is not enough :
<button type="submit" [disabled]="!myFormGroup.valid" >Valider</button>
component.ts :
import { Component, OnInit } from '#angular/core';
import 'rxjs/add/operator/switchMap';
import { ManagementArbologistiqueService } from "../management-arbologistique.service";
import { ActivatedRoute, Params } from '#angular/router';
import { FormGroup, FormControl, FormBuilder, FormArray, Validators } from '#angular/forms';
#Component({
selector: 'app-arbologistique',
templateUrl: './arbologistique.component.html',
styleUrls: ['./arbologistique.component.css']
})
export class ArbologistiqueComponent implements OnInit {
private reponseTest: String;
private listOfArticles :Array<Object>
private pathDownload: any;
private myFormGroup: FormGroup;
fileToUpload: File = null;
private buttonSubmitEnabled: boolean = false;
constructor(public fb: FormBuilder, private managementArbo: ManagementArbologistiqueService, private route: ActivatedRoute) { }
ngOnInit() {
this.myFormGroup = this.fb.group({
itemRows: this.fb.array([this.initItemRows()])
})
this.myFormGroup.valueChanges.subscribe(x => this.buttonSubmitEnabled = false);
this.getListBdd();
}
initItemRows() {
return this.fb.group({
... //other fields
refNb: ['',Validators.required],
... //other fields
})
}
addRow(index: number) {
console.log("functionAddRow called");
const control = <FormArray>this.myFormGroup.controls['itemRows'];
control.insert(index, this.initItemRows());
}
deleteRow(index: number) {
console.log("functionDeleteRow called");
const control = <FormArray>this.myFormGroup.controls['itemRows'];
control.removeAt(index);
}
sendForm() {
this.buttonSubmitEnabled=true;
console.log("functionExportCalled");
this.route.params.subscribe((params: Params) => {
let subroute = "exportation";
this.managementArbo.postProducts(subroute, JSON.stringify(this.myFormGroup.value))
.subscribe(
res => { this.reponseTest = res; console.log('reponse:' + res); }
,
err => console.log(err),
() => console.log('getProducts done'));
});
}
getListBdd() {
this.route.params.subscribe((params: Params) => {
let subroute = "getRefNumber";
this.managementArbo.getProducts(subroute)
.subscribe(
res => { this.listOfArticles = res; console.log('reponse:' + res); }
,
err => console.log(err),
() => console.log('getProducts done'));
});
}
get refNb() {
return this.myFormGroup.get('itemRows.refNb');
}
}
If you want to add Validation in reactive form you can use build in Validators
initItemRows() {
const regEx="[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]";
return this.fb.group({
... //other fields
refNb: ['',Validators.required,Validators.pattern(regEx)],
... //other fields
})
}
<button type="submit" [disabled]="!myFormGroup.valid" >Valider</button>

How to rerun a ngFor loop after its variable's value has been changed in the component?

I'm trying to make a Github Search app and have used a ngFor loop to display search data. As I type the value the value of UARR changes but no changes are made to the DOM.
Initially also as I enter one character it show the result instantly but subsequent keydowns have no effect on the HTML DOM. I'm confused and looked everywhere for an answer but it was of no avail.
How can I possibly rerun ngFor loop each time the value of uarr changes?
<div class="row">
<div class="col-md-12">
<form>
<div class="form-group">
<input type="text" class="form-control" [(ngModel)]="username" name="username" (keyup)="searchUser()" >
</div>
</form>
</div>
</div>
<div *ngIf="uarr" >
<ul *ngFor="let data of uarr" class="list-unstyled" >
<li>
<div class="col-sm-6 col-md-4">
<div class="thumbnail">
<a href="#" >
<img class="github-avatar" src="{{data.avatar_url}}" >
</a>
<div class="caption">
<h3 class="text-center">{{ data.login }}</h3>
</div>
</div>
</div>
</li>
</ul>
</div>
The componentcode:
import { Component } from '#angular/core';
import { GithubService } from '../services/git.services';
import { map } from 'rxjs/operators';
//import { user } from '../models/gitusers';
#Component({
selector: 'searchform',
templateUrl: 'search.component.html',
providers:[GithubService]
})
export class SearchformComponent {
users : any;
uarr: any[] = [];
username: string;
// #Output() userUpdated: EventEmitter<user> = new EventEmitter<user>();
constructor(private _githubService: GithubService) {
}
searchUser() {
this._githubService.updateUser(this.username);
console.log(this.username);
this._githubService.getUser().subscribe(user => {
this.users = user.items;
for (var i in this.users) {
this.uarr.push(this.users[i]); }
});
console.log(this.uarr);
}
/*
ngOnInit() {
if (this.user) {
this.user.user = false;
this.getUserInformation();
}
}
getUserInformation() {
if (this.user.userName && this.user.userName.length > 0) {
this._githubService.getUser().subscribe(user => {
this.user.user = user;
// this.userUpdated.emit(this.user);
},
(err) => {
console.log('err:' + err);
this.user.user = false;
},
() => console.log('Done')
);
this._githubService.getRepos().subscribe(repos => {
// console.log(repos);
this.user.repos = repos;
// this.userUpdated.emit(this.user);
},
(err) => {
console.log('err:' + err);
this.user.user = false;
},
() => console.log('Done')
);
}
}*/
}
The Services Code:
import { Injectable } from '#angular/core';
import { Http, Headers } from '#angular/http';
import { Observable, throwError } from 'rxjs';
import { map, catchError } from 'rxjs/operators';
import { environment } from '../../environments/environment';
const API_URL = environment.apiUrl;
#Injectable()
export class GithubService {
private userName = "matt";
private client_id = '3198278eb6fb7788fa1e';
private client_secret = 'd6b3cf6265f7997f110ec1450246e7157d055a8f';
constructor(private _http: Http) {
console.log('Github Service Ready.');
}
getUser() {
if (this.userName) {
return this._http.get(API_URL + this.userName + '&client_id=' + this.client_id + '&client_secret=' + this.client_secret)
.pipe(
map(res => res.json()),
catchError(this.handleError));
}
}
getRepos() {
if (this.userName) {
return this._http.get(API_URL + this.userName + '/repos')
.pipe(
map(res => res.json()),
catchError(this.handleError));
}
}
updateUser(username: string) {
this.userName = username;
console.log(this.userName);
}
private handleError(error: any) {
if (error.status === 401) {
return Observable.throw(error.status);
} else {
return Observable.throw(error.status || 'Server error');
}
}
}
Some of the functions in the services are redundant and for future use.
Should I remove the Exception handling code to decrease the size of the app.
Thank You.