How to bind form input to object? - forms

I have the following form:
<form role="form" [ngFormModel]="userEditForm" (ngSubmit)="editUser(user)">
<div>
<label for="username">Username</label>
<input type="text" #username id="username" placeholder="Username" [ngFormControl]="userEditForm.controls['username']">
</div>
<div>
<label for="firstName">First Name</label>
<input type="text" #firstName id="firstName" placeholder="First Name" [ngFormControl]="userEditForm.controls['firstName']">
</div>
<div>
<label for="lastName">Last Name</label>
<input type="text" #lastName id="lastName" placeholder="Last Name" [ngFormControl]="userEditForm.controls['lastName']">
</div>
<div>
<label for="email">Email</label>
<input type="text" #email id="email" placeholder="Email" [ngFormControl]="userEditForm.controls['email']">
</div>
<button type="submit">Submit</button>
And in my component I have defined:
constructor(private _routeParams:RouteParams, private _formBuilder:FormBuilder, private _UserInject:UserInject){
this.userEditForm = _formBuilder.group({
'firstName': [this.user.firstName],
'lastName': [this.user.lastName],
'username': [this.user.username],
'email': [this.user.email],
})
}
ngOnInit(){
let id = this._routeParams.get('userId');
this.user = this._UserInject.getUser(id);
}
}
However, this creates an error, because this.user is not yet defined in the constructor. Any ideas?
UPDATE
It works when I use formBuilder in the ngOnInit - however, I am not sure if thats a proper way to do it.

Just move
this.userEditForm = _formBuilder.group({
'firstName': [this.user.firstName],
'lastName': [this.user.lastName],
'username': [this.user.username],
'email': [this.user.email],
})
after the code where you assign this.user (into ngOnInit())

Related

How to upload the image in storage from flask

i have stored these form field in firestore and i need to store the image file to Storage but i have been getting error. i need to save the image to storage from the HTML code. here is the html code below,
if request.method == "POST":
client_id = request.form["clientId"]
first_name = request.form["firstName"]
last_name = request.form["lastName"]
image = request.files["image"]
client = {
"clientId": client_id,
"firstName": first_name,
"lastName": last_name,
"image": image
}
try:
db.collection('clients').document(client_id).set(client)
return redirect("/addclient")
except:
return render_template("/add_client.html", message="Something went wrong")
return render_template("/add_client.html")
<form method="post" class="col-3">
<div class="mb-3">
<label for="clientId" >Client ID</label>
<input type="text" class="form-control" name="clientId"
placeholder="Client ID" required>
</div>
<div class="mb-3">
<label for="firstName" >First Name</label>
<input type="text" class="form-control" name="firstName"
placeholder="Client's First name" required>
</div>
<div class="mb-3">
<label for="lastName" >Last Name</label>
<input type="text" class="form-control" name="lastName"
placeholder="Client's Last name" >
</div>
<div class="mb-3">
<label class="image" for="image">Upload a Client's Photo</label>
<input type="file" class="form-control" name="image" accept="image/*" />
</div>
<div class="mb-3">
<button type="submit" class="btn btn-warning text-white font-weight-bold w-100 mt-2">
Register Client
</button>
</div>
</form>

Add inputs dynamically according to the choice of radio button

I am using the following code, which is intended to show two inputs after choosing according to the selected radio button.
Only I may have to include it several times, dynamically.
And when I add dynamically, radio buttons appear, but when selecting one, the inputs do not appear.
Would I have to reset the javascript to use it again?
$(document).ready(function() {
$('input:radio[name="radiocpfcnpj"]').on("change", function() {
if (this.checked && this.value == 'cpf') {
$("#cpfParteProcesso").show();
$("#cnpjParteProcesso").hide();
$("#cpfParteProcessoNome").show();
$("#cnpjParteProcessoNome").hide();
$("#add_interessado").show();
} else {
$("#cnpjParteProcesso").show();
$("#cpfParteProcesso").hide();
$("#cnpjParteProcessoNome").show();
$("#cpfParteProcessoNome").hide();
$("#add_interessado").show();
}
});
});
$(document).ready(function(e) {
//Variáveis
var html = '<div class="form-group"><label for="cpfParteProcesso">CPF/CNPJ da parte<small class="text-muted"> (escolha a opção)</small></label><div class="form-check"><input class="form-check-input" type="radio" id="cpfProcessoFilho" name="radiocpfcnpj" value="cpf"><label class="form-check-label">CPF</label><input class="form-check-input" type="radio" id="cnpjProcessoFilho" name="radiocpfcnpj" value="cnpj"><label class="form-check-label">CNPJ</label></div><input type="text" class="form-control cpfcnpj" id="cpfParteProcessoFilho" name="cpfParteProcesso" data-mask><input type="text" class="form-control cpfcnpj" id="cnpjParteProcessoFilho" name="cnpjParteProcesso" data-mask><button id="add_interessado" type="button" class="btn btn-primary btn-sm interessado">Remover</button></div>';
//Adicionar linhas
$("#add_interessado").click(function(e){
$("#dadoscpfcnpj").append(html);
$("#cpfParteProcesso").append(html);
$("#cpfParteProcessoNome").append(html);
$("#cnpjParteProcesso").append(html);
$("#cnpjfParteProcessoNome").append(html);
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="dadoscpfcnpj" class="form-group">
<label for="cpfParteProcesso">CPF/CNPJ da parte<small class="text-muted"> (escolha a opção)</small></label>
<div id="dadoscpfcnpj" class="form-group form-check">
<input class="form-check-input" type="radio" id="cpfProcesso" name="radiocpfcnpj" value="cpf">
<label class="form-check-label">CPF</label>
<input class="form-check-input" type="radio" id="cnpjProcesso" name="radiocpfcnpj" value="cnpj">
<label class="form-check-label">CNPJ</label>
</div>
<input type="text" class="form-control cpfcnpj" id="cpfParteProcesso" name="cpfParteProcesso" data-mask>
<input type="text" class="form-control cpfcnpj" id="cpfParteProcessoNome" name="cpfParteProcessoNome" >
<input type="text" class="form-control cpfcnpj" id="cnpjParteProcesso" name="cnpjParteProcesso" data-mask>
<input type="text" class="form-control cpfcnpj" id="cnpjParteProcessoNome" name="cnpjParteProcessoNome">
<button id="add_interessado" type="button" class="btn btn-primary btn-sm interessado" value="cpf">Adicionar interessado</button>
</div>
</div>
`

How to use formControlName and deal with nested formGroup?

As Angular documentation says we can use formControlName in our forms:
<h2>Hero Detail</h2>
<h3><i>FormControl in a FormGroup</i></h3>
<form [formGroup]="heroForm" novalidate>
<div class="form-group">
<label class="center-block">Name:
<input class="form-control" formControlName="name">
</label>
</div>
</form>
As they say...
Without a parent FormGroup, [formControl]="name" worked earlier because that directive can stand alone, that is, it works without being in a FormGroup. With a parent FormGroup, the name input needs the syntax formControlName=name in order to be associated with the correct FormControl in the class. This syntax tells Angular to look for the parent FormGroup, in this case heroForm, and then inside that group to look for a FormControl called name.
Anyway some months ago I asked this to figure out what is the difference between formControlName and [formControl].
Now my question is: what about use formControlName with nested FormGroups?
For example, if I have the following form structure:
this.myForm = fb.group({
'fullname': ['', Validators.required],
'gender': [],
'address': fb.group({
'street': [''],
'houseNumber': [''],
'postalCode': ['']
})
});
What is the right way to bind "street" (or "houseNumber" or "postalCode") to related HTML elements using formControlName?
you can use Form group which is basically a collection of controls ( controls mean the fields given in your html form) define in your typescript syntax and binded to your HTML elements using the formControlName directive ,for example
this.myForm = fb.group({
'fullname': ['', Validators.required],
'gender': [],
'address': fb.group({
'street': [''],
'houseNumber': [''],
'postalCode': ['']
})
});
Template:
<form [formGroup]="myForm" >
<div class="form-group">
<label for="fullname">Username</label>
<input type="text" id="username" formControlName="fullname" class="form-control">
</div>
<div class="radio" *ngFor="let gender of genders">
<label>
<input type="radio" formControlName="gender" [value]="gender">{{ gender }} </label>
</div>
<div formGroupName="address">
<div class="form-group">
<label for="street">Username</label>
<input type="text" id="username" value="street" formControlName="street" class="form-control">
</div>
<div class="form-group">
<label for="houseNumber">Username</label>
<input type="text" id="username" value="street" formControlName="houseNumber" class="form-control">
</div>
<div class="form-group">
<label for="postalCode">Username</label>
<input type="text" id="username" value="street" formControlName="postalCode" class="form-control">
</div>
</div>
</form>
A formGroup can consist of a nested formGroup and hierarchy can continue on ,but in accessing the value the its fairly simple .
It is true. Look at formGroupName
this.myForm = fb.group({
'fullname': ['', Validators.required],
'gender': [],
'address': fb.group({
'street': [''],
'houseNumber': [''],
'postalCode': ['']
})
});
<form [formGroup]="myForm" >
<div class="form-group">
<label for="fullname">Username</label>
<input type="text" id="username" formControlName="fullname" class="form-control">
</div>
<div class="radio" *ngFor="let gender of genders">
<label>
<input type="radio" formControlName="gender" [value]="gender">{{ gender }} </label>
</div>
<div formGroupName="address">
<div class="form-group">
<label for="street">Username</label>
<input type="text" id="username" value="street" formControlName="street" class="form-control">
</div>
<div class="form-group">
<label for="houseNumber">Username</label>
<input type="text" id="username" value="street" formControlName="houseNumber" class="form-control">
</div>
<div class="form-group">
<label for="postalCode">Username</label>
<input type="text" id="username" value="street" formControlName="postalCode" class="form-control">
</div>
</div>
</form>
tl;dr:
You can break your form up into components that use your nested formgroups, and formcontrolname can be used as normal.
The approach I tend to use, since usually nested Formgroups are used to designate separate parts of a form, is to break it up into components and pass those components the nested formgroup as an input parameter.
So in your case, I would have an address component that takes a formgroup as a parameter:
<app-address [formGroup]="myForm.get('address')"></app-address
And inside of that component, I would just have an #Input() formGroup that would be used in the html:
<div [formGroup]="formGroup">
....
That way you can reference the control name explicitly as you normally would, since it would be part of this formgroup.
Also, keep in mind the form is passed as reference. your changes would be accounted for in the parent component's myForm element, and if you needed access to parts of the form not in you formgroup (validation, change detection, ect ect) you could always pass down the whole form and just define the formgroup to reference the inner group explicitly:
<div [formGroup]="formGroup.get('adress')">
(assuming you pass down the entire form object that is
Happy coding!
I am struggling with a problem in Angular 10.
I have a "parent" form group "forma" who has a few dependent groups: "company", and at the same time, "company" has two
"children" with another groups, msgAccounts and socialMedia.
When I fill the form and I submit it, in the backend everything is correct, I can see how these data is stored in the db
correctly, but when I receive this json I cannot display the data
inside "company.msgAccounts" and "company.socialMedia" in the controls
(inputs). This is what I get from the server:
{
name:'',
active: '',
........
company:{
msgAccounts:{line: "#linedemo", whatsapp: "0325554244"},
socialMedia: {fb: '', tw: '', is: ''}
}
..........
}
this.forma = this.fb.group( {
siteName : [ '', [Validators.required, Validators.minLength(5)]],
siteEmail : [ '', [Validators.required, Validators.minLength(5)]],
// defaultLocation: [ '', [Validators.required, Validators.minLength(10)]],
active : [ true, [Validators.required, Validators.minLength(5)]],
mainLanguage: ['' , [Validators.required, Validators.minLength(2)]],
company: this.fb.group({
name: [''],
address: [''],
phone: [''],
msgAccounts: this.fb.group({
line: [],
whatsapp: []
}),
socialMedia: this.fb.group({
fb: [],
is: [],
tw: []
})
})
});
And the html: (Sorry about the indentation, when it was not easy using this editor, and I just pasted a part of the code in order to do it as shorter as possible).
<mat-tab-group>
<mat-tab label="settings">
<form autocomplete="off" >
<ng-template ng-template matTabContent>
<mat-tab-group [formGroup]="forma">
<mat-tab label="global">
// All this fields have are fine
</mat-tab>
<mat-tab formGroupName="company" label="company">
<div class="card">
<div class="card-header" id="headingTwo">
<h5 class="mb-0">Details</h5>
</div>
<div id="company-details">
<div class="form-group row">
<div class="col-sm-3">
<input
type="text"
class="form-control"
id="name"
name="name"
placeholder="Company name"
formControlName=name>
</div>
</div>
<div class="form-group row" formGroupName="msgAccounts">
<div class="col-sm-6">
<input
type="text"
class="form-control"
id="line"
name="line"
placeholder="line"
formControlName=line>
</div>
<div class="col-sm-6">
<input
type="text"
class="form-control"
id="whatsapp"
name="whatsapp"
placeholder="whatsapp"
formControlName=whatsapp>
</div>
</div>
<div class="form-group row" formGroupName="socialMedia" >
<div class="col-sm-6">
<input
type="text"
class="form-control"
id="is"
name="is"
placeholder="Is"
formControlName=is>
</div>
</div>
</div>
</div>
</mat-tab>
</mat-tab-group>
<div class="form-group row">
<div class="col-sm-10">
<button type="submit"
(click)="saveConfig()">Save</button>
</div>
</div>
</ng-template>
</form>
</mat-tab>
</mat-tab-group>

Cannot read property of undefined in record edit form in angular 2

I have a problem in my edit form with undefined properties. I have an API that allows me to create and update customers. The problem is that some of the nested attributes are optional, this is fine when creating or editing fields that already exist but i can't figure out what to do when editing one of the nested fields on a customer that wasn't created with those fields and keep getting Cannot read property undefined errors.
This is my customer object:
export class Customer {
CompanyName: string;
DisplayName: string;
FamilyName: string;
GivenName: string;
Id: number;
Title: string;
BillAddr: BillAddress;
ShipAddr: ShipAddress;
PrimaryPhone: PrimaryPhoneNumber;
Mobile: MobileNumber;
PrimaryEmailAddr: PrimaryEmailAddress;
}
export class ShipAddress {
City: string;
Country: string;
CountrySubDivisionCode: string;
Line1: string;
Line2: string;
Line3: string;
Line4: string;
Line5: string;
PostalCode:string;
}
export class BillAddress {
City: string;
Country: string;
CountrySubDivisionCode: string;
Line1: string;
Line2: string;
Line3: string;
Line4: string;
Line5: string;
PostalCode:string;
}
export class PrimaryPhoneNumber {
FreeFormNumber: number;
}
export class MobileNumber {
FreeFormNumber: number;
}
export class PrimaryEmailAddress {
Address: string;
}
This is the html from the edit component:
<h1 class="page-header">Edit Customer</h1>
<div [ngBusy]="busy"></div>
<form (ngSubmit)="onSubmit()">
<div class="row">
<div class="col-md-6">
<h3>Customer information</h3>
<div class="form-group">
<label for="customertitle">Title</label>
<input type="text" class="form-control" id="cutomertitle" placeholder="Title" name="title" [(ngModel)]="customer && customer.Title" >
</div>
<div class="form-group">
<label for="customerGivenName">First Name</label>
<input type="text" class="form-control" id="customerGivenName" placeholder="First Name" name="givenname" [(ngModel)]="customer && customer.GivenName" >
</div>
<div class="form-group">
<label for="customerFamilyName">Last Name</label>
<input type="text" class="form-control" id="customerFamilyName" placeholder="Surname" name="familyname" [(ngModel)]="customer && customer.FamilyName" >
</div>
<div class="form-group">
<label for="customerEmailAddress">Email Address</label>
<input type="text" class="form-control" id="customerEmailAddress" placeholder="Email" name="email" [(ngModel)]="customer && customer.PrimaryEmailAddr.Address" >
</div>
<div class="form-group">
<label for="customerPhone">Phone</label>
<input type="text" class="form-control" id="customerPhone" placeholder="Phone Number" name="primaryphone" [(ngModel)]="customer && customer.PrimaryPhone.FreeFormNumber" >
</div>
<div class="form-group">
<label for="customerMobile">Mobile</label>
<input type="text" class="form-control" id="customerMobile" placeholder="Mobile Number" name="mobile" [(ngModel)]="customer && customer.Mobile.FreeFormNumber" >
</div>
</div>
<div class="col-md-6">
<h3>Address:</h3>
<div class="form-group">
<label for="customerLine1">Line 1</label>
<input type="text" class="form-control" id="cutomerLine1" placeholder="Line 1" name="line1" [(ngModel)]="customer && customer.BillAddr.Line1" >
</div>
<div class="form-group">
<label for="customerLine1">Line 2</label>
<input type="text" class="form-control" id="cutomerLine2" placeholder="Password" name="line2" [(ngModel)]="customer && customer.BillAddr.Line2" >
</div>
<div class="form-group">
<label for="customerLine1">Line 3</label>
<input type="text" class="form-control" id="cutomerLine3" placeholder="Password" name="line3" [(ngModel)]="customer && customer.BillAddr.Line3" >
</div>
<div class="form-group">
<label for="customerCity">City</label>
<input type="text" class="form-control" id="customerCity" placeholder="Password" name="city" [(ngModel)]="customer && customer.BillAddr.City" >
</div><div class="form-group">
<label for="customerLine1">State/Province</label>
<input type="text" class="form-control" id="cutomerLine1" placeholder="Password" name="Province" [(ngModel)]="customer && customer.BillAddr.CountrySubDivisionCode" >
</div>
<div class="form-group">
<label for="customerLine1">Postal Code</label>
<input type="text" class="form-control" id="cutomerLine1" placeholder="Password" name="postcode" [(ngModel)]="customer && customer.BillAddr.PostalCode" >
</div>
</div>
</div>
<button type="submit" class="btn btn-default">Save Changes</button>
</form>
The current details are fetched oninit with this function:
getCustomer(id): void {
this.busy = this.customersService.getCustomer(id)
.then(customer => this.customer = customer);
}
First problem is that data is coming async, so customer will be undefined when the view is rendered on all fields. Second problem is indeed that, since some fields do not have a value, will also throw an error.
Usually this could be solved by just initializing the customer:
customer = {};
But here again the problem is, that you have some deeper property paths that will though throw error despite this, like: customer.BillAddr.Line3. Of course you could initialize aaaall properties you have in your object, but that seems just ugly to me.
All this can be solved with the safe navigation operator. Unfortunately two-way-binding, i.e [(ngModel)] does not allow the safe navigation operator.
But!
[(ngModel)]="something" equals the following:
[ngModel]="something" (ngModelChange)="changeHappened($event)"
and one-way-binding does support the safe navigation operator. So what you could then do, is to use the ternary operator, that catches the input user makes and assigns it to your variable (in this example) with customer.Title = $event. And by using the ternary operator you get rid of the error undefined if there is no value initially with applying an empty string to the field:
[ngModel]="customer?.Title"
(ngModelChange)="customer?.Title ? customer.Title = $event : ''"
(All credit goes to this answer: https://stackoverflow.com/a/36016472/6294072)
Also I could suggest to use a model-driven form here where you could set all fields as empty initially and then just set values to the fields that have value and get rid of the ngModel. Just to throw in a second option.
But all in all, the above solution should get rid of your errors! :)

React form not clearing inputs after submit POST

Not sure why the setState function in the addUser() not doing it's job. The POST request works fine, but the inputs don't clear and that is an issue for the users. Perhaps a second pair of eyes, can spot the flaw.
import React, { Component, PropTypes } from 'react';
import { injectIntl, intlShape, FormattedMessage } from 'react-intl';
import { Link } from 'react-router';
// Import Style
import styles from './UserRegistrationForm.css';
export class UserRegistrationForm extends Component {
constructor(props) {
super(props);
this.state = { nickname: '', studentId: '', email: '', password: '' };
this.handleInputChange = this.handleInputChange.bind(this);
this.addUser = this.addUser.bind(this);
}
handleInputChange(event) {
this.setState({
[event.target.name]: event.target.value,
});
}
addUser = () => {
if (this.state.nickname && this.state.studentId && this.state.email && this.state.password) {
this.props.addUser(this.state.nickname, this.state.studentId, this.state.email, this.state.password);
this.setState({ nickname: '', studentId: '', email: '', password: '' });
}
};
render() {
return (
<div className={`${styles.formContainer} ${styles.center}`}>
<i className={`${styles.cap} fa fa-graduation-cap`} />
<h1 className={styles.title}><FormattedMessage id="siteTitle" /></h1>
<div className="row">
<form method="POST" className="col-lg-4 push-lg-4 col-md-6 push-md-3 col-xs-8 push-xs-2">
<div className="form-group row">
<label className="input-labels">Full Name</label>
<input type="text" className="form-control" name="nickname" placeholder="Full Name" onChange={this.handleInputChange} />
</div>
<div className="form-group row">
<label className="input-labels">Student ID</label>
<input type="text" className="form-control" name="studentId" placeholder="Student ID" onChange={this.handleInputChange} />
</div>
<div className="form-group row">
<label className="input-labels">Email</label>
<input type="email" className="form-control" name="email" placeholder="Email" onChange={this.handleInputChange} />
</div>
<div className="form-group row">
<label className="input-labels">Password</label>
<input type="password" className="form-control" name="password" placeholder="Password" onChange={this.handleInputChange} />
</div>
<div className={styles.center}>
<button
className={`${styles.btnOutlineSecondary} btn btn-outline-secondary ${styles.signInButton}`}
type="button" onClick={this.addUser}
>
Register and Start Studying!
</button><br /><br />
<Link to="/profile"><button className="btn btn-info" type="button">Temp Button to Profile Page</button></Link><br /><br />
<Link to="/">Already have an account? Sign in Here</Link>
</div>
</form>
</div>
</div>
);
}
}
UserRegistrationForm.propTypes = {
addUser: PropTypes.func.isRequired,
intl: intlShape.isRequired,
};
export default injectIntl(UserRegistrationForm);
There is no two-way data-binding in react, so you have to be careful when implementing controlled components https://facebook.github.io/react/docs/forms.html#controlled-components
for every one of your inputs, to make them controlled inputs, that will clear on submit, you must set their values to the corresponding state value, e.g.
<input value={this.state.nickname} type="text" className="form-control" name="nickname" placeholder="Full Name" onChange={this.handleInputChange} />
and
<input value={this.state.nickname} type="text" className="form-control" name="studentId" placeholder="Student ID" onChange={this.handleInputChange} />
... for every one of your inputs, adding the value attribute will make sure they stay in sync with, this.setState calls