使用 Backbone 验证插件选择性地验证模型属性?

Selectively validate model attributes using Backbone Validation plugin?

我正在使用 Backbone Validation plugin 并希望在不同时间选择性地验证不同的模型属性集,这可能吗?

我的测试模型对 nameageaddress 进行了验证,如果我只想验证 address,我该怎么做?

我认为这是调用 this.model.validate('address'); 的情况,但所有验证规则似乎 运行?

JS

    console.clear();


const Model = Backbone.Model.extend({
    validation: {
    name: {
        required: true
    },
    age: {
      range: [1, 80],
      required: true
    },
    address: {
        minLength: 1,
        msg: 'Address required',
      required: false
    }
  }
});
const View = Backbone.View.extend({

    template: Handlebars.compile( $('.tmpl-person').html() ),

    className: 'view',

    events: {
        'click .js-action--validate-keys': 'actionValidateKeysClicked',
        'click .js-action--validate-key': 'actionValidateKeyClicked'
    },

    initialize() {
        Backbone.Validation.bind(this);

        this.listenTo(this.model, 'validated', this.onModelValidated, this);
        this.listenTo(this.model, 'validated:valid', this.onModelValid, this);
        this.listenTo(this.model, 'validated:invalid', this.onModelInvalid, this);
    },

    render() {
        this.$el.html(this.template(this.model.toJSON()));
        return this;
    },

    actionValidateKeysClicked(event) {
        event.preventDefault();
        console.log('actionValidateKeysClicked');

        this.model.set({
            'name': 'Joe Bloggs',
            'age': 23
        });

        this.model.validate(['name', 'age']);
    },

    actionValidateKeyClicked(event) {
        event.preventDefault();
        console.log('actionValidateKeyClicked');
        this.model.set('address', '123 ABC');
        this.model.validate('address');
    },

  /**
   *    The validated event is triggered after validation is performed, either it was successful or not.
   *    isValid is true or false depending on the result of the validation.
   */
  onModelValidated(isValid, model, errors) {
    console.log('onModelValidated', isValid, model, errors);
  },

  onModelValid(model) {
    console.log('onModelValid', model);
  },

  onModelInvalid(model, errors) {
    console.log('onModelInvalid', model, errors);
  }
});

const newModel = new Model();
const newView = new View({
    model: newModel
});


document.body.append(newView.render().el);

JSfiddle http://jsfiddle.net/kyllle/qmx2y9yr/

isValid

要仅验证某些字段,Backbone.Validation offers a modified version of isValid

If you pass the name of an attribute or an array of names, you can check whether or not the attributes are valid:

// Check if name is valid
var isValid = model.isValid('name');

// Check if name and age are valid
var isValid = model.isValid(['name', 'age']);

isValid 将仅在验证出现错误时触发 'invalid' 事件 (source),而不会触发 'validated' 事件或 'validated:valid'.

preValidate

Sometimes it can be useful to check (for instance on each key press) if the input is valid - without changing the model - to perform some sort of live validation. You can execute the set of validators for an attribute, or a hash of attributes, by calling the preValidate method and pass it the name of the attribute and the value to validate, or a hash of attributes.

If the value is not valid, the error message is returned (truthy), otherwise it returns a falsy value.

// Validate one attribute
// The `errorsMessage` returned is a string
var errorMessage = model.preValidate('attributeName', 'Value');

// Validate a hash of attributes
// The errors object returned is a key/value pair of attribute name/error, e.g
// {
//   name: 'Name is required',
//   email: 'Email must be a valid email'
// }
var errors = model.preValidate({name: 'value', email: 'foo@example.com'});

演示

我拿了你的代码在下面做了一个小例子来演示使用isValid时不触发无效事件,但使用validate时会触发。另外,请注意 preValidate.

不会触发任何事件

const Model = Backbone.Model.extend({
  validation: {
    name: {
      required: true
    },
    age: {
      range: [1, 80],
      required: true
    },
    address: {
      minLength: 1,
      msg: 'Address required',
      required: true
    }
  }
});

const View = Backbone.View.extend({

  template: $('.tmpl-person').html(),

  className: 'view',

  events: {
    'click .validate': 'onValidateClick',
    'click .is-valid': 'onIsValidClick',
    'click .pre-validate': 'onPreValidateClick',
  },

  initialize() {
    Backbone.Validation.bind(this);

    this.listenTo(this.model, {
      'all': this.onAllModelEvent,
      //  'validated': this.onModelValidated,
      //  'validated:valid': this.onModelValid,
      //  'validated:invalid': this.onModelInvalid
    });

  },

  render() {
    this.$el.html(this.template);
    this.$checkbox = this.$('.invalid');
    return this;
  },

  getAddress() {
 
    return this.$checkbox.is(':checked') ? null : '123 ABC';
  },

  onValidateClick() {
    console.log('validate click');
    this.model.set('address', this.getAddress());
    console.log("validate:", this.model.validate('address'));
  },

  onIsValidClick() {
    console.log('isValid click');
    this.model.set('address', this.getAddress());
    console.log("isValid:", this.model.isValid('address'));
  },

  onPreValidateClick() {
    console.log('preValidate click');
    this.model.set('address', this.getAddress());

    console.log("preValidate:", this.model.preValidate('address'));
  },

  onAllModelEvent: function(event) {
    console.log("event:", event);
  }

});

const newModel = new Model();
const newView = new View({
  model: newModel
});


document.body.append(newView.render().el);
* {
  -webkit-font-smoothing: antialiased;
}
body {
  padding: 5%;
  font-size: 16px;
  line-height: 1.4;
}
.view {
  width: 100%;
  height: 100vh;
  background: lightBlue;
}
.btn {
  outline: none;
  border: none;
  background: #1C90F3;
  border-radius: 4px;
  color: white;
  padding: 15px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.3.3/backbone-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.validation/0.11.5/backbone-validation-min.js"></script>
<script type="text/template" class="tmpl-person">
  Set 'address' and use:
  <button type="button" class="btn validate">validate</button>
  <button type="button" class="btn is-valid">isValid</button>
  <button type="button" class="btn pre-validate">preValidate</button>
  <br>
  <input type="checkbox" class="invalid">make address invalid.
</script>

附加信息


旁注

请注意我是如何对一个对象使用 listenTo 而不是调用它 3 次。

this.listenTo(this.model, {
    'validated': this.onModelValidated,
    'validated:valid': this.onModelValid,
    'validated:invalid': this.onModelInvalid
});

此外,没有 this 参数传递给 listenTo,这可能与旧的 on/bind 语法混淆。