0
votes

Im struggling to insert array of strings into mongo db collection.

its coming up with an error insert failed: Error: Address must be a string

EDIT

I am generating dynamic form fields for CCs and Attendees, and need to save those values in an array.

here the jQuery snippet:

$(function(){
  $(document).on('focus', 'div.form-group-options div.input-group-option:last-child input', function(){
    var sInputGroupHtml = $(this).parent().html();
    var sInputGroupClasses = $(this).parent().attr('class');
    $(this).parent().parent().append('<div class="'+sInputGroupClasses+'">'+sInputGroupHtml+'</div>');
  });
  $(document).on('click', 'div.form-group-options .input-group-addon-remove', function(){
    $(this).parent().remove();
  });
});

html:

<form class="row form-horizontal newMeeting"> 
  <div class="form-group form-group-options col-xs-11 col-md-3" id="cc">
    <div class="input-group input-group-option col-xs-12">
      <input type="text" name="option[]" class="form-control" id="cc" placeholder="CCs">
      <span class="input-group-addon input-group-addon-remove">
        <span class="glyphicon glyphicon-remove"></span>
      </span>
    </div>
  </div>

  <div class="form-group form-group-options col-xs-11 col-md-3">
    <div class="input-group input-group-option col-xs-12">
      <input type="text" class="form-control" id="attendees" placeholder="Attendees">
      <span class="input-group-addon input-group-addon-remove">
        <span class="glyphicon glyphicon-remove"></span>
      </span>
    </div>
  </div>

  <div class="row no-print">
    <div class="col-xs-12">     
      <input type="submit" value="Save" class="btn btn-primary pull-right">
    </div>
  </div>
</form>

my schema:

Emails = new Mongo.Collection('emails');


EmailSchema = new SimpleSchema({

 "attendeesEmail": {
  type: [Object],
  optional: true
},  
"attendeesEmail.$.address": {
  type: String,
  regEx: SimpleSchema.RegEx.Email
},
ccEmails: {
  type: [Object],
  optional: true
},
"ccEmails.$.address": {
  type: String,
  regEx: SimpleSchema.RegEx.Email
}
});

Emails.attachSchema(EmailSchema);

event:

Template.form.events({
'submit .newMeeting': function(event) {
var cc = $('#cc').serializeArray();
var attendees = $('#attendees').serializeArray();
});

Insert:

Emails.insert({
  attendeesEmail: [{address: attendees}],
  ccEmails: [{address: cc }]
});

console.log(attendees); prints [Object] error message says insert failed: Error: 0 must be a string

I've tried few solutions, but couldn't get it working, any suggestions would be appreciated.

3

3 Answers

0
votes

The .serializeArray() method creates a JavaScript array of objects, ready to be encoded as a JSON string

So cc, attendees are not Strings

You can try to use toSource() method:

var cc = $('#cc').serializeArray().toSource();
var attendees = $('#attendees').serializeArray().toSource();

Or use JSON.stringify method

var cc = JSON.stringify($('#cc').serializeArray());
var attendees = JSON.stringify($('#attendees').serializeArray());

But the toSource method doesn't working on Chrome,IE. It works on Firefox
API Here

   <!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.2/jquery.min.js"></script>
<script>
$(document).ready(function(){
$("button").click(function(){
    var x = $("form").serializeArray();
    alert(JSON.stringify($("form").serializeArray()));
    $.each(x, function(i, field){
        $("#results").append(field.name + ":" + field.value + " ");
    });
});
});
</script>
</head>
<body>

<form action="">
  First name: <input type="text" name="FirstName" value="Mickey"><br>
  Last name: <input type="text" name="LastName" value="Mouse"><br>
</form>

<button>Serialize form values</button>

<div id="results"></div>

</body>
</html>
0
votes

You can solve the issue with updating your events like this.

Template.form.events({
  'submit .newMeeting': function(event) {
     var cc = $('#cc').val();
     var attendees = $('#attendees').val();
});

The issue is occurring due to serializeArray() methods which converting your string to an object, But if you still want to use the serializeArray methods then you can do like this

Template.form.events({
  'submit .newMeeting': function(event) {
     var cc = $('#cc').serializeArray().value;
     var attendees = $('#attendees').serializeArray().value;
});
0
votes

The way you are explicitly defining your schema is wrong, in particular the attendeesEmail and ccEmails properties. If you intend it to be an array of objects then you need to define the array of objects keys explicitly as follows:

Emails = new Mongo.Collection('emails');

EmailSchema = new SimpleSchema({
    "attendeesEmail": {
        type: [Object],
        optional: true
    },  
    "attendeesEmail.$.address": {
        type: String,
        regEx: SimpleSchema.RegEx.Email
    },
    ccEmails: {
        type: [Object],
        optional: true
    },
    "ccEmails.$.address": {
        type: String,
        regEx: SimpleSchema.RegEx.Email
    }
});

Emails.attachSchema(EmailSchema);

Once you have this schema defined then you can implement the insert using the following example as guideline. This assumes user enters a semicolon delimited list of email addresses in the text input. It uses the template scope provided in the event handler which makes code a lot less error prone by scoping to the template and this approach is a slightly cleaner way to do forms in Meteor without all the global jQuery references.

Template code:

<template name="foo">
    <form id="myform" class="newMeeting">
        <input type="text" name="attendees" />
        <input type="text" name="cc" />
        <input type="submit" id="submit" />
    </form>
</template>

Event handler:

Template.foo.events({   
    'submit form': function(event, template) {
        event.preventDefault();

        var attendees = template.find("input[name=attendees]"),
            cc = template.find("input[name=cc]"),
            attendeesList = attendees.split(';').map(function (email){ 
                return { address: email } 
            }),
            ccList = cc.split(';').map(function (email){ 
                return { address: email } 
            });


        // Do form validation

        var data = {
            attendeesEmail: attendeesList,
            ccEmails: ccList
        };

        // Clear form
        attendees.value = "";
        cc.value = "";

        Emails.insert(data, function(err) { /* handle error */ });
    }
});