В Meteor, как я могу проверить с помощью Collection2 на стороне клиента?

Я всегда использую методы для вставки, обновления и удаления. Вот как мой код выглядит сейчас:

Сторона клиента

Template.createClient.events({
  'submit form': function(event, tmpl) {
    e.preventDefault();
    var client = {
      name: event.target.name.value,
      // .... more fields
    }

    var validatedData = Clients.validate(client);
    if (validatedData.errors) {
      // Display validation errors
      return;
    }

    Meteor.call('createClient', validatedData.client, function(error) {
      if (error)
        // Display error
    });
  }
});

Клиентская и серверная часть:

Clients = new Mongo.Collection("clients");

Clients.validate = function(client) {
  // ---- Clean data ----
  client.name = _.str.trim(client.name);
  // .... more fields clean

  // ---- Validate data ---
  var errors = [];
  if (!client.name)
    errors.push("The name is required.");
  // .... more fields validation

  // Return and object with errors and cleaned data
  return { errors: _.isEmpty(errors) ? undefined : errors, client: client };
}

Meteor.methods({
  'createClient': function (client) {
    // --- Validate user permisions ---

    // If server, validate data again
    if (Meteor.isServer) {
      var validatedData = Clients.validate(client);
      if (validatedData.errors)
        // There is no need to send a detailed error, because data was validated on client before
        throw new Meteor.Error(500, "Invalid client."); 
      client = validatedData.client;
    }

    check(client, {
      name: String,
      // .... more fields
    });

    return Clients.insert(client);
  }
});

Meteor.call выполняется на стороне клиента и сервера, но у Meteor нет способа остановить работу на стороне сервера, если проверка на стороне клиента не удалась (или, по крайней мере, я не знаю, как это сделать). С помощью этого шаблона я избегаю отправки данных на сервер с помощью Meteor.call, если проверка не удалась.

Я хочу начать использовать Collection2, но не могу понять, как получить такой же шаблон. Все примеры, которые я нашел, включают использование прямой вставки и обновления на стороне клиента и разрешения/запрета для управления безопасностью, но я хочу придерживаться Meteor.call.

Я нашел в документации, которую я могу проверить перед вставкой или обновлением, но я не знаю, как заставить это работать:

Books.simpleSchema().namedContext().validate({title: "Ulysses", author: "James Joyce"}, {modifier: false});

Я знаю пакет autoform, но пока не хочу его использовать.

Как я могу проверить с помощью Collection2 на стороне клиента перед отправкой данных на сервер с помощью Meteor.call? Является ли мой шаблон неверным или несовместимым с Collection2, и мне нужно сделать это другим способом?


person Camilo    schedule 17.05.2015    source источник


Ответы (2)


Менее чем за 30 строк вы можете написать свой собственный полнофункциональный пакет проверки для Collection2. Давайте рассмотрим пример:

"use strict"; //keep it clean
var simplyValid = window.simplyValid = {}; //OK, not that clean (global object)
simplyValid.RD = new ReactiveDict(); //store error messages here

/**
 * 
 * @param data is an object with the collection name, index (if storing an array), and field name, as stored in the schema (e.g. 'foo.$.bar')
 * @param value is the user-inputted value
 * @returns {boolean} true if it's valid
 */
simplyValid.validateField = function (data, value) {
  var schema = R.C[data.collection]._c2._simpleSchema; //access the schema from the local collection, 'R.C' is where I store all my collections
  var field = data.field;
  var fieldVal = field.replace('$', data.idx); //make a seperate key for each array val
  var objToValidate = {};
  var dbValue = schema._schema[field].dbValue; //custom conversion (standard to metric, dollars to cents, etc.) IGNORE

  if (dbValue && value) value = dbValue.call({value: value}); //IGNORE
  objToValidate[field] = value; //create a doc to clean
  schema.clean(objToValidate, {removeEmptyStrings: false}); //clean the data (trim, etc.)
  var isValid = schema.namedContext().validateOne(objToValidate, field, {extendedCustomContext: true}); //FINALLY, we validate
  if (isValid) {
    simplyValid.RD.set(fieldVal, undefined); //The RD stores error messages, if it's valid, it won't have one
    return true;
  }
  var errorType = schema.namedContext()._getInvalidKeyObject(field).type; //get the error type
  var errorMessage = schema.messageForError(errorType, field); //get the message for the given error type
  simplyValid.RD.set(fieldVal, errorMessage); //set the error message. it's important to validate on error message because changing an input could get rid of an error message & produce another one
  return false;
};
simplyValid.isFieldValid = function (field) {
  return simplyValid.RD.equals(field, undefined); //a very cheap function to get the valid state
};

Не стесняйтесь вырезать части, которые вам нужны, и задавайте мне любые вопросы, которые у вас могут возникнуть.

person Matt K    schedule 18.05.2015

Вы можете отправить схему клиенту и проверить ее перед отправкой на сервер. Если вы хотите использовать «Коллекцию», вам нужно прикрепить схему к коллекции и использовать insert, что вам не нужно. Поэтому лучший вариант для вашего сценария — отправить схему клиенту и использовать ее для подтвердить.

Также пересмотрите возможность использования mini-mongo вместо использования методов для всего, это сэкономит вам много времени и не будет думать, что ваше приложение безопасно только потому, что вы используете методы.

person Mário    schedule 18.05.2015