[SOLVED] Auto-create a post on "New" to support auto-saving of changes

TL:DR
I am not able to get Iron Router to wait for a record to be created and then pass the id of that record to the current route. I have tried finding answers to this in the Iron Router Guide and elsewhere, but nothing seems to work.


  • I am working on a note-taking app, mostly for learning purposes.
  • I would like to implement my note form such that changes are auto-saved as I type (for example, something like this)

My Goal: the experience I would like to support

  1. User clicks on “New Note”
  2. A blank note form is displayed
  3. As the user types, changes are auto-saved.

What I’m assuming
For this to be possible, I am assuming that, on click of “New Note” that I will need to actually create a note for it to be possible to auto-save changes as they type. Is this a correct assumption? I don’t see any other way to be able to auto-save without having a note id in the params.

The issue
On create of a new note in my controller, I am not able to get the controller to wait for note creation to complete and instead get the following error:

Error: Missing required parameters on path "/notes/:_id/edit". The missing params are: ["_id"]. The params object passed in was: undefined.

My current Code for creating a note on “New Note” Action

(1) On click on “New Note” button:

Session.set("newNote", true); Router.go('edit_note'); // Is the issue that Iron Router is expecting an id value already here, which is why everything else appears to be ignored? If so, can I use a different method to call the controller which doesn't expect the param value?

(2) In the EditPostController, I have a before action that creates a new note if the session variable returns true. However, it appears that the before action either doesn’t run at all or doesn’t complete.

EditPostController = RouteController.extend({
  template:'edit_post',
  onBeforeAction: function (){
    
    if (Session.get("newPost")){
      var postAttributes = {
        title: "New Post"
      };
   
    //My goal here is to get the newly created id and pass it into params - this is likely incorrect - any suggestions on how to fix this?    
    this.params._id = Meteor.call('createPost', postAttributes, function(error, result){
      if (error){
        alert(error.reason);
      } else {
         return result._id;
      };
    });
  };

      this.next();
  },
  waitOn: function () {
      // It does not appear as if this actually waits for the before action to complete
      return Meteor.subscribe('posts', this.params._id).wait();
  },
  data: function() {
       return Posts.findOne({ _id: this.params._id });      
  },
  action: function(){
   // this also does not appear to have any impact
    if (this.ready()) {
      this.render();
    } else {
      this.render('Loading');
    };
  }
});

Why not just call that Router.go in callback of method used to create that note. Or insert callback, if you are using direct collection inserts ? In both cases you will have _id in result.

1 Like

@shock - yes, I was just looking at the code and realizing that the issue might be in the Router.go call. Thanks for the suggestion!

Yes, that was the issue. It’s obvious now that that is what I should have done.

 "click .new-note": function(event) {
    event.preventDefault();
    
    var noteAttributes = {
      title: "New Note"
    };

    Meteor.call('createNote', noteAttributes, function(error, result){
      if (error){
        alert(error.reason);
      } else {
        Router.go('edit_note', {_id: result._id});
      };
    });
 }

and…

EditNoteController = RouteController.extend({
  template:'edit_note',
  waitOn: function () {
    return Meteor.subscribe('notes', this.params._id);   
  },
  data: function() {
    return Notes.findOne({ _id: this.params._id });   
  },
  action: function(){
    if (this.ready()) {
      this.render();
    } else {
      this.render('Loading');
    };
  }
});