Skip to content

Commit 05319f0

Browse files
authored
React - add contact functionality (#21)
1 parent 09cf1f7 commit 05319f0

File tree

6 files changed

+644
-376
lines changed

6 files changed

+644
-376
lines changed
Lines changed: 153 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,69 @@
11
import * as React from 'react';
2-
import { RouteComponentProps } from 'react-router';
3-
import { Link, NavLink } from 'react-router-dom';
2+
import { RouteComponentProps, Redirect } from 'react-router';
3+
import { NavLink } from 'react-router-dom';
44
import 'isomorphic-fetch';
55
import { Contact } from './contact';
66
import { ContactService } from './contactService';
77

88
interface ContactDetailState {
99
id: string;
10-
contact: Contact | undefined;
10+
name: string;
11+
address: string;
12+
city: string;
13+
state: string;
14+
postalCode: string;
15+
phone: string;
16+
email: string;
1117
loading: boolean;
18+
redirect: boolean;
1219
}
1320

1421
export class ContactDetail extends React.Component<RouteComponentProps<{}>, ContactDetailState> {
1522

1623
constructor(props: any) {
1724
super();
18-
this.state = { id: props.match.params.id, contact: undefined, loading: true };
1925

20-
let contactService = new ContactService();
21-
contactService.getById(this.state.id)
22-
.then(data => {
23-
this.setState({ contact: data, loading: false });
24-
});
26+
27+
if (props.match.params.id == undefined) {
28+
this.state = {
29+
id: props.match.params.id,
30+
name: '', address: '', city: '',
31+
state: '', postalCode: '', phone: '',
32+
email: '',
33+
loading: false,
34+
redirect: false
35+
};
36+
}
37+
else {
38+
this.state = {
39+
id: props.match.params.id,
40+
name: '', address: '', city: '',
41+
state: '', postalCode: '', phone: '',
42+
email: '',
43+
loading: true,
44+
redirect: false
45+
};
46+
47+
let contactService = new ContactService();
48+
contactService.getById(this.state.id)
49+
.then(data => {
50+
this.setState({
51+
name: data.name, address: data.address, city: data.city,
52+
state: data.state, postalCode: data.postalCode, phone: data.phone,
53+
email: data.email,
54+
loading: false
55+
});
56+
});
57+
}
2558
}
2659

2760
public render() {
2861
let contents = this.state.loading
2962
? <p><em>Loading...</em></p>
30-
: this.state.contact
31-
? ContactDetail.renderContactsTable(this.state.contact)
32-
: <p>No contacts</p>;
63+
: this.state.id != undefined &&
64+
!this.state.redirect
65+
? this.renderExistingContact()
66+
: this.renderNewContact();
3367

3468
return <div>
3569
<h1>Contact Detail</h1>
@@ -40,18 +74,113 @@ export class ContactDetail extends React.Component<RouteComponentProps<{}>, Cont
4074
</div>;
4175
}
4276

43-
private static renderContactsTable(contact: Contact) {
77+
private renderExistingContact() {
4478
return <dl className="dl-horizontal">
45-
<dt>ID</dt>
46-
<dd>{contact.id}</dd>
47-
<dt>Name</dt>
48-
<dd>{contact.name}</dd>
49-
<dt>Address</dt>
50-
<dd>{contact.getAddress()}</dd>
51-
<dt>Phone</dt>
52-
<dd>{contact.phone}</dd>
53-
<dt>Email</dt>
54-
<dd>{contact.email}</dd>
55-
</dl>;
79+
<dt>ID</dt>
80+
<dd>{this.state.id}</dd>
81+
<dt>Name</dt>
82+
<dd>{this.state.name}</dd>
83+
<dt>Address</dt>
84+
<dd>{this.state.address} {this.state.city}, {this.state.state} {this.state.postalCode}</dd>
85+
<dt>Phone</dt>
86+
<dd>{this.state.phone}</dd>
87+
<dt>Email</dt>
88+
<dd>{this.state.email}</dd>
89+
</dl>;
90+
}
91+
92+
private handleChange(event: any): void {
93+
const target = event.target;
94+
const value = target.value;
95+
const name = target.name;
96+
97+
this.setState({ [name]: value });
98+
}
99+
100+
handleSubmit(event: any): void {
101+
event.preventDefault();
102+
103+
let contact = new Contact();
104+
contact.name = this.state.name;
105+
contact.address = this.state.address;
106+
contact.city = this.state.city;
107+
contact.state = this.state.state;
108+
contact.postalCode = this.state.postalCode;
109+
contact.phone = this.state.phone;
110+
contact.email = this.state.email;
111+
112+
let contactService = new ContactService();
113+
contactService.save(contact)
114+
.then(c => this.setState({ id: String(c.id) }));
115+
116+
if (this.state.id) {
117+
this.setState({ redirect: true });
118+
}
119+
56120
}
121+
122+
private reset() {
123+
this.setState({
124+
name: '', address: '', city: '',
125+
state: '', postalCode: '', phone: '',
126+
email: ''
127+
});
128+
}
129+
130+
private renderNewContact() {
131+
return (
132+
<div>
133+
{this.state.redirect && <Redirect to={`/contactdetail/${this.state.id}`}/>}
134+
<form role="form" className="form-horizontal" onSubmit={(e: any) => this.handleSubmit(e)}>
135+
<div className="form-group">
136+
<label className="col-sm-2 control-label">Name</label>
137+
<div className="col-sm-10">
138+
<input type="text" placeholder="name" className="form-control" name="name" value={this.state.name} onChange={(e: any) => this.handleChange(e)} />
139+
</div>
140+
</div>
141+
<div className="form-group">
142+
<label className="col-sm-2 control-label">Address</label>
143+
<div className="col-sm-10">
144+
<input type="text" placeholder="address" className="form-control" name="address" value={this.state.address} onChange={(e: any) => this.handleChange(e)} />
145+
</div>
146+
</div>
147+
<div className="form-group">
148+
<label className="col-sm-2 control-label">City</label>
149+
<div className="col-sm-10">
150+
<input type="text" placeholder="city" className="form-control" name="city" value={this.state.city} onChange={(e: any) => this.handleChange(e)} />
151+
</div>
152+
</div>
153+
<div className="form-group">
154+
<label className="col-sm-2 control-label">State</label>
155+
<div className="col-sm-10">
156+
<input type="text" placeholder="state" className="form-control" name="state" value={this.state.state} onChange={(e: any) => this.handleChange(e)} />
157+
</div>
158+
</div>
159+
<div className="form-group">
160+
<label className="col-sm-2 control-label">Zip</label>
161+
<div className="col-sm-10">
162+
<input type="text" placeholder="zip" className="form-control" name="postalCode" value={this.state.postalCode} onChange={(e: any) => this.handleChange(e)} />
163+
</div>
164+
</div>
165+
<div className="form-group">
166+
<label className="col-sm-2 control-label">Phone</label>
167+
<div className="col-sm-10">
168+
<input type="text" placeholder="phone" className="form-control" name="phone" value={this.state.phone} onChange={(e: any) => this.handleChange(e)} />
169+
</div>
170+
</div>
171+
<div className="form-group">
172+
<label className="col-sm-2 control-label">Email</label>
173+
<div className="col-sm-10">
174+
<input type="email" placeholder="email" className="form-control" name="email" value={this.state.email} onChange={(e: any) => this.handleChange(e)} />
175+
</div>
176+
</div>
177+
<div className="text-center">
178+
<button className="btn btn-success btn-lg" type="submit">Save</button>
179+
<button className="btn btn-danger btn-lg" onClick={() => this.reset()}>Reset</button>
180+
</div >
181+
</form>
182+
</div>
183+
);
184+
}
185+
57186
}

ASP.NET Core Basics/src/React/ClientApp/components/contacts/ContactList.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ export class ContactList extends React.Component<RouteComponentProps<{}>, Contac
2929

3030
return <div>
3131
<h1>Contact List</h1>
32+
<Link to={'contactdetail'}>Create New Contact</Link>
3233
{contents}
3334
</div>;
3435
}

ASP.NET Core Basics/src/React/ClientApp/components/contacts/contactService.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,18 @@ export class ContactService {
1717
.then(contact => new Contact(contact));
1818
}
1919

20+
save(contact: Contact): Promise<Contact> {
21+
return fetch(this.baseUrl,
22+
{
23+
method: 'post',
24+
headers: {
25+
'Accept': 'application/json',
26+
'Content-Type': 'application/json'
27+
},
28+
body: JSON.stringify(contact)
29+
})
30+
.then(response => response.json())
31+
.then(contact => new Contact(contact));
32+
}
33+
2034
}

ASP.NET Core Basics/src/React/ClientApp/routes.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,5 @@ export const routes = <Layout>
1212
<Route path='/counter' component={Counter} />
1313
<Route path='/fetchdata' component={FetchData} />
1414
<Route path='/contactlist' component={ContactList} />
15-
<Route path='/contactdetail/:id' component={ContactDetail} />
15+
<Route path='/contactdetail/:id?' component={ContactDetail} />
1616
</Layout>;

0 commit comments

Comments
 (0)