angular 2 on from submit error self.context.onSubmit is not a function - forms

I am using 2.0.0-rc.6 in my angular 2 application.
on form submit I am getting this error - self.context.onSubmit is not a function
also it is appending form values in browser.
http://localhost:3000/register
on submit the page reloading and url become like this.
http://localhost:3000/register?firstName=vcvvc&lastName=vcv&userName=cvv&password=vcv&password=vcv
the codes are
form
<form class="ui form" (ngSubmit)="onSubmit()" #registrationForm="ngForm">
----
----
<button type="submit" class="ui button"> Register</button>
</form>
the service
import { Component } from '#angular/core';
import { User } from '../models/user';
import { RegisterService } from '../services/register.service';
#Component({
selector: 'side-panel',
templateUrl: 'app/components/register.component.html'
})
export class RegisterComponent {
newuser: User = new User();
theText: string;
constructor(private _registerService: RegisterService){
}
onsubmit(){
console.log('form submit clicked..');
this._registerService.sendUser(this.newuser).subscribe(
date =>{
this.newuser = new User();
},
error => console.log(error)
);
}
}

This error occurs when the name of the methods called in an event not matched with the template declaration and inside the class
In your template you have specified onSubmit() as camel case
<form class="ui form" (ngSubmit)="**onSubmit()**" #registrationForm="ngForm">
but inside the class, its not a camelCase "onsubmit()"
onsubmit(){
console.log('form submit clicked..');
this._registerService.sendUser(this.newuser).subscribe(

Related

REACT Multiple Registration

I have a problem with React, so I created script and it doesn't work.
This should:
Render first state step (it's working) (Component First)
Here is error, it don't see default values.(name & email
After click Save And Continue it should save files to data.
And going to next steps in cases.
The error is
bundle.js:34147 Uncaught ReferenceError: email is not defined
function send(e){
e.preventDefault()
}
function nextStep(){
this.setState({
step:this.state.step + 1
})
}
function nextStep(){
this.setState({
step:this.state.step - 1
})
}
function saveAndContinue(e) {
e.preventDefault()
// Get values via this.refs
var data = {
name : this.refs.name.getDOMNode().value,
email : this.refs.email.getDOMNode().value,
}
this.props.saveValues(data)
this.props.nextStep()
};
var fieldValues = [
name : null,
email : null,
];
function saveValues(fields) {
return (
fieldValues = Object.assign({}, fieldValues, fields)
);
}
class Registration extends React.Component{
constructor () {
super()
this.state = {
step:1
}
}
render() {
switch (this.state.step) {
case 1:
return <First fieldValues={fieldValues}
nextStep={this.nextStep}
previousStep={this.previousStep}
saveValues={this.saveValues} />
case 2:
return <Two fieldValues={fieldValues}
nextStep={this.nextStep}
previousStep={this.previousStep}
saveValues={this.saveValues}/>
case 3:
return <Third fieldValues={fieldValues}
nextStep={this.nextStep}
previousStep={this.previousStep}
saveValues={this.saveValues}/>
case 4:
return <Success fieldValues={fieldValues} />
}
}
}
class First extends React.Component{
render(){
return(
<form onSubmit ={send}>
<div className="group">
<input className="text" type="text" ref="name" defaultValue={this.props.fieldValues.name}/>
<span className="highlight"></span>
<span className="bar"></span>
<label>Write Name</label>
</div>
<div className="group">
<input className="text" type="email" ref="email" defaultValue={this.props.fieldValues.email} />
<span className="highlight"></span>
<span className="bar"></span>
<label>Write Your Mail</label>
</div>
<button onClick={this.saveAndContinue}>Save and Continue</button>
</form>
)
}
}
There is no Two, Third and Success classes in your code, so I'm assuming they are similar to the First class.
A global function doesn't need this keyword. But in this case, you have to put saveAndContinue inside First class if it need to access the state.
In React, normally you don't have to set default value for input.
Link the input value to the state, and then setState in onChange event.
The string in placeholder is shown when the state is empty.
The code below shows how to work with input tag in React:
<input
value={this.state.inputValue}
onChange={e => {
this.setState({ inputValue: e.target.value });
}}
type="text"
placeholder="default value"
/>
Note that the state will updates onChange rather than click the save button.
Does this solve your problem?

React|Rest API: Storing form data into an object on the REST API

I've set up a react web application that's currently listing all "Employees" from a mongodb.
I'm now trying to "add" employees to the database through a react frontend form.
I've managed to pass the data from the form to the application but I'm unsure of the process I need to go through to actually get that data solidified into an object and stored in the api.
Please excuse my code, it's disgusting as this is my first week learning react(honestly with little js knowledge, that's another story) and I've just patched together like 20 tutorials....
Here's my Form class:
class Form extends React.Component {
state = {
fullname: '',
}
change = e => {
this.setState({
[e.target.name]: e.target.value
});
}
onSubmit = e => {
e.preventDefault();
this.props.onSubmit(this.state)
this.setState({
fullname: ''
})
}
render() {
return <div>
<form>
<input name="fullname" placeholder="Full Name" value={this.state.fullname} onChange={e => this.change(e)} />
<button onClick={e => this.onSubmit(e)}>Submit</button>
</form>
</div>
}
}
and my Listing(?) class:
class EmployeeList extends React.Component {
constructor(props) {
super(props);
this.state = {employee: []};
this.EmployeeList = this.EmployeeList.bind(this)
this.componentDidMount = this.componentDidMount.bind(this)
}
componentDidMount() {
this.EmployeeList();
}
EmployeeList() {
fetch('/api/employees').then(function(data){
return data.json();
}).then( json => {
this.setState({
employee: json
});
console.log(json);
});
}
onSubmit = fields => {
console.log('app component got: ', fields)
}
render() {
//return a mapped array of employees
const employees = this.state.employee.map((item, i) => {
return <div className="row">
<span className="col-sm-6">{item.fullname}</span>
<span className="col-sm-2" id={item.action1}></span>
<span className="col-sm-2" id={item.action2}></span>
<span className="col-sm-2" id={item.action3}></span>
</div>
});
return <div>
<Form onSubmit={fields => this.onSubmit(fields)}/>
<div className="container">
<div className="row">
<div className="col-sm-6 bg-warning"><h3>Full Name</h3></div>
<div className="col-sm-2 bg-success"><h3>Action 1</h3></div>
<div className="col-sm-2 bg-success"><h3>Action 2</h3></div>
<div className="col-sm-2 bg-success"><h3>Action 3</h3></div>
</div>
</div>
<div id="layout-content" className="layout-content-wrapper">
<div className="panel-list">{ employees }</div>
</div>
</div>
}
}
I've managed to pass the data to the listing app evident by
onSubmit = fields => {
console.log('app component got: ', fields)
}
But how can I go about making a post request to store this data I send into an object on the db? And then also reload the page so that the new list of all employee's is shown?
Thanks so much for your time!
You can use fetch API to make POST request as well. Second parameter is the config object wherein you can pass the required request configurations.
fetch('url', {
method: 'post',
body: JSON.stringify({
name: fields.fullname
})
})
.then(response) {
response.json();
}
.then( json => {
this.setState({
employee: json
});
});
Additional Request Configs which can be used :
method - GET, POST, PUT, DELETE, HEAD
url - URL of the request
headers - associated Headers object
referrer - referrer of the request
mode - cors, no-cors, same-origin
credentials - should cookies go with the request? omit, same-origin
redirect - follow, error, manual
integrity - subresource integrity value
cache - cache mode (default, reload, no-cache)

ControlValueAccessor with FormArray in Angular 2

I have a child component which deals with the array of input controls. I want to have a formcontrol over the child component.
I am passing the array of json object, what would be the correct way to bind parent form to the child component's FormArray having 2 form control with Validator required on first.
This is the initial code
<h1>Child</h1>
<div formArrayName="names">
<div *ngFor="let c of names.control">
<input formControlName="firstName">
<input formControlName="lastName">
</div>
</div>
Intention is to bind parent form with the array of input control in the child component. Also form will become invalid if one of the input control in child component doesn't have required field.
http://plnkr.co/edit/HznCJfSEiSV28ERqNiWr?p=preview
I love solve old post :)
The key is that your custom Form Component has inside a FormArray, then use "writeValue" to create the formArray, see stackblitz
#Component({
selector: "my-child",
template: `
<h1>Child</h1>
<div *ngFor="let group of formArray.controls" [formGroup]="group">
<input formControlName="firstName" (blur)="_onTouched()" />
<input formControlName="lastName" (blur)="_onTouched()"/>
</div>
`,
providers: [{
provide: NG_VALUE_ACCESSOR,
useExisting: Child,
multi: true
},
{
provide: NG_VALIDATORS,
useExisting: Child,
multi: true
}
]
})
export class Child implements ControlValueAccessor {
formArray: FormArray;
_onChange;
_onTouched;
writeValue(value: any) {
this.formArray = new FormArray(
value.map(x => {
return new FormGroup({
firstName: new FormControl(x.firstName, Validators.required),
lastName: new FormControl(x.firstName, Validators.required)
});
})
);
this.formArray.valueChanges.subscribe(res => {
this._onChange(res);
});
}
registerOnChange(fn: (value: any) => void) {
this._onChange = fn;
}
registerOnTouched(fn: (value: any) => void) {
this._onTouched = fn;
}
validate({ value }: FormControl) {
return !this.formArray || this.formArray.valid ?
null : { error: "Some fields are not fullfilled" };
}
}
You have to use formArrayName directive and *ngFor like this:
<form [formGroup]="form" (ngSubmit)="sayHello()">
<input formControlName="name"><br>
<input formControlName="email"><br>
<div formArrayName="username">
<div *ngFor="let user of username.controls; let i=index">
<my-child formControlName="i"></my-child>
</div>
</div>
<button type="submit">Register</button>
</form>
And with FormBuilder you have to use FormArray as well.
form = new FormGroup({
name: new FormControl('My Name'),
username: new FormArray([
new FormControl("value"),// ControlValueAccesor is applied only to one control, not two. So you cannot use javascript object like you are using below this line.
{firstName:"Anna", lastName:"Smith"},
{firstName:"Peter", lastName:"Jones"}
])
});
For more details, see this doc.
Case 2: passing FormGroup:
form = new FormGroup({
name: new FormControl('My Name'),
username: new FormArray([
new FormGroup({
firstName: new FormControl('Anna'),
lastName: new FormControl('Smith')
}),
new FormGroup({
firstName: new FormControl('Peper'),
lastName: new FormControl('Jones')
}),
])
})
If you are tring to pass the FormGroup as a ngModel parameters, you can't!

Angular 2 : How to make POST call using form

I am completely new to Angular 2 and form concept. I am trying to POST form data to a POST API call. like this
POST API : http://localohot:8080/**********
Component :
user: any = {
id: null,
gender: null,
mstatus: null,
birthdate: null,
bloodgroup: null
}
userName: any = {
id: null,
personId: null,
displayName: '',
prefix: null,
givenName: null
}
userAddressJSON: any = {
id: null,
personId: null,
address1: null,
address2: null,
cityVillage: null
}
var form = new FormData();
form.append('userid', new Blob(['' + uid], { type: 'application/json' }));
form.append('user', new Blob([JSON.stringify(this.user)], { type: 'application/json' }));
form.append('userName', new Blob([JSON.stringify(this.userName)], { type: 'application/json' }));
form.append('userAddress', new Blob([JSON.stringify(this.userAddressJSON)], { type: 'application/json' }));
Here, I don't know how to make API call.
In our old application they used form data POST in jQuery. Now I am trying to do the same in Angular 2. When I do the form POST in old application they are sending like this
------WebKitFormBoundarybAWvwmP2VtRxvKA7
Content - Disposition: form - data; name = "userid"; filename = "blob"
Content - Type: application / json
------WebKitFormBoundarybAWvwmP2VtRxvKA7
Content - Disposition: form - data; name = "user"; filename = "blob"
Content - Type: application / json
------WebKitFormBoundarybAWvwmP2VtRxvKA7
Content - Disposition: form - data; name = "userName"; filename = "blob"
Content - Type: application / json
------WebKitFormBoundarybAWvwmP2VtRxvKA7
Content - Disposition: form - data; name = "userAddress"; filename = "blob"
Content - Type: application / json
Can any one help me how to do that form POST in Angular 2.
Here is how I currently make a POST call in my Angular 2 app, because it sounds like you could use a simple example of how to setup a form. Here is the Angular 2 documentation on How to Send Data to the Server.
For even more high level documentation on making AJAX requests in Angular 2 visit this URL.
in my app/app.module.ts
...
import { HttpModule } from '#angular/http';
...
#NgModule({
imports: [
...
HttpModule
...
],
declarations: [
...
],
providers: [ ... ],
bootstrap: [AppComponent],
})
export class AppModule { }
app/system-setup/system-setup.ts
export class SystemSetup {
system_setup_id: number;
name: string;
counter: number;
}
app/form-component/form.component.html (Notice the [(ngModel)], that is what binds the property of the object to the html input element)
<form class="form" (ngSubmit)="saveEdits()" #editSystemSetupForm="ngForm">
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label for="name">Name</label>
<input type="text" class="form-control" id="theName" name="name" [(ngModel)]="selectedItem.name" #itemsName="ngModel" required minlength="3"/>
<div [hidden]="itemsName.valid || itemsName.pristine" class="alert alert-danger">Name is required! Min length of 3.</div>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label for="">Counter</label>
<input type="number" step=0.01 class="form-control" name="counter" [(ngModel)]="selectedItem.counter" />
</div>
</div>
</div>
<div class="row">
<div class="col-md-4 col-md-offset-8">
<button type="submit" class="btn btn-success" style="float: right; margin-left: 15px;" [disabled]="!editISystemSetupForm.form.valid" >Save</button>
<button type="button" class="btn btn-danger" style="float: right;" (click)="cancelEdits()">Cancel</button>
</div>
</div>
</form>
in my app/form-component/form.component.ts
import { Component, OnInit, Input, Output, EventEmitter } from '#angular/core';
import { Headers, RequestOptions, Http, Response } from '#angular/http';
import { SystemSetup } from '../system-setup/system-setup';
#Component({
selector: 'app-setup-form',
templateUrl: 'setup-form.component.html',
styleUrls: ['setup-form.component.css']
})
export class SetupFormComponent implements OnInit {
#Input() selectedItem: SystemSetup; // The object to be edited
#Output() finishedEditing = new EventEmitter<number>(); // When the POST is done send to the parent component the new id
// Inject the Http service into our component
constructor(private _http: Http) { }
// User is finished editing POST the object to the server to be saved
saveEdits(): void {
let body = JSON.stringify( this.selectedItem );
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
return this._http.post('http://localhost:8080/**********', body, options)
.map(this.extractData)
.do(
data => {
this.finishedEditing.emit(data.system_setup_id); // Send the parent component the id if the selectedItem
})
.toPromise()
.catch(this.handleError);
}
/**
* Gets the data out of the package from the AJAX call.
* #param {Response} res - AJAX response
* #returns SystemSetup - A json of the returned data
*/
extractData(res: Response): SystemSetup {
let body = res.json();
if (body === 'failed') {
body = {};
}
return body || {};
}
/**
* Handles the AJAX error if the call failed or exited with exception. Print out the error message.
* #param {any} error - An error json object with data about the error on it
* #returns Promise - A promise with the error message in it
*/
private handleError(error: any): Promise<void> {
// In a real world app, we might use a remote logging infrastructure
// We'd also dig deeper into the error to get a better message
let errMsg = (error.message) ? error.message :
error.status ? `${error.status} - ${error.statusText}` : 'Server error';
console.error(errMsg); // log to console instead
return Promise.reject(errMsg);
}
}
This URL is the link to the official Angular 2 documentation site, which is a very good reference for anything an Angular 2 developer could want.

Form-Providers ngForm

I've got the following problem. I want to work with NG2 Forms. According to the angular 2 documentation, using the ngForm directive on the form and the ngControl directive on the input, the form should always have access to the validity of the input.
This works if the inputs are in the same component as the form, but as soon as I move the inputs into a child directive, they don't get the ngForm-Provider anymore.
This works:
import { Component, Input } from 'angular2/core';
import { FORM_DIRECTIVES } from 'angular/common';
#Component({
directives: [FORM_DIRECTIVES],
template: `
<form #heroForm="ngForm">
<input type="text"
[(ngModel)]="input.test"
ngControl="name">
</form>
`
})
export class FormTest1 {
public input = {
test: ""
}
}
However, this doesn't:
import { Component, Input } from 'angular2/core';
import { FORM_DIRECTIVES } from 'angular/common';
#Component({
directives: [FORM_DIRECTIVES],
template: `
<input *ngIf="data"
[(ngModel)]="data.test"
ngControl="name">
`
})
export class FormInput {
#Input() data;
}
#Component({
directives: [FormInput, FORM_DIRECTIVES],
template: `
<form #heroForm="ngForm">
<form-input
[data]="input">
</form-input>
</form>
`
})
export class FormTest1 {
public input = {
test: ""
}
}
As this throws:
EXCEPTION: No provider for t! (t -> t) in [null]
As soon as I remove the ngControl-attribute from the input, the error disappears, but the form in the parent doesn't receive any information about the input anymore. How do I go about passing the ngForm down to the child component?
Thanks in advance.
Here's a little example:
form-test.component.js
#Component({
selector: 'form-test',
directives: [FormInput, FORM_DIRECTIVES],
template: `
<form [ngFormModel]="heroForm">
<br>Is Form Valid? - {{heroForm.valid}}<br>
<br>Data: - {{input | json}}<br>
<input type="text" [(ngModel)]="input.test1" required [ngFormControl]="heroForm.controls['test1']">
<form-input [hForm]="heroForm" [data]="input">
</form-input>
<button type="submit">Submit</button>
</form>
`
})
export class FormTest1 {
public heroForm:ControlGroup;
constructor(private _builder:FormBuilder){
this.heroForm = _builder.group({
test1: ["", Validators.required],
test2: ["", Validators.required]
});
}
public input = {
test1: "",
test2: ""
}
}
form-input-test.ts
#Component({
selector: 'form-input',
directives: [FORM_DIRECTIVES,NgForm],
template: `
<label>sdsd</label>
<input type="text" [(ngModel)]="data.test2" [ngFormControl]="hForm.controls['test2']" required>
`
})
export class FormInput {
#Input() hForm:ControlGroup;
#Input() data;
}
I did two things mainly:
1- you only have access to the form in the parent object not in the child, I added another input so you can pass it along.
2-There's two ways to create a ControlGroup, one is implicitly like the one you did with ngForm and ngControl, and the other one is explicitely like I did with ngFormModel and ngFormControl, the second one gives you more control over the form so you can you things like this.
I recommend you to read this link