In this project we will create an application that can change the theme of a paragraph real-time using elements on the front-end. We will also create a switch that can enable and disable the ability to change the theme of the paragraph. In the process of creating this project, we will cover how to use this
, bind
, state
, and props
.
fork
andclone
this repository.cd
into the project directory.- Run
npm install
. - Run
npm start
afternpm install
has finished.
In this step, we will create the initial state for src/App.js
. On this state object, we will keep track of the initial theme values and if the theme is allowed to be edited.
- Open
src/App.js
. - Create a
constructor
method where it says// constructor
:- This method should call
super()
. - This method should create an initial state object with the following properties:
- fontColor: 'black',
- fontSize: 12,
- fontFamily: 'monospace',
- allowEdit: 'true'
- This method should call
src/App.js
import React, { Component } from 'react';
// Components
import EditToggle from './components/EditToggle';
import ColorChanger from './components/ColorChanger';
import SizeChanger from './components/SizeChanger';
import FamilyChanger from './components/FamilyChanger';
import TextContainer from './components/TextContainer';
class App extends Component {
constructor() {
super();
this.state = {
fontColor: 'black',
fontSize: 12,
fontFamily: 'monospace',
allowEdit: 'true'
};
}
// updateColor
// updateSize
// updateFamily
// updateEditStatus
render() {
return (
<div>
<div className="headerBar">
{ /* Render EditToggle */ }
{ /* Render ColorChanger */ }
{ /* Render SizeChanger */ }
{ /* Render FamilyChanger */ }
</div>
<div className="textArea">
{ /* Render TextContainer */ }
</div>
</div>
)
}
}
export default App;
In this step, we will create class methods in src/App.js
to update fontColor
, fontSize
, fontFamily
, and allowEdit
on state.
- Open
src/App.js
. - Create an
updateColor
method that takes a parameter calledval
where it says// updateColor
:- Use
setState
to updatefontColor
toval
.
- Use
- Create an
updateSize
method that takes a parameter calledval
where it says// updateSize
:- Use
setState
to updatefontSize
toval
.
- Use
- Create an
updateFamily
method that takes a parameter calledval
where it says// updateFamily
:- Use
setState
to updatefontFamily
toval
.
- Use
- Create an
updateEditStatus
method that takes a parameter calledval
where it says// updateEditStatus
:- Use
setState
to updateallowEdit
toval
.
- Use
src/App.js
import React, { Component } from 'react';
// Components
import EditToggle from './components/EditToggle';
import ColorChanger from './components/ColorChanger';
import SizeChanger from './components/SizeChanger';
import FamilyChanger from './components/FamilyChanger';
import TextContainer from './components/TextContainer';
class App extends Component {
constructor() {
super();
this.state = {
fontColor: 'black',
fontSize: 12,
fontFamily: 'monospace',
allowEdit: 'true'
};
}
updateColor(val) {
this.setState({ fontColor: val });
}
updateSize(val) {
this.setState({ fontSize: val });
}
updateFamily(val) {
this.setState({ fontFamily: val });
}
updateEditStatus(val) {
this.setState({ allowEdit: val });
}
render() {
return (
<div>
<div className="headerBar">
{ /* Render EditToggle */ }
{ /* Render ColorChanger */ }
{ /* Render SizeChanger */ }
{ /* Render FamilyChanger */ }
</div>
<div className="textArea">
{ /* Render TextContainer */ }
</div>
</div>
)
}
}
export default App;
In this step, we will bind this
to our methods in the constructor
method in App.js
. We'll need to bind this
on the updateEditStatus
, updateColor
, updateSize
, and updateFamily
methods.
- Open
src/App.js
. - Bind
this
to theupdateColor
,updateSize
,updateFamily
, andupdateEditStatus
methods at the bottom of theconstructor
method.
src/App.js
import React, { Component } from 'react';
// Components
import EditToggle from './components/EditToggle';
import ColorChanger from './components/ColorChanger';
import SizeChanger from './components/SizeChanger';
import FamilyChanger from './components/FamilyChanger';
import TextContainer from './components/TextContainer';
class App extends Component {
constructor() {
super();
this.state = {
fontColor: 'black',
fontSize: 12,
fontFamily: 'monospace',
allowEdit: 'true'
};
this.updateColor = this.updateColor.bind( this );
this.updateSize = this.updateSize.bind( this );
this.updateFamily = this.updateFamily.bind( this );
this.updateEditStatus = this.updateEditStatus.bind( this );
}
updateColor(val) {
this.setState({ fontColor: val });
}
updateSize(val) {
this.setState({ fontSize: val });
}
updateFamily(val) {
this.setState({ fontFamily: val });
}
updateEditStatus(val) {
this.setState({ allowEdit: val });
}
render() {
return (
<div>
<div className="headerBar">
{ /* Render EditToggle */ }
{ /* Render ColorChanger */ }
{ /* Render SizeChanger */ }
{ /* Render FamilyChanger */ }
</div>
<div className="textArea">
{ /* Render TextContainer */ }
</div>
</div>
)
}
}
export default App;
In this step, we will render
our imported components in App.js
.
- Open
src/App.js
. - Render the
EditToggle
component where it says{ /* Render EditToggle */ }
:- Add a prop called
update
that is equal to theupdateEditStatus
method.
- Add a prop called
- Render the
ColorChanger
component where it says{ /* Render ColorChange */ }
:- Add a prop called
update
that is equal to theupdateColor
method. - Add a prop called
allowEdit
that is equal to the value ofallowEdit
on state.
- Add a prop called
- Render the
SizeChanger
component where it says{ /* Render SizeChanger */ }
:- Add a prop called
update
that is equal to theupdateSize
method. - Add a prop called
allowEdit
that is equal to the value ofallowEdit
on state.
- Add a prop called
- Render the
FamilyChanger
component where it says{ /* Render FamilyChanger */ }
:- Add a prop called
update
that is equal to theupdateFamily
method. - Add a prop called
allowEdit
that is equal to the value ofallowEdit
on state.
- Add a prop called
- Render the
TextContainer
component where it says{ /* Render TextContainer */ }
:- Add a prop called
fontColor
that equalsfontColor
on state. - Add a prop called
fontSize
that equalsfontSize
on state. - Add a prop called
fontFamily
that equalsfontFamily
on state.
- Add a prop called
src/App.js
import React, { Component } from 'react';
// Components
import EditToggle from './components/EditToggle';
import ColorChanger from './components/ColorChanger';
import SizeChanger from './components/SizeChanger';
import FamilyChanger from './components/FamilyChanger';
import TextContainer from './components/TextContainer';
class App extends Component {
constructor() {
super();
this.state = {
fontColor: 'black',
fontSize: 12,
fontFamily: 'monospace',
allowEdit: 'true'
};
this.updateColor = this.updateColor.bind( this );
this.updateSize = this.updateSize.bind( this );
this.updateFamily = this.updateFamily.bind( this );
this.updateEditStatus = this.updateEditStatus.bind( this );
}
updateColor(val) {
this.setState({ fontColor: val });
}
updateSize(val) {
this.setState({ fontSize: val });
}
updateFamily(val) {
this.setState({ fontFamily: val });
}
updateEditStatus(val) {
this.setState({ allowEdit: val });
}
render() {
return (
<div>
<div className="headerBar">
<EditToggle update={ this.updateEditStatus } />
<ColorChanger update={ this.updateColor } allowEdit={ this.state.allowEdit } />
<SizeChanger update={ this.updateSize } allowEdit={ this.state.allowEdit } />
<FamilyChanger update={ this.updateFamily } allowEdit={ this.state.allowEdit } />
</div>
<div className="textArea">
<TextContainer
fontColor={ this.state.fontColor }
fontSize={ this.state.fontSize }
fontFamily={ this.state.fontFamily } />
</div>
</div>
)
}
}
export default App;
In this step, we will update our select
elements in the EditToggle
, ColorChanger
, FamilyChanger
, and SizeChanger
components to use an onChange
that calls the update
prop with the value of the select
element. We will also disable the select
element if the value of allowEdit
is "false"
.
- Open
EditToggle
,ColorChanger.js
,FamilyChanger.js
, andSizeChanger.js
fromsrc/components/
. - Locate the
select
tag, in all four files, and add anonChange
prop:- The
onChange
should use an arrow function to capture theevent
. - Inside the arrow function call the
update
prop with the value of the target from theevent
. - Parse Int the value of the target when in
SizeChanger.js
.
- The
- Locate the
select
tag, inColorChanger
,FamilyChanger
, andSizeChanger
, and add adisabled
prop:- The
select
element should bedisabled
ifallowEdit
from props is equal to"false"
.
- The
src/components/EditToggle.js
return (
<select className="dropDownContainer ml0" onChange={ (e) => this.props.update(e.target.value) }>
<option value="true"> Allow Edit </option>
<option value="false"> Disable Edit </option>
</select>
)
src/components/ColorChanger.js
return (
<select className="dropDownContainer" onChange={ (e) => this.props.update(e.target.value) } disabled={ this.props.allowEdit === "false" }>
<option value="black"> Black </option>
<option value="blue"> Blue </option>
<option value="green"> Green </option>
</select>
)
src/components/FamilyChanger.js
return (
<select className="dropDownContainer" onChange={ (e) => this.props.update(e.target.value) } disabled={ this.props.allowEdit === "false" }>
<option value="monospace"> Monospace </option>
<option value="arial"> Arial </option>
<option value="courier"> Courier </option>
</select>
)
src/components/SizeChanger.js
return (
<select className="dropDownContainer" onChange={ (e) => this.props.update( parseInt(e.target.value) ) } disabled={ this.props.allowEdit === "false" }>
<option value="12"> 12 </option>
<option value="13"> 13 </option>
<option value="14"> 14 </option>
</select>
)
Now we have everything set up to be able to edit the look of our text. Our last step is to connect our styling in the TextContainer
components to the props being passed to it so they will reflect the changes we make.
- Open
TextContainer.js
fromsrc/components/
. - Bind the
updateText
method tothis
in theconstructor
method. - In the
textarea
tag there is astyle
prop, this is where we need to add the styling that's being passed to this component through props.- Uncomment the
style
prop. - Set
fontFamily
,fontSize
andcolor
equal to the appropriate props values.
- Uncomment the
src/components/TextContainer.js
import React, { Component } from 'react';
export default class TextContainer extends Component {
constructor() {
super()
this.state = {
text: ''
}
this.updateText = this.updateText.bind(this)
}
updateText(e) {
this.setState({
text: e.target.value
})
}
render() {
return (
<div className="textContainer">
<textarea
style={ { color: this.props.fontColor, fontFamily: this.props.fontFamily, fontSize: this.props.fontSize } }
onChange={this.updateText}
value={this.state.text}
placeholder='This is where your text will be!'
cols="90"
rows="30">
</textarea>
</div>
)
}
}
If you see a problem or a typo, please fork, make the necessary changes, and create a pull request so we can review your changes and merge them into the master repo and branch.
© DevMountain LLC, 2017. Unauthorized use and/or duplication of this material without express and written permission from DevMountain, LLC is strictly prohibited. Excerpts and links may be used, provided that full and clear credit is given to DevMountain with appropriate and specific direction to the original content.