Reputation: 1
I'm making a fitness log MEN CRUD app and am trying to push data to a MongoDB subdocument using an HTML form. When adding (creating) a new workout, the user is presented with two options between 'run' or 'weight training'. The button selection takes the user to a form to fill in relevant data like date, time, distance.
I'm able to create each workout, but the data is 'null'.
Models:
const mongoose = require('mongoose');
const RunSchema = new mongoose.Schema({
date: {
type: Number,
required: true,
},
time: Number,
distance: {
type: Number,
required: true,
},
});
const WeightliftingSchema = new mongoose.Schema({
date: {
type: Number,
required: true,
},
time: Number,
exercise: {
type: String,
required: true,
},
notes: String,
});
const workoutSchema = new mongoose.Schema({
run: RunSchema,
weightTraining: WeightliftingSchema,
});
const userSchema = new mongoose.Schema({
username: {
type: String,
required: true,
},
password: {
type: String,
required: true,
},
workouts: [workoutSchema],
});
const User = mongoose.model('User', userSchema);
module.exports = User;
Routers:
router.get('/new', async (req, res) => {
res.render('workouts/new.ejs')
})
router.get('/new/run', async (req, res) => {
res.render('workouts/new/run.ejs')
})
router.get('/new/weightlifting', async (req, res) => {
res.render('workouts/new/weightlifting.ejs')
})
router.post('/', async (req, res) => {
try {
const currentUser = await User.findById(req.session.user._id);
currentUser.workouts.push(req.body)
await currentUser.save();
res.redirect(`/users/${currentUser._id}/workouts`)
} catch (error) {
console.log(error)
res.redirect('/')
}
})
router.post('/:workoutId', async (req, res) => {
try {
const currentUser = await User.findById(req.session.user._id);
const workout = currentUser.workouts.id(req.params.workoutId);
currentUser.workout.run.push(req.body)
res.redirect('workouts/show.ejs', { workout: workout })
} catch (error) {
console.log(error)
res.redirect('/')
}
})
HTML form:
<form action="/users/<%= user._id %>/workouts" method="POST">
<label for="date">date:</label>
<input type="number" id="date" name="date"/>
<label for="time">time:</label>
<input type="number" id="time" name="time"/>
<label for="distance">distance:</label>
<input type="number" id="distance" name="distance"/>
<button type="submit">Add Item</button>
</form>
What I'm going for:
const userSchema = new mongoose.Schema({
username: {
type: String,
required: true,
},
password: {
type: String,
required: true,
},
workouts: [
run: [
date: DATA FROM FORM
time: DATA FROM FORM
distance: DATA FROM FORM
]
weightTraining: [null]
],
});
Edit (adding server.js
):
dotenv.config();
const express = require('express');
const app = express();
const mongoose = require('mongoose');
const methodOverride = require('method-override');
const morgan = require('morgan');
const session = require('express-session');
/* ------------------------------- CONTROLLERS ------------------------------ */
const authController = require('./controllers/auth.js');
const workoutsController = require('./controllers/workouts.js');
const passUserToView = require('./middleware/pass-user-to-view.js');
const isSignedIn = require('./middleware/is-signed-in.js');
const port = process.env.PORT ? process.env.PORT : '3000';
mongoose.connect(process.env.MONGODB_URI);
mongoose.connection.on('connected', () => {
console.log(`Connected to MongoDB ${mongoose.connection.name}.`);
});
app.use(express.urlencoded({ extended: false }));
app.use(methodOverride('_method'));
// app.use(morgan('dev'));
app.use(
session({
secret: process.env.SESSION_SECRET,
resave: false,
saveUninitialized: true,
})
);
/* --------------------------------- ROUTES --------------------------------- */
app.get('/', (req, res) => {
res.render('index.ejs', {
user: req.session.user,
});
});
app.use(passUserToView);
app.use('/auth', authController);
app.use(isSignedIn);
app.use('/users/:userId/workouts', workoutsController);
app.listen(port, () => {
console.log(`The express app is ready on port ${port}!`);
});
I've tried a number of things including:
Upvotes: 0
Views: 49