Hello all! I’ve been lurking on these forums for a few months and I really appreciate all the good information.
I’ve been modifying the Meteor1.3+React Todos app to get the basics down and it’s been going well so far. However, i’d like to add another text field so that the user can submit a description of an item (the first field that comes with the Todos app) as well as the cost of that item. I’ve been trying to add the second input field and copy over the values/pass them through to the tasks.js api but I can’t seem to get it to work. I’m aware that this is aesthetically unsettling (hitting enter to input two text fields into a collection) and it may be impossible/is most likely not the correct way to do something like this.
Here’s what I’m working with:
App.jsx
import React, { Component, PropTypes } from 'react'; import ReactDOM from 'react-dom'; import { Meteor } from 'meteor/meteor'; import { createContainer } from 'meteor/react-meteor-data';
import { Tasks } from '../api/tasks.js'; import Task from './Task.jsx'; import AccountsUIWrapper from './AccountsUIWrapper.jsx';
// App component - represents the whole app //render collection of tasks class App extends Component { //componenet contructor that contains initializations for: hideCompleted constructor(props) { super(props);
this.state = { hideCompleted: false, }; }
//Event handler for when you press enter to input data. Calls Meteor method tasks.insert and sends it the text, //then clears the text form handleSubmit(event) { event.preventDefault();
// Find the task text field via the React ref const taskText = ReactDOM.findDOMNode(this.refs.textInput).value.trim(); // Find the cost field via the React ref const costNum = ReactDOM.findDOMNode(this.refs.costInput).value.trim();
//Call the tasks insert method in tasks.js api Meteor.call('tasks.insert', taskText, costNum);
// Clear task form ReactDOM.findDOMNode(this.refs.textInput).value = ''; //Clear cost form ReactDOM.findDOMNode(this.refs.textInput).value = '';
}
//Event handler for hideCompleted checkbox check toggleHideCompleted() { this.setState({ hideCompleted: !this.state.hideCompleted, }); }
//Filters out tasks that have hideCompleted === true renderTasks() { let filteredTasks = this.props.tasks; if (this.state.hideCompleted) { filteredTasks = filteredTasks.filter(task => !task.checked); } return filteredTasks.map((task) => ( <Task key={task._id} task={task} /> )); }
render() { return ( <div className="container"> <header> <h1>The Economy</h1> ({this.props.incompleteCount}) <label className="hide-completed"> <input type="checkbox" readOnly checked={this.state.hideCompleted} onClick={this.toggleHideCompleted.bind(this)} /> Hide Completed Tasks </label>
<AccountsUIWrapper />
{ this.props.currentUser ? <form className="new-task" onSubmit={this.handleSubmit.bind(this)} > <input type="text" ref="textInput" placeholder="Type to add new tasks" /> <input type="Number" ref="costInput" placeholder="Type to add cost" /> </form> : '' } </header>
<ul> {this.renderTasks()} </ul> </div> ); } }
//proptypes - set up the tasks proptype App.propTypes = { tasks: PropTypes.array.isRequired, incompleteCount: PropTypes.number.isRequired, currentUser: PropTypes.object, };
//exports createContainer function which queries the tasks collection export default createContainer(() => { return { tasks: Tasks.find({}, { sort: { createdAt: -1 } }).fetch(), incompleteCount: Tasks.find({ checked: { $ne: true } }).count(), currentUser: Meteor.user(), // currentBalance: Tasks.characters.aggregate([ { $group: { _id: null, total: { $sum: "$cost" } } } ]), }; }, App);
tasks.js
import { Meteor } from 'meteor/meteor'; import { Mongo } from 'meteor/mongo'; import { check } from 'meteor/check';
export const Tasks = new Mongo.Collection('tasks');
Meteor.methods({ 'tasks.insert'(text, cost) { //Make sure that text is a String check(text, String); //Make sure that cost is a Number check(cost, Number);
// Make sure the user is logged in before inserting a task if (! this.userId) { throw new Meteor.Error('not-authorized'); }
//Actual database insertion Tasks.insert({ text, cost, createdAt: new Date(), owner: this.userId, username: Meteor.users.findOne(this.userId).username, }); }, 'tasks.remove'(taskId) { check(taskId, String);
Tasks.remove(taskId); }, 'tasks.setChecked'(taskId, setChecked) { check(taskId, String); check(setChecked, Boolean);
Tasks.update(taskId, { $set: { checked: setChecked } }); }, });
I feel like there’s some type of simple answer out there but after a while of searching, I can’t seem to find anything that makes sense to me. I haven’t dabbled in any React forms packages yet because I thought i’d be able to do this without one. I feel bad about asking about something seemingly so simple but alas here I am. Any recommended reading or methods to look into is greatly appreciated.