Skip to content

Commit 3d48cfb

Browse files
committed
Moved the logic for <ListWidget> into a new separate file 'webpack_in/list_widget.jsx'.
1 parent 1f86f44 commit 3d48cfb

2 files changed

Lines changed: 170 additions & 157 deletions

File tree

webpack_in/entry.jsx

Lines changed: 1 addition & 157 deletions
Original file line numberDiff line numberDiff line change
@@ -10,168 +10,12 @@ import PropTypes from 'prop-types';
1010
import React from 'react';
1111
import ReactDOM from 'react-dom';
1212

13-
import ButtonWidget from './button_widget.jsx';
1413
import HelloWidget from './hello_widget.jsx';
14+
import ListWidget from './list_widget.jsx';
1515
import Styles from './styles.es';
1616
import TextWidget from './text_widget.jsx';
1717

1818

19-
class ListItem extends React.Component {
20-
render() {
21-
return (<li><input type='checkbox'
22-
checked={ this.props.isChecked }
23-
onChange={ this.props.onChangeChecked }/>{ this.props.caption }</li>);
24-
}
25-
}
26-
27-
ListItem.propTypes = {
28-
caption: PropTypes.string.isRequired,
29-
isChecked: PropTypes.bool.isRequired,
30-
onChangeChecked: PropTypes.func.isRequired
31-
};
32-
33-
class ListWidget extends React.Component {
34-
constructor(props) {
35-
super(props);
36-
37-
this._mutateStateToAddItem = (state, strItemCaption) => ({
38-
...state,
39-
items: [
40-
...state.items,
41-
{
42-
id: state.total_added,
43-
caption: strItemCaption,
44-
is_checked: false
45-
}
46-
],
47-
total_added: state.total_added + 1
48-
});
49-
50-
this._mutateStateToUpdateItemCaption = (state, id, strCaptionNew) => ({
51-
...state,
52-
items: state.items.map(objItem => (
53-
objItem.id === id ? {
54-
...objItem,
55-
caption: strCaptionNew
56-
}
57-
: objItem
58-
))
59-
});
60-
61-
this._mutateStateToUpdateItemChecked = (state, id, isChecked) => ({
62-
...state,
63-
items: state.items.map(objItem => (
64-
objItem.id === id ? {
65-
...objItem,
66-
is_checked: isChecked
67-
}
68-
: objItem
69-
))
70-
});
71-
72-
this._mutateStateToRemoveItemsChecked = state => ({
73-
...state,
74-
items: state.items.filter(objItem => !objItem.is_checked)
75-
});
76-
77-
const objStateEmpty = {
78-
items: [],
79-
total_added: 0
80-
};
81-
82-
this.state = this._mutateStateToAddItem(
83-
this._mutateStateToAddItem(
84-
this._mutateStateToAddItem(
85-
objStateEmpty,
86-
"Item 1"),
87-
"Item 2"),
88-
"Item 3");
89-
}
90-
91-
render() {
92-
const arrItemsSelected = this.state.items.filter(objItem => objItem.is_checked);
93-
94-
const formatListOfNames = (arrNames) => arrNames.reduce(
95-
(strOutput, strName, index) => (
96-
`${strOutput}${index > 0 // Will render either ' and' or ',' before 2nd item.
97-
// Will render ', and' before the 3rd+ last item.
98-
? (`${arrNames.length > 2 ? ',' : ""
99-
}${index === arrNames.length - 1 ? ' and' : ""}`
100-
)
101-
: ""} "${strName}"`
102-
),
103-
"");
104-
105-
return (
106-
<div style={ Styles.common }>
107-
<div style={ Styles.content }>
108-
<ul style={{ display: 'inline-block', textAlign: 'left', listStyleType: 'none' }}>
109-
{ this.state.items.map((objItem, index) => (
110-
<ListItem key={ objItem.id }
111-
caption={ objItem.caption }
112-
isChecked={ objItem.is_checked }
113-
onChangeChecked={ () => {
114-
this.setState(
115-
this._mutateStateToUpdateItemChecked(
116-
this.state,
117-
objItem.id,
118-
!objItem.is_checked));
119-
}}
120-
/>
121-
)) }
122-
</ul>
123-
</div>
124-
<div>
125-
<ButtonWidget caption="Add new item..."
126-
onClick={() => {
127-
const strItemNew = prompt("Please enter new item to add:",
128-
"Item "
129-
+ (this.state.items.length + 1));
130-
if (strItemNew === null) {
131-
return;
132-
}
133-
134-
this.setState(this._mutateStateToAddItem(this.state,
135-
strItemNew));
136-
}}/>
137-
<ButtonWidget caption="Edit item..."
138-
isDisabled={ arrItemsSelected.length !== 1 }
139-
onClick={() => {
140-
const objItemEdit = arrItemsSelected[0];
141-
const strItemEdited = prompt("Please edit item:",
142-
objItemEdit.caption);
143-
if (strItemEdited === null) {
144-
return;
145-
}
146-
147-
this.setState(this._mutateStateToUpdateItemCaption(
148-
this.state,
149-
objItemEdit.id,
150-
strItemEdited));
151-
}}/>
152-
<ButtonWidget caption={ arrItemsSelected.length > 1 ? "Remove items..."
153-
: "Remove item..." }
154-
isDisabled={ arrItemsSelected.length === 0 }
155-
onClick={() => {
156-
const arrCaptions = arrItemsSelected
157-
.map(objItem => objItem.caption);
158-
const isConfirmed = confirm(
159-
`Are you sure you want to remove item${
160-
arrCaptions.length > 1 ? "s" : ""} ${
161-
formatListOfNames(arrCaptions)
162-
}?`);
163-
if (isConfirmed === false) {
164-
return;
165-
}
166-
167-
this.setState(this._mutateStateToRemoveItemsChecked(this.state));
168-
}}/>
169-
</div>
170-
</div>
171-
);
172-
}
173-
}
174-
17519
class ButtonForCounter extends React.Component {
17620
constructor(props) {
17721
super(props);

webpack_in/list_widget.jsx

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
// This file 'list_widget.jsx' is part of an example for building a multi-widget React front-end
2+
// app step by step as outlined in the tutorial blog at
3+
// http://maratbn.com/blogs/2018/07/02/react-multi-widget/
4+
5+
6+
import PropTypes from 'prop-types';
7+
import React from 'react';
8+
9+
import ButtonWidget from './button_widget.jsx';
10+
import Styles from './styles.es';
11+
12+
13+
class ListItem extends React.Component {
14+
render() {
15+
return (<li><input type='checkbox'
16+
checked={ this.props.isChecked }
17+
onChange={ this.props.onChangeChecked }/>{ this.props.caption }</li>);
18+
}
19+
}
20+
21+
ListItem.propTypes = {
22+
caption: PropTypes.string.isRequired,
23+
isChecked: PropTypes.bool.isRequired,
24+
onChangeChecked: PropTypes.func.isRequired
25+
};
26+
27+
class ListWidget extends React.Component {
28+
constructor(props) {
29+
super(props);
30+
31+
this._mutateStateToAddItem = (state, strItemCaption) => ({
32+
...state,
33+
items: [
34+
...state.items,
35+
{
36+
id: state.total_added,
37+
caption: strItemCaption,
38+
is_checked: false
39+
}
40+
],
41+
total_added: state.total_added + 1
42+
});
43+
44+
this._mutateStateToUpdateItemCaption = (state, id, strCaptionNew) => ({
45+
...state,
46+
items: state.items.map(objItem => (
47+
objItem.id === id ? {
48+
...objItem,
49+
caption: strCaptionNew
50+
}
51+
: objItem
52+
))
53+
});
54+
55+
this._mutateStateToUpdateItemChecked = (state, id, isChecked) => ({
56+
...state,
57+
items: state.items.map(objItem => (
58+
objItem.id === id ? {
59+
...objItem,
60+
is_checked: isChecked
61+
}
62+
: objItem
63+
))
64+
});
65+
66+
this._mutateStateToRemoveItemsChecked = state => ({
67+
...state,
68+
items: state.items.filter(objItem => !objItem.is_checked)
69+
});
70+
71+
const objStateEmpty = {
72+
items: [],
73+
total_added: 0
74+
};
75+
76+
this.state = this._mutateStateToAddItem(
77+
this._mutateStateToAddItem(
78+
this._mutateStateToAddItem(
79+
objStateEmpty,
80+
"Item 1"),
81+
"Item 2"),
82+
"Item 3");
83+
}
84+
85+
render() {
86+
const arrItemsSelected = this.state.items.filter(objItem => objItem.is_checked);
87+
88+
const formatListOfNames = (arrNames) => arrNames.reduce(
89+
(strOutput, strName, index) => (
90+
`${strOutput}${index > 0 // Will render either ' and' or ',' before 2nd item.
91+
// Will render ', and' before the 3rd+ last item.
92+
? (`${arrNames.length > 2 ? ',' : ""
93+
}${index === arrNames.length - 1 ? ' and' : ""}`
94+
)
95+
: ""} "${strName}"`
96+
),
97+
"");
98+
99+
return (
100+
<div style={ Styles.common }>
101+
<div style={ Styles.content }>
102+
<ul style={{ display: 'inline-block', textAlign: 'left', listStyleType: 'none' }}>
103+
{ this.state.items.map((objItem, index) => (
104+
<ListItem key={ objItem.id }
105+
caption={ objItem.caption }
106+
isChecked={ objItem.is_checked }
107+
onChangeChecked={ () => {
108+
this.setState(
109+
this._mutateStateToUpdateItemChecked(
110+
this.state,
111+
objItem.id,
112+
!objItem.is_checked));
113+
}}
114+
/>
115+
)) }
116+
</ul>
117+
</div>
118+
<div>
119+
<ButtonWidget caption="Add new item..."
120+
onClick={() => {
121+
const strItemNew = prompt("Please enter new item to add:",
122+
"Item "
123+
+ (this.state.items.length + 1));
124+
if (strItemNew === null) {
125+
return;
126+
}
127+
128+
this.setState(this._mutateStateToAddItem(this.state,
129+
strItemNew));
130+
}}/>
131+
<ButtonWidget caption="Edit item..."
132+
isDisabled={ arrItemsSelected.length !== 1 }
133+
onClick={() => {
134+
const objItemEdit = arrItemsSelected[0];
135+
const strItemEdited = prompt("Please edit item:",
136+
objItemEdit.caption);
137+
if (strItemEdited === null) {
138+
return;
139+
}
140+
141+
this.setState(this._mutateStateToUpdateItemCaption(
142+
this.state,
143+
objItemEdit.id,
144+
strItemEdited));
145+
}}/>
146+
<ButtonWidget caption={ arrItemsSelected.length > 1 ? "Remove items..."
147+
: "Remove item..." }
148+
isDisabled={ arrItemsSelected.length === 0 }
149+
onClick={() => {
150+
const arrCaptions = arrItemsSelected
151+
.map(objItem => objItem.caption);
152+
const isConfirmed = confirm(
153+
`Are you sure you want to remove item${
154+
arrCaptions.length > 1 ? "s" : ""} ${
155+
formatListOfNames(arrCaptions)
156+
}?`);
157+
if (isConfirmed === false) {
158+
return;
159+
}
160+
161+
this.setState(this._mutateStateToRemoveItemsChecked(this.state));
162+
}}/>
163+
</div>
164+
</div>
165+
);
166+
}
167+
}
168+
169+
export default ListWidget;

0 commit comments

Comments
 (0)