Home > Mobile >  Meteor Client calling findOne in Server Method
Meteor Client calling findOne in Server Method

Time:12-01

I have a client-side form that can create a document upon submission. I want to see if one of the input fields already exists on a Document in the DB though. This would then alert the user and ask them if they want to continue creating the record.

Client-side event

Template.createDoc.events({
    'click button[type=submit]'(e, template) {

        //This particular example is checking to see if a Doc with its `name` property set to `value` already exists

        const value = $('#name');
        const fieldName = 'name';

        const exists = Meteor.call('checkIfFieldExistsOnDoc', fieldName, value);
        if (exists) {
            if (confirm(`Doc with ${value} as its ${fieldName} already exists. Are you sure you want to continue creating Doc?`) {
               //db.Docs.insert....
           }
        }
    }
});

Server-side Meteor Method

'checkIfFieldExistsOnDoc'(field, val) {
    
    if (this.isServer) {
      this.unblock();
      check(field, String);
      check(val, String);

      if (!this.userId) {
        throw new Meteor.Error('not-authorized', 'You are not authorized.');
      }

      const findObj = {};
      findObj[field] = val;

      const fieldsObj = {};
      fieldsObj[fieldsObj] = 1;

      const doc = Docs.findOne(findObj, {fields: fieldsObj});
      return doc;
    }
  },

My issue is that the client-side code always gets undefined back when calling the Server method. I now understand why, however, I'm not keen on wrapping all of my subsequent client-code into a callback yet.

So - any other ideas on how I can attempt to do this simple feature?

Also - I was thinking of having the client-side page's onCreated do a 1-time server call to get ALL names for all Docs, storing this in memory, and then doing the check upon form submission using this. Obviously, this is inefficient and not-scalable, although it would work

CodePudding user response:

Meteor.call in the client side is always an async call. Then you need implement a callback.

See docs: https://docs.meteor.com/api/methods.html#Meteor-call

Meteor.call('checkIfFieldExistsOnDoc', fieldName, value, function(error, result) {
  if (result) {
    if (confirm(`Doc with ${value} as its ${fieldName} already exists. Are you sure you want to continue creating Doc?`) {
      //db.Docs.insert....
    }
  }
});

CodePudding user response:

On the client, you can wrap any Meteor.call with a Promise and then use it with async/await. There are some packages on Atmosphere that do this for you to.

I've used this package for years: https://atmospherejs.com/deanius/promise

On the client I often just use await Meteor.callPromise() which returns a response nicely.

Here are a couple of the best write-ups on the many options available to you:

  1. https://blog.meteor.com/using-promises-on-the-client-in-meteor-fb4f1c155f84
  2. https://forums.meteor.com/t/meteor-methods-return-values-via-promise-async/42060
  3. https://dev.to/jankapunkt/async-meteor-method-calls-24f9
  • Related