【问题标题】:On Meteor, how can I validate with Collection2 on the client side?在 Meteor 上,如何在客户端使用 Collection2 进行验证?
【发布时间】:2015-07-29 08:35:02
【问题描述】:

我总是使用方法来插入、更新和删除。这是我的代码现在的样子:

客户端

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 包,但我现在想避免使用该包。

在使用 Meteor.call 将数据发送到服务器端之前,如何在客户端使用 Collection2 进行验证?我的模式是否错误或与 Collection2 不兼容,我需要以其他方式进行吗?

【问题讨论】:

    标签: meteor meteor-collection2


    【解决方案1】:

    您可以在 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
    };
    

    随意破解你需要的部分,并把你可能有的任何问题告诉我。

    【讨论】:

      【解决方案2】:

      您可以将架构发送到客户端并在发送到服务器之前进行验证。如果您想使用 Collection”,您需要将架构附加到集合并使用 insert,这是您不想要的。因此,对于您的场景,最好的选择是将架构发送到客户端并使用它来验证。

      还要重新考虑使用 mini-mongo 而不是对所有事情都使用方法,它会为您节省大量时间,并且不要认为您的应用程序是安全的,因为您正在使用方法。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-02-04
        • 2020-12-26
        • 2012-12-06
        • 1970-01-01
        • 1970-01-01
        • 2018-04-07
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多