Search code examples
htmlexpressdatabase-schemamongoose-schemaembedded-documents

how to retrieve the value from a submitted html form and store it inside the nested document in mongoose schema


Mongoose Schema:

const addressSchema = new Schema({
    street: { type: String, trim: true },
    state: { type: String, trim: true , match: [/^[a-zA-Z]{2,}/, 'Please Enter State in a Correct Format']}, 
    zip: {type: Number, match:[/^[0-9]{5}([-][0-9]{3})?$/, 'Please Enter Valid Zip Code']}
});

/*
 * Contact Schema
 */
const contactSchema = new Schema({
    firstName: { type: String, trim: true, required: true },
    lastName: { type: String, required: true, min: 1, trim: true },
    phoneNumber: { type: String, trim: true, match: [/^\d{3}-\d{3}-\d{4}$/, 'Please Enter Valid Phone Number.'], required: true },
    email: { type: String, trim: true, match: [/^(\w{1,})([\.+-]?\w+)?\@[a-z]{1,}([.-]?\w+){1,}?\.[a-z]{2,6}$/, 'Please Enter Valid Email Address.'] },
    address: [addressSchema] //nested instead of a reference
},
    { timestamps: true }
);
module.exports = mongoose.model('Contact', contactSchema);

HTML form using EJS:

<form action="/contacts/new" method="POST">
    <div>
        <label for="first-name">First Name:
        <input type="text" name="firstName">
      </div>

      <div>
        <label for="last-name">Last Name:
        <input type="text" id="last-name" name="lastName">
        </label>
      </div>

      <div>
        <label for="phone"> Phone: 
        <input type="text" id="phone" name="phoneNumber" placeholder="111-111-111">
        </label>
      </div>

      <div>
        <label for="email"> Email: 
        <input type="email" id="email" name="email">
        </label>
      </div>
      <br/>
      <p> Address: </p>
      <br />
      <div>
        <label for="street-address"> Street: 
        <input type="text" id="street-address" name="street">
        </label>
      </div>

      <div>
        <label for="state-address"> State: 
        <input type="text" id="state-address" name="state">
        </label>
      </div>

      <div>
        <label for="zip-address"> Zip Code: 
        <input type="number" id="zip-address" name="zip">
        </label>
      </div>
</form>

my controller is as follows:

module.exports.addNewContact = async (req, res, next) => {
    try {
        let newContact = new ContactModel(req.body);
        await newContact.save();
        res.redirect('/contacts');
    } catch (err) {
        console.log(err);
    }
};

this is what get's stored in the database

{
  _id: 6044570c86de7d07d93e1be5,
  firstName: 'Luna',
  lastName: 'hh',
  phoneNumber: '123-123-1232',
  email: 'luna@yahoo.com',
  address: []
}

This is what I get for my req.body

[Object: null prototype] {
  firstName: 'Tetet',
  lastName: 'Tic',
  phoneNumber: '123-123-1232',
  email: '',
  street: 'King AS',
  state: '',
  zip: '12333'
}

My question is how do you even retrieve all the key from the form and store it inside the addressSchema? I was thinking that adding req.body when instantiating the ContactModel object would get all the values and add it to the respective schema.


Solution

  • So basically all i had to do was push additional address to the object.

    module.exports.addNewContact = async (req, res, next) => {
        try {
            let newContact = new ContactModel(req.body);
    
            //since addressSchema field is empty, I had to push the address field again
            newContact.address.push(req.body);
    
            await newContact.save();
            res.redirect('/contacts');
        } catch (err) {
            console.log(err);
        }
    };