master 181e65d4262b cached
14 files
12.2 KB
3.5k tokens
14 symbols
1 requests
Download .txt
Repository: lorenseanstewart/react-controlled-form-components
Branch: master
Commit: 181e65d4262b
Files: 14
Total size: 12.2 KB

Directory structure:
gitextract_rlcvmnka/

├── .gitignore
├── .nvmrc
├── README.md
├── package.json
├── public/
│   ├── fake_db.json
│   └── index.html
└── src/
    ├── App.js
    ├── components/
    │   ├── CheckboxOrRadioGroup.js
    │   ├── Select.js
    │   ├── SingleInput.js
    │   └── TextArea.js
    ├── containers/
    │   └── FormContainer.js
    ├── index.js
    └── styles.css

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
# See http://help.github.com/ignore-files/ for more about ignoring files.

# dependencies
node_modules

# testing
coverage

# production
build

# misc
.DS_Store
.idea/
.env
npm-debug.log


================================================
FILE: .nvmrc
================================================
6.2.1

================================================
FILE: README.md
================================================
### Tutorial: React.js Controlled Form Components

This repo is the companion to my blog post, [React.js Controlled Form Components](http://lorenstewart.me/2016/10/31/react-js-forms-controlled-components/).

[DEMO](http://lorenstewart.me/react-controlled-form-components/)

To get started:
 1. Make sure you're using Node 6 or higher (4 and higher will work, though)
 2. `npm install create-react-app -g` (if you don't have it installed already)
 3. `npm install`
 4. `npm run start`
 5. Open [http://localhost:3000/](http://localhost:3000/) in your browser


================================================
FILE: package.json
================================================
{
  "name": "react-form-components",
  "version": "0.1.0",
  "private": true,
  "devDependencies": {
    "react-scripts": "0.6.1"
  },
  "dependencies": {
    "react": "^15.3.2",
    "react-dom": "^15.3.2",
    "spectre.css": "^0.1.27"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test --env=jsdom",
    "eject": "react-scripts eject"
  }
}


================================================
FILE: public/fake_db.json
================================================
{
  "ownerName": "",
  "petSelections": ["dog", "cat", "rabbit", "iguana", "pony", "ferret", "fish", "bird"],
  "selectedPets": ["dog", "cat", "ferret"],
  "ageOptions": ["18 - 25", "26 - 59", "60 or older"],
  "ownerAgeRangeSelection": "",
  "siblingOptions": ["yes", "no"],
  "siblingSelection": ["yes"],
  "currentPetCount": 0,
  "description": ""
}

================================================
FILE: public/index.html
================================================
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
    <!--
      Notice the use of %PUBLIC_URL% in the tag above.
      It will be replaced with the URL of the `public` folder during the build.
      Only files inside the `public` folder can be referenced from the HTML.

      Unlike "/favicon.ico" or "favico.ico", "%PUBLIC_URL%/favicon.ico" will
      work correctly both with client-side routing and a non-root public URL.
      Learn how to configure a non-root public URL by running `npm run build`.
    -->
    <title>React App</title>
  </head>
  <body>
    <div id="root"></div>
    <!--
      This HTML file is a template.
      If you open it directly in the browser, you will see an empty page.

      You can add webfonts, meta tags, or analytics to this file.
      The build step will place the bundled scripts into the <body> tag.

      To begin the development, run `npm start`.
      To create a production bundle, use `npm run build`.
    -->
  </body>
</html>


================================================
FILE: src/App.js
================================================
import React, { Component } from 'react';
import '../node_modules/spectre.css/dist/spectre.min.css';
import './styles.css';
import FormContainer from './containers/FormContainer';

class App extends Component {
  render() {
    return (
      <div className="container">
        <div className="columns">
          <div className="col-md-9 centered">
            <h3>React.js Controlled Form Components</h3>
            <FormContainer />
          </div>
        </div>
      </div>
    );
  }
}

export default App;


================================================
FILE: src/components/CheckboxOrRadioGroup.js
================================================
import React from 'react';

const CheckboxOrRadioGroup = (props) => (
	<div>
		<label className="form-label">{props.title}</label>
		<div className="checkbox-group">
			{props.options.map(option => {
				return (
					<label key={option} className="form-label capitalize">
						<input
							className="form-checkbox"
							name={props.setName}
							onChange={props.controlFunc}
							value={option}
							checked={props.selectedOptions.indexOf(option) > -1}
							type={props.type} /> {option}
					</label>
				);
			})}
		</div>
	</div>
);

CheckboxOrRadioGroup.propTypes = {
	title: React.PropTypes.string.isRequired,
	type: React.PropTypes.oneOf(['checkbox', 'radio']).isRequired,
	setName: React.PropTypes.string.isRequired,
	options: React.PropTypes.array.isRequired,
	selectedOptions: React.PropTypes.array,
	controlFunc: React.PropTypes.func.isRequired
};

export default CheckboxOrRadioGroup;


================================================
FILE: src/components/Select.js
================================================
import React from 'react';

const Select = (props) => (
	<div className="form-group">
		<select
			name={props.name}
			value={props.selectedOption}
			onChange={props.controlFunc}
			className="form-select">
			<option value="">{props.placeholder}</option>
			{props.options.map(opt => {
				return (
					<option
						key={opt}
						value={opt}>{opt}</option>
				);
			})}
		</select>
	</div>
);

Select.propTypes = {
	name: React.PropTypes.string.isRequired,
	options: React.PropTypes.array.isRequired,
	selectedOption: React.PropTypes.string,
	controlFunc: React.PropTypes.func.isRequired,
	placeholder: React.PropTypes.string
};

export default Select;

================================================
FILE: src/components/SingleInput.js
================================================
import React from 'react';

const SingleInput = (props) => (
	<div className="form-group">
		<label className="form-label">{props.title}</label>
		<input
			className="form-input"
			name={props.name}
			type={props.inputType}
			value={props.content}
			onChange={props.controlFunc}
			placeholder={props.placeholder} />
	</div>
);

SingleInput.propTypes = {
	inputType: React.PropTypes.oneOf(['text', 'number']).isRequired,
	title: React.PropTypes.string.isRequired,
	name: React.PropTypes.string.isRequired,
	controlFunc: React.PropTypes.func.isRequired,
	content: React.PropTypes.oneOfType([
		React.PropTypes.string,
		React.PropTypes.number,
	]).isRequired,
	placeholder: React.PropTypes.string,
};

export default SingleInput;

================================================
FILE: src/components/TextArea.js
================================================
import React from 'react';

const TextArea = (props) => (
	<div className="form-group">
		<label className="form-label">{props.title}</label>
		<textarea
			className="form-input"
			style={props.resize ? null : {resize: 'none'}}
			name={props.name}
			rows={props.rows}
			value={props.content}
			onChange={props.controlFunc}
			placeholder={props.placeholder} />
	</div>
);

TextArea.propTypes = {
	title: React.PropTypes.string.isRequired,
	rows: React.PropTypes.number.isRequired,
	name: React.PropTypes.string.isRequired,
	content: React.PropTypes.string.isRequired,
	resize: React.PropTypes.bool,
	placeholder: React.PropTypes.string,
	controlFunc: React.PropTypes.func.isRequired
};

export default TextArea;

================================================
FILE: src/containers/FormContainer.js
================================================
import React, {Component} from 'react';
import CheckboxOrRadioGroup from '../components/CheckboxOrRadioGroup';
import SingleInput from '../components/SingleInput';
import TextArea from '../components/TextArea';
import Select from '../components/Select';

class FormContainer extends Component {
	constructor(props) {
		super(props);
		this.state = {
			ownerName: '',
			petSelections: [],
			selectedPets: [],
			ageOptions: [],
			ownerAgeRangeSelection: '',
			siblingOptions: [],
			siblingSelection: [],
			currentPetCount: 0,
			description: ''
		};
		this.handleFormSubmit = this.handleFormSubmit.bind(this);
		this.handleClearForm = this.handleClearForm.bind(this);
		this.handleFullNameChange = this.handleFullNameChange.bind(this);
		this.handleCurrentPetCountChange = this.handleCurrentPetCountChange.bind(this);
		this.handleAgeRangeSelect = this.handleAgeRangeSelect.bind(this);
		this.handlePetSelection = this.handlePetSelection.bind(this);
		this.handleSiblingsSelection = this.handleSiblingsSelection.bind(this);
		this.handleDescriptionChange = this.handleDescriptionChange.bind(this);
	}
	componentDidMount() {
		fetch('./fake_db.json')
			.then(res => res.json())
			.then(data => {
				this.setState({
					ownerName: data.ownerName,
					petSelections: data.petSelections,
					selectedPets: data.selectedPets,
					ageOptions: data.ageOptions,
					ownerAgeRangeSelection: data.ownerAgeRangeSelection,
					siblingOptions: data.siblingOptions,
					siblingSelection: data.siblingSelection,
					currentPetCount: data.currentPetCount,
					description: data.description
				});
			});
	}
	handleFullNameChange(e) {
		this.setState({ ownerName: e.target.value }, () => console.log('name:', this.state.ownerName));
	}
	handleCurrentPetCountChange(e) {
		this.setState({ currentPetCount: e.target.value }, () => console.log('pet count', this.state.currentPetCount));
	}
	handleAgeRangeSelect(e) {
		this.setState({ ownerAgeRangeSelection: e.target.value }, () => console.log('age range', this.state.ownerAgeRangeSelection));
	}
	handlePetSelection(e) {
		const newSelection = e.target.value;
		let newSelectionArray;
		if(this.state.selectedPets.indexOf(newSelection) > -1) {
			newSelectionArray = this.state.selectedPets.filter(s => s !== newSelection)
		} else {
			newSelectionArray = [...this.state.selectedPets, newSelection];
		}
		this.setState({ selectedPets: newSelectionArray }, () => console.log('pet selection', this.state.selectedPets));
	}
	handleSiblingsSelection(e) {
		this.setState({ siblingSelection: [e.target.value] }, () => console.log('siblingz', this.state.siblingSelection));
	}
	handleDescriptionChange(e) {
		// const textArray = e.target.value.split('').filter(x => x !== 'e');
		// console.log('string split into array of letters',textArray);
		// const filteredText = textArray.join('');
		// this.setState({ description: filteredText }, () => console.log('description', this.state.description));
		this.setState({ description: e.target.value }, () => console.log('description', this.state.description));
	}
	handleClearForm(e) {
		e.preventDefault();
		this.setState({
			ownerName: '',
			selectedPets: [],
			ownerAgeRangeSelection: '',
			siblingSelection: [],
			currentPetCount: 0,
			description: ''
		});
	}
	handleFormSubmit(e) {
		e.preventDefault();

		const formPayload = {
			ownerName: this.state.ownerName,
			selectedPets: this.state.selectedPets,
			ownerAgeRangeSelection: this.state.ownerAgeRangeSelection,
			siblingSelection: this.state.siblingSelection,
			currentPetCount: this.state.currentPetCount,
			description: this.state.description
		};

		console.log('Send this in a POST request:', formPayload);
		this.handleClearForm(e);
	}
	render() {
		return (
			<form className="container" onSubmit={this.handleFormSubmit}>
				<h5>Pet Adoption Form</h5>
				<SingleInput
					inputType={'text'}
					title={'Full name'}
					name={'name'}
					controlFunc={this.handleFullNameChange}
					content={this.state.ownerName}
					placeholder={'Type first and last name here'} />
				<Select
					name={'ageRange'}
					placeholder={'Choose your age range'}
					controlFunc={this.handleAgeRangeSelect}
					options={this.state.ageOptions}
					selectedOption={this.state.ownerAgeRangeSelection} />
				<CheckboxOrRadioGroup
					title={'Which kinds of pets would you like to adopt?'}
					setName={'pets'}
					type={'checkbox'}
					controlFunc={this.handlePetSelection}
					options={this.state.petSelections}
					selectedOptions={this.state.selectedPets} />
				<CheckboxOrRadioGroup
					title={'Are you willing to adopt more than one pet if we have siblings for adoption?'}
					setName={'siblings'}
					controlFunc={this.handleSiblingsSelection}
					type={'radio'}
					options={this.state.siblingOptions}
					selectedOptions={this.state.siblingSelection} />
				<SingleInput
					inputType={'number'}
					title={'How many pets do you currently own?'}
					name={'currentPetCount'}
					controlFunc={this.handleCurrentPetCountChange}
					content={this.state.currentPetCount}
					placeholder={'Enter number of current pets'} />
				<TextArea
					title={'If you currently own pets, please write their names, breeds, and an outline of their personalities.'}
					rows={5}
					resize={false}
					content={this.state.description}
					name={'currentPetInfo'}
					controlFunc={this.handleDescriptionChange}
					placeholder={'Please be thorough in your descriptions'} />
				<input
					type="submit"
					className="btn btn-primary float-right"
					value="Submit"/>
				<button
					className="btn btn-link float-left"
					onClick={this.handleClearForm}>Clear form</button>
			</form>
		);
	}
}

export default FormContainer;


================================================
FILE: src/index.js
================================================
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';

ReactDOM.render(
  <App />,
  document.getElementById('root')
);


================================================
FILE: src/styles.css
================================================
body {
    padding-bottom: 80px;
}
form {
    border: 3px solid #ccc;
    padding: 0 20px 25px 20px;
    border-radius: 10px;
}
input[type=checkbox],
input[type=radio] {
    margin-right: 8px;
}
.form-label.capitalize {
    text-transform: capitalize;
}
.checkbox-group {
    display: flex;
    justify-content: space-between;
    flex-wrap: wrap;
}
.checkbox-group .form-label {
    width: 50%;
}
input[type=submit],
.btn-link {
    margin-top: 20px;
}
Download .txt
gitextract_rlcvmnka/

├── .gitignore
├── .nvmrc
├── README.md
├── package.json
├── public/
│   ├── fake_db.json
│   └── index.html
└── src/
    ├── App.js
    ├── components/
    │   ├── CheckboxOrRadioGroup.js
    │   ├── Select.js
    │   ├── SingleInput.js
    │   └── TextArea.js
    ├── containers/
    │   └── FormContainer.js
    ├── index.js
    └── styles.css
Download .txt
SYMBOL INDEX (14 symbols across 2 files)

FILE: src/App.js
  class App (line 6) | class App extends Component {
    method render (line 7) | render() {

FILE: src/containers/FormContainer.js
  class FormContainer (line 7) | class FormContainer extends Component {
    method constructor (line 8) | constructor(props) {
    method componentDidMount (line 30) | componentDidMount() {
    method handleFullNameChange (line 47) | handleFullNameChange(e) {
    method handleCurrentPetCountChange (line 50) | handleCurrentPetCountChange(e) {
    method handleAgeRangeSelect (line 53) | handleAgeRangeSelect(e) {
    method handlePetSelection (line 56) | handlePetSelection(e) {
    method handleSiblingsSelection (line 66) | handleSiblingsSelection(e) {
    method handleDescriptionChange (line 69) | handleDescriptionChange(e) {
    method handleClearForm (line 76) | handleClearForm(e) {
    method handleFormSubmit (line 87) | handleFormSubmit(e) {
    method render (line 102) | render() {
Condensed preview — 14 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (14K chars).
[
  {
    "path": ".gitignore",
    "chars": 187,
    "preview": "# See http://help.github.com/ignore-files/ for more about ignoring files.\n\n# dependencies\nnode_modules\n\n# testing\ncovera"
  },
  {
    "path": ".nvmrc",
    "chars": 5,
    "preview": "6.2.1"
  },
  {
    "path": "README.md",
    "chars": 558,
    "preview": "### Tutorial: React.js Controlled Form Components\n\nThis repo is the companion to my blog post, [React.js Controlled Form"
  },
  {
    "path": "package.json",
    "chars": 415,
    "preview": "{\n  \"name\": \"react-form-components\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"devDependencies\": {\n    \"react-scripts\""
  },
  {
    "path": "public/fake_db.json",
    "chars": 352,
    "preview": "{\n  \"ownerName\": \"\",\n  \"petSelections\": [\"dog\", \"cat\", \"rabbit\", \"iguana\", \"pony\", \"ferret\", \"fish\", \"bird\"],\n  \"selecte"
  },
  {
    "path": "public/index.html",
    "chars": 1136,
    "preview": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-wid"
  },
  {
    "path": "src/App.js",
    "chars": 517,
    "preview": "import React, { Component } from 'react';\nimport '../node_modules/spectre.css/dist/spectre.min.css';\nimport './styles.cs"
  },
  {
    "path": "src/components/CheckboxOrRadioGroup.js",
    "chars": 910,
    "preview": "import React from 'react';\n\nconst CheckboxOrRadioGroup = (props) => (\n\t<div>\n\t\t<label className=\"form-label\">{props.titl"
  },
  {
    "path": "src/components/Select.js",
    "chars": 660,
    "preview": "import React from 'react';\n\nconst Select = (props) => (\n\t<div className=\"form-group\">\n\t\t<select\n\t\t\tname={props.name}\n\t\t\t"
  },
  {
    "path": "src/components/SingleInput.js",
    "chars": 733,
    "preview": "import React from 'react';\n\nconst SingleInput = (props) => (\n\t<div className=\"form-group\">\n\t\t<label className=\"form-labe"
  },
  {
    "path": "src/components/TextArea.js",
    "chars": 717,
    "preview": "import React from 'react';\n\nconst TextArea = (props) => (\n\t<div className=\"form-group\">\n\t\t<label className=\"form-label\">"
  },
  {
    "path": "src/containers/FormContainer.js",
    "chars": 5709,
    "preview": "import React, {Component} from 'react';\nimport CheckboxOrRadioGroup from '../components/CheckboxOrRadioGroup';\nimport Si"
  },
  {
    "path": "src/index.js",
    "chars": 152,
    "preview": "import React from 'react';\nimport ReactDOM from 'react-dom';\nimport App from './App';\n\nReactDOM.render(\n  <App />,\n  doc"
  },
  {
    "path": "src/styles.css",
    "chars": 453,
    "preview": "body {\n    padding-bottom: 80px;\n}\nform {\n    border: 3px solid #ccc;\n    padding: 0 20px 25px 20px;\n    border-radius: "
  }
]

About this extraction

This page contains the full source code of the lorenseanstewart/react-controlled-form-components GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 14 files (12.2 KB), approximately 3.5k tokens, and a symbol index with 14 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!