Skip to content

Commit 5fb529c

Browse files
authored
Merge pull request #35 from linuxonrails/port_11_tablemock_from_ts_to_js_#20
Port 11 tablemock from ts to js Issue #20
2 parents 07e8020 + c5be535 commit 5fb529c

File tree

10 files changed

+491
-0
lines changed

10 files changed

+491
-0
lines changed

11 TableMock/package.json

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
{
2+
"name": "samplereact",
3+
"version": "1.0.0",
4+
"description": "In this sample we are going to setup the basic plumbing to \"build\" our project and launch it in a dev server.",
5+
"main": "index.js",
6+
"scripts": {
7+
"start": "webpack-dev-server --inline",
8+
"test": "echo \"Error: no test specified\" && exit 1"
9+
},
10+
"author": "",
11+
"license": "ISC",
12+
"devDependencies": {
13+
"babel-core": "^6.18.2",
14+
"babel-loader": "^6.2.7",
15+
"babel-plugin-transform-runtime": "^6.15.0",
16+
"babel-preset-es2015": "^6.18.0",
17+
"babel-preset-react": "^6.16.0",
18+
"css-loader": "^0.25.0",
19+
"file-loader": "^0.9.0",
20+
"html-webpack-plugin": "^2.24.1",
21+
"style-loader": "^0.13.1",
22+
"url-loader": "^0.5.7",
23+
"webpack": "^1.13.3",
24+
"webpack-devserver": "0.0.6"
25+
},
26+
"dependencies": {
27+
"bootstrap": "^3.3.7",
28+
"react": "^15.3.2",
29+
"react-dom": "^15.3.2"
30+
}
31+
}

11 TableMock/readme.md

Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
# 11 TableMock
2+
3+
Let's render a table and use a child component to render each row.
4+
5+
We will start by just creating some mock data.
6+
7+
We will take a startup point sample _03 State_:
8+
9+
Summary steps:
10+
11+
- Define a model entity (we will call it _member_).
12+
- Define a fake api (to take thing simple we will just make it synchronous)
13+
- We will row component, we will call it _memberRow_.
14+
- Create a table component, we will call it _memberTable_ and make use of _memberRow
15+
16+
17+
## Prerequisites
18+
19+
Install [Node.js and npm](https://nodejs.org/en/) (v6.6.0 or newer) if they are not already installed on your computer.
20+
21+
> Verify that you are running at least node v6.x.x and npm 3.x.x by running `node -v` and `npm -v` in a terminal/console window. Older versions may produce errors.
22+
23+
## Steps to build it
24+
25+
- Copy the content from _03 State_ and execute:
26+
27+
```
28+
npm install
29+
```
30+
31+
- Let's create some mock data in _src/api/memberMockData.js_:
32+
33+
```javascript
34+
const MembersMockData = [
35+
{
36+
id: 1457912,
37+
login: 'brauliodiez',
38+
avatar_url: 'https://avatars.githubusercontent.com/u/1457912?v=3',
39+
},
40+
{
41+
id: 4374977,
42+
login: 'Nasdan',
43+
avatar_url: 'https://avatars.githubusercontent.com/u/4374977?v=3',
44+
},
45+
];
46+
47+
export default MembersMockData;
48+
49+
```
50+
51+
- Define a fake api (to take thing simple we will just make it synchronous) in _src/api/memberAPI.js_:
52+
53+
```javascript
54+
import MembersMockData from './memberMockData';
55+
56+
// Sync mock data API, inspired from:
57+
// https://gist.github.com/coryhouse/fd6232f95f9d601158e4
58+
class MemberAPI {
59+
// This would be performed on the server in a real app. Just stubbing in.
60+
static _clone(item) {
61+
return (
62+
// return cloned copy so that the item is passed by value instead of by reference
63+
JSON.parse(JSON.stringify(item))
64+
);
65+
}
66+
67+
// Just return a copy of the mock data
68+
getAllMembers() {
69+
return (
70+
MemberAPI._clone(MembersMockData)
71+
);
72+
}
73+
}
74+
75+
const memberAPI = new MemberAPI();
76+
77+
export default memberAPI;
78+
79+
```
80+
81+
- Now it's time jump into the interesting part, let's delete _hello.jsx_ and _nameEdit.jsx_.
82+
83+
- We are going to create an stateless component that will display a single row _memberRow.jsx_.
84+
85+
```jsx
86+
import * as React from 'react';
87+
88+
const MemberRow = props => (
89+
<tr>
90+
<td>
91+
<img src={props.member.avatar_url} style={{ maxWidth: '150px' }} alt="Avatar" />
92+
</td>
93+
<td>
94+
<span>{props.member.id}</span>
95+
</td>
96+
<td>
97+
<span>{props.member.login}</span>
98+
</td>
99+
</tr>
100+
);
101+
102+
MemberRow.propTypes = {
103+
// Is impossible to use:
104+
// member: React.PropTypes.instanceOf(MemberEntity),
105+
// with _clone().
106+
member: React.PropTypes.shape({
107+
id: React.PropTypes.number,
108+
avatar_url: React.PropTypes.string,
109+
login: React.PropTypes.string,
110+
}),
111+
};
112+
113+
export default MemberRow;
114+
115+
```
116+
117+
We can't use max-widh in the param style in. We must write 'maxWidth' in the react components.
118+
119+
- Then we are going to implement a component that will display a list of members (and will
120+
make use of rows), _membersTable.jsx_:
121+
122+
```jsx
123+
import * as React from 'react';
124+
import memberAPI from './api/memberAPI';
125+
import MemberRow from './memberRow';
126+
127+
class MembersTable extends React.Component {
128+
129+
constructor(props) {
130+
super(props);
131+
// set initial state
132+
this.state = { members: [] };
133+
}
134+
135+
// Standard react lifecycle function:
136+
// https://facebook.github.io/react/docs/component-specs.html
137+
componentWillMount() {
138+
this.setState({ members: memberAPI.getAllMembers() });
139+
}
140+
141+
render() {
142+
return (
143+
<div className="row">
144+
<h2> Members Page</h2>
145+
<table className="table">
146+
<thead>
147+
<tr>
148+
<th>
149+
Avatar
150+
</th>
151+
<th>
152+
Id
153+
</th>
154+
<th>
155+
Name
156+
</th>
157+
</tr>
158+
</thead>
159+
<tbody>
160+
{
161+
this.state.members.map(member =>
162+
<MemberRow key={member.id} member={member} />
163+
)
164+
}
165+
</tbody>
166+
</table>
167+
</div>
168+
);
169+
}
170+
}
171+
172+
export default MembersTable;
173+
174+
```
175+
176+
- Let's update app.jsx
177+
178+
```jsx
179+
import React from 'react';
180+
import MembersTableComponent from './membersTable';
181+
182+
export class App extends React.Component {
183+
constructor(props) {
184+
super(props);
185+
186+
this.state = {
187+
userName: 'defaultUserName',
188+
};
189+
190+
this.setUsernameState = this.setUsernameState.bind(this);
191+
}
192+
193+
setUsernameState(event) {
194+
// If the state gets more complex we should use object.assign
195+
this.setState({
196+
userName: event.target.value,
197+
});
198+
}
199+
200+
render() {
201+
return (
202+
<div className="col-xs-12">
203+
<MembersTableComponent />
204+
</div>
205+
);
206+
}
207+
}
208+
209+
```
210+
211+
- Let's run the sample
212+
213+
```
214+
npm start
215+
```

11 TableMock/src/api/memberAPI.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import MembersMockData from './memberMockData';
2+
3+
// Sync mock data API, inspired from:
4+
// https://gist.github.com/coryhouse/fd6232f95f9d601158e4
5+
class MemberAPI {
6+
// This would be performed on the server in a real app. Just stubbing in.
7+
static _clone(item) {
8+
return (
9+
// return cloned copy so that the item is passed by value instead of by reference
10+
JSON.parse(JSON.stringify(item))
11+
);
12+
}
13+
14+
// Just return a copy of the mock data
15+
getAllMembers() {
16+
return (
17+
MemberAPI._clone(MembersMockData)
18+
);
19+
}
20+
}
21+
22+
const memberAPI = new MemberAPI();
23+
24+
export default memberAPI;
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
const MembersMockData = [
2+
{
3+
id: 1457912,
4+
login: 'brauliodiez',
5+
avatar_url: 'https://avatars.githubusercontent.com/u/1457912?v=3',
6+
},
7+
{
8+
id: 4374977,
9+
login: 'Nasdan',
10+
avatar_url: 'https://avatars.githubusercontent.com/u/4374977?v=3',
11+
},
12+
];
13+
14+
export default MembersMockData;

11 TableMock/src/app.jsx

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import React from 'react';
2+
import MembersTableComponent from './membersTable';
3+
4+
export class App extends React.Component {
5+
constructor(props) {
6+
super(props);
7+
8+
this.state = {
9+
userName: 'defaultUserName',
10+
};
11+
12+
this.setUsernameState = this.setUsernameState.bind(this);
13+
}
14+
15+
setUsernameState(event) {
16+
// If the state gets more complex we should use object.assign
17+
this.setState({
18+
userName: event.target.value,
19+
});
20+
}
21+
22+
render() {
23+
return (
24+
<div className="col-xs-12">
25+
<MembersTableComponent />
26+
</div>
27+
);
28+
}
29+
}

11 TableMock/src/index.html

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8">
5+
<title>Sample 11: TableMock</title>
6+
</head>
7+
<body>
8+
<h1>Sample app</h1>
9+
<div id="root"></div>
10+
</body>
11+
</html>

11 TableMock/src/main.jsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/* global document */
2+
3+
import React from 'react';
4+
import { render } from 'react-dom';
5+
import { App } from './app';
6+
7+
render(
8+
<App />
9+
, document.getElementById('root')
10+
);

11 TableMock/src/memberRow.jsx

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import * as React from 'react';
2+
3+
const MemberRow = props => (
4+
<tr>
5+
<td>
6+
<img src={props.member.avatar_url} style={{ maxWidth: '150px' }} alt="Avatar" />
7+
</td>
8+
<td>
9+
<span>{props.member.id}</span>
10+
</td>
11+
<td>
12+
<span>{props.member.login}</span>
13+
</td>
14+
</tr>
15+
);
16+
17+
MemberRow.propTypes = {
18+
// Is impossible to use:
19+
// member: React.PropTypes.instanceOf(MemberEntity),
20+
// with _clone().
21+
member: React.PropTypes.shape({
22+
id: React.PropTypes.number,
23+
avatar_url: React.PropTypes.string,
24+
login: React.PropTypes.string,
25+
}),
26+
};
27+
28+
export default MemberRow;

0 commit comments

Comments
 (0)