flo
flo

Reputation: 1

How can I use push() with router.post to populate a subdocument with contents from an HTML form?

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

Answers (0)

Related Questions