ReactiveForms with custom input - angular5

I'm getting the following error when trying to create a form using a custom component.
Error: No value accessor for form control with name:
'nomeEmpresaAerea'
Error: No value accessor for form control with name: 'nomeEmpresaAerea'
Stack trace:
_throwError#webpack-internal:///./node_modules/#angular/forms/esm5/forms.js:2510:11
setUpControl#webpack-internal:///./node_modules/#angular/forms/esm5/forms.js:2380:9
FormGroupDirective.prototype.addControl#webpack-internal:///./node_modules/#angular/forms/esm5/forms.js:6736:9
FormControlName.prototype._setUpControl#webpack-internal:///./node_modules/#angular/forms/esm5/forms.js:7386:45
FormControlName.prototype.ngOnChanges#webpack-internal:///./node_modules/#angular/forms/esm5/forms.js:7299:13
checkAndUpdateDirectiveInline#webpack-internal:///./node_modules/#angular/core/esm5/core.js:12581:9
checkAndUpdateNodeInline#webpack-internal:///./node_modules/#angular/core/esm5/core.js:14109:20
checkAndUpdateNode#webpack-internal:///./node_modules/#angular/core/esm5/core.js:14052:16
debugCheckAndUpdateNode#webpack-internal:///./node_modules/#angular/core/esm5/core.js:14945:55
debugCheckDirectivesFn#webpack-internal:///./node_modules/#angular/core/esm5/core.js:14886:13
View_EmpresaCadastroComponent_0/<#ng:///EmpresaModule/EmpresaCadastroComponent.ngfactory.js:80:5
debugUpdateDirectives#webpack-internal:///./node_modules/#angular/core/esm5/core.js:14871:12
checkAndUpdateView#webpack-internal:///./node_modules/#angular/core/esm5/core.js:14018:5
callViewAction#webpack-internal:///./node_modules/#angular/core/esm5/core.js:14369:21
this is my reactive form:
import { Component, OnInit, Input } from '#angular/core';
import { Router } from '#angular/router';
import { HttpClient } from '#angular/common/http';
import { FormArray, FormBuilder, FormGroup, Validators } from '#angular/forms';
#Component({
selector: 'app-empresa-cadastro',
templateUrl: './empresa-cadastro.component.html',
styleUrls: ['./empresa-cadastro.component.css']
})
export class EmpresaCadastroComponent implements OnInit {
#Input() empresa = {};
empresaForm: FormGroup;
constructor(private route: Router, private http: HttpClient, private fb: FormBuilder) {
this.createForm();
}
createForm() {
this.empresaForm = this.fb.group({
nomeEmpresaAerea: '',
status: 'S',
});
}
this is my html:
<form [formGroup]="empresaForm" (ngSubmit)="onSubmit()">
<div style="margin-bottom: 1em">
<button type="submit" [disabled]="empresaForm.pristine" class="btn btn-success">Cadastrar</button>
<button type="button" (click)="limpar()" [disabled]="empresaForm.pristine" class="btn btn-danger">Limpar</button>
</div>
<div class="form-group">
<label class="center-block">Nome:
<input class="form-control" >
<app-pf-input-text formControlName="nomeEmpresaAerea" ></app-pf-input-text>
</label>
</div>
</form>
pf-input-text.componente.ts:
import { Component, OnInit, Input } from '#angular/core';
#Component({
selector: 'app-pf-input-text',
templateUrl: './pf-input-text.component.html',
styleUrls: ['./pf-input-text.component.scss']
})
export class PfInputTextComponent implements OnInit {
#Input() id: string;
#Input() name: string;
#Input() value: string;
#Input() placeholder: string;
//falta trim
#Input() maxlength: string;
#Input() minlength: string;
#Input() disabled: boolean;
#Input() required: boolean;
constructor() { }
ngOnInit() {
}
}
pf-input-text.component.html
<div class="input-group">
<input
type="text"
id="{{id}}"
name="{{name}}"
placeholder="{{placeholder}}"
attr.maxlength="{{maxlength}}"
class="form-control"
disabled="{{disabled}}"
required="{{required}}">
</div>

try this in reactive form component
this.empresaForm = new FormGroup({
'nomeEmpresaAerea': new FormControl(null, Validators.required)});

Related

The page is showing some error with Reactve components

<input type="text" name="" id=""
class="form-control" [formControl]='fname'
placeholder="Enter your name">
and this is the error i am getting
ERROR in src/app/myform/myform.component.html:12:54 - error TS2339: Property 'fname' does not exist on type 'MyformComponent'.
12 class="form-control" [formControl]='fname'
~~~~~
src/app/myform/myform.component.ts:9:16
9 templateUrl: './myform.component.html',
~~~~~~~~~~~~~~~~~~~~~~~~~
Error occurs in the template of component MyformComponent.
try this:
Typescript
import { Component } from '#angular/core';
import { FormGroup,FormControl } from '#angular/forms';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
form = new FormGroup({
fname : new FormControl(''),
});
onsubmit(){
//submit button
}
}
HTML
<form [formGroup]="form" (ngSubmit)="onSubmit()">
<label>
Name:
<input type="text" formControlName="fname" placeholder="Enter your fname">
</label>
</form>
app.module.ts //module
import { FormsModule,ReactiveFormsModule } from '#angular/forms';
On your typescript you need to add the following function to get the value from your form:
get fname(){
return this.formName.get('fname')
}

Set value programmatically ng-select

[items] : {id: number, label: string }[]
[bindValue]: id
[bindLabel]: label
([ngModel)] : number[]
I want to bind default data but there is no label.(picture)
And if i change bindValue to label then these square will show up the label
Manually selecting works fine.
i add this line of code to add default selected items
this.heroForm.get('selectedCitiesIds').patchValue([1,2]);
check this example
<form [formGroup]="heroForm">
<div class="form-group">
<label for="state">City</label>
<ng-select *ngIf="isCitiesControlVisible"
[items]="cities"
bindLabel="name"
bindValue="id"
labelForId="state"
[multiple]="true"
placeholder="Select cities"
clearAllText="Clear"
formControlName="selectedCitiesIds">
</ng-select>
<br>
<button (click)="toggleCitiesControl()" class="btn btn-sm btn-secondary">Show/Hide</button>
<button (click)="clearCities()" class="btn btn-sm btn-secondary">Clear</button>
</div>
</form>
and
import { Component, OnInit } from '#angular/core';
import { FormBuilder, FormGroup } from '#angular/forms';
#Component({
selector: 'forms-multi-select-example',
templateUrl: './forms-multi-select-example.component.html',
styleUrls: ['./forms-multi-select-example.component.scss']
})
export class FormsMultiSelectExampleComponent implements OnInit {
heroForm: FormGroup;
isCitiesControlVisible = true;
cities: any[] = [
{ id: 1, name: 'Vilnius' },
{ id: 2, name: 'Kaunas' },
{ id: 3, name: 'Pavilnys (Disabled)', disabled: true },
{ id: 4, name: 'Pabradė' },
];
constructor(private fb: FormBuilder) {
}
ngOnInit() {
this.heroForm = this.fb.group({
selectedCitiesIds: []
});
this.heroForm.get('selectedCitiesIds').patchValue([1,2]);
}
toggleCitiesControl() {
this.isCitiesControlVisible = !this.isCitiesControlVisible;
}
clearCities() {
this.heroForm.get('selectedCitiesIds').patchValue([]);
}
}

Angular 8 - Form Group Values are always empty

Am new to angular and am starting off with a simple login form. However the form values are always showing up as empty - even if values have been entered before form submission.
I have created a login component which is imported in app module. The page comes up, but the submission does not carry any values. I have removed all Angular validation checks for debugging but the values received in my onsubmit function are still empty.
I have pasted the component code.Below.
login.component.html
<form [formGroup]="loginForm" (ngSubmit)="onSubmit()">
<div class="form-group" >
<div class="form-group">
<input type="email" class="form-control" formcontrolname="username"
placeholder="Email Id" required autofocus/><br/>
</div>
<div class="form-group">
<input type="password" class="form-control" formcontrolname="password" placeholder="Password" required/><br/>
</div>
<div class="form-group">
<button>Login</button>
<a href="/public/register" class="btn" >Register</a>
</div>
app.component
import { NgModule } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { FormsModule, ReactiveFormsModule } from '#angular/forms';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { LoginComponent } from './login/login.component';
#NgModule({
imports: [ BrowserModule, AppRoutingModule, FormsModule,
ReactiveFormsModule ],
declarations: [ AppComponent, HelloComponent, LoginComponent ],
bootstrap: [ AppComponent ]
})
export class AppModule { }
login.component.ts
import { Component, OnInit } from '#angular/core';
import { Router } from '#angular/router';
import { FormBuilder, FormGroup, Validators } from '#angular/forms';
#Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
loginForm: FormGroup;
submitted = false;
returnUrl = '';
constructor(
private formBuilder: FormBuilder,
private router: Router
) {
}
ngOnInit() {
this.loginForm = this.formBuilder.group ({
username: ['', Validators.required],
password: ['', Validators.required]
});
}
get user() { return this.loginForm.controls; }
onSubmit() {
// stop if form is invalid
/* if (this.loginForm.invalid) {
console.log("Returning");
return;
} */
this.submitted = true;
console.log('login values:');
console.log(this.user.username.value, this.user.password.value);
this.returnUrl='/home';
// this.router.navigate([this.returnUrl]);
}
}
You can try this:
get user() { return this.loginForm.value; }
Knew it would be something super silly and trivial - turned out to be a case sensitivity problem issue on my end. Changed 'formcontrolname' to 'formControlName' and it started working! Duh!

input not beign validated by form

I created an input component to reuse it between a few forms. In one of then, it's working perfectly, but in the other, it's not.
It doesn't throw any erros. I even receive the input value after submit.
code.component.html
<div [ngClass]="aplicaCssErro(ag)">
<label for="code">Code</label>
<input id="code" name="code" type="text" class="form-control" [(ngModel)]="value" required #ag="ngModel"
maxlength="4" minlength="4" (blur)="formatCode(ag)">
<div *ngIf="verificaValidTouched(ag)" class="msgErroText">
<gce-campo-control-erro [mostrarErro]="ag?.errors?.required" msgErro="the code is required">
</gce-campo-control-erro>
</div>
code.component.ts
import { Component, OnInit, Input } from '#angular/core';
#Component({
selector: 'gce-input-code',
templateUrl: './input-code.component.html',
styleUrls: ['./input-code.component.scss']
})
export class InputCodeComponent implements OnInit {
#Input() value: string = "";
constructor() { }
ngOnInit() {
}
//some functions
}
form.component.html
The problem is that the form is not validating it, just the first input.
I think the form is not recognizing it as one of it's inputs.
<form (ngSubmit)="onSubmitForm2(f)" #f="ngForm">
<div class="row">
<div class="col-sm-6" [ngClass]="aplicaCssErro(apelido)">
<label for="apelido">Apelido da conta</label>
<input id="apelido" name="apelido" type="text" class="form-control" alt="Apelido" [(ngModel)]="conta.apelido" required #apelido="ngModel">
<div *ngIf="verificaValidTouched(apelido)" class="msgErroText">
<gce-campo-control-erro [mostrarErro]="apelido?.errors?.required" msgErro="O Apelido é obrigatório.">
</gce-campo-control-erro>
</div>
</div>
</div>
<div class="row">
<div class="form-group">
<div class="col-sm-2">
<gce-input-code name="code" [(ngModel)]="user.code" #code="ngModel" ngDefaultControl></gce-input-code>
</div>
</div>
</div>
<div class="row">
<button class="btn btn-default" name="btn2" type="submit" alt="Continuar" [disabled]="!f.valid">Continue</button>
</div>
Any help?
If I understand your question correctly. You are trying to make it so the form(ngForm) can validate the custom component that wraps around the input(gce-input-code).
A normal form does not have any way to know what is going in/out of the component as it is Angular component. You would have to enhance your code.component.ts to include all the connectors (ControlValueAccessor, NG_VALUE_ACCESSOR, NG_VALIDATORS) into it.
Checkout this blog
https://blog.thoughtram.io/angular/2016/07/27/custom-form-controls-in-angular-2.html#custom-form-control-considerations
and its plnkr(exerpt code below)
https://plnkr.co/edit/6xVdppNQoLcsXGMf7tph?p=info
import { Component, OnInit, forwardRef, Input, OnChanges } from '#angular/core';
import { FormControl, ControlValueAccessor, NG_VALUE_ACCESSOR, NG_VALIDATORS }
from '#angular/forms';
export function createCounterRangeValidator(maxValue, minValue) {
return (c: FormControl) => {
let err = {
rangeError: {
given: c.value,
max: maxValue || 10,
min: minValue || 0
}
};
return (c.value > +maxValue || c.value < +minValue) ? err: null;
}
}
#Component({
selector: 'counter-input',
template: `
<button (click)="increase()">+</button> {{counterValue}} <button (click)="decrease()">-</button>
`,
providers: [
{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => CounterInputComponent), multi: true },
{ provide: NG_VALIDATORS, useExisting: forwardRef(() => CounterInputComponent), multi: true }
]
})
export class CounterInputComponent implements ControlValueAccessor, OnChanges {
propagateChange:any = () => {};
validateFn:any = () => {};
#Input('counterValue') _counterValue = 0;
#Input() counterRangeMax;
#Input() counterRangeMin;
get counterValue() {
return this._counterValue;
}
set counterValue(val) {
this._counterValue = val;
this.propagateChange(val);
}
ngOnChanges(inputs) {
if (inputs.counterRangeMax || inputs.counterRangeMin) {
this.validateFn = createCounterRangeValidator(this.counterRangeMax, this.counterRangeMin);
this.propagateChange(this.counterValue);
}
}
writeValue(value) {
if (value) {
this.counterValue = value;
}
}
registerOnChange(fn) {
this.propagateChange = fn;
}
registerOnTouched() {}
increase() {
this.counterValue++;
}
decrease() {
this.counterValue--;
}
validate(c: FormControl) {
return this.validateFn(c);
}
}

aurelia: binding and #observable not working

I don't get why this "property changed" via #observable is not working, the stringValueChanged() method doesn't get called. What am I missing here? (The whole binding is not working here.)
currency-control.ts
import { bindable, observable } from 'aurelia-framework';
export class CurrencyControl {
#bindable
value: number;
#observable
stringValue: string;
constructor() {
}
valueChanged(newValue: number, oldValue: number) {
alert('value changed');
}
stringValueChanged(newValue: string, oldValue: string) {
alert('stringValueChanged changed');
}
}
currency-control.html
<template>
<require from="./currency-control.css"></require>
<div class="input-group">
<div class="input-group-addon">€</div>
<input type="text" maxlength="5" pattern="\d*" class="form-control" value.bind="stringValue" />
</div>
</template>
My fault! In the component that uses the CurrencyControl I required the CurrencyControl's html:
<template>
<require from="../currency-control/currency-control.html"></require>
instead of the component:
<template>
<require from="../currency-control/currency-control"></require>