javascript - 多个 View 中出现 Backbone.js 验证错误

标签 javascript backbone.js

作为学习练习,我在使用 backbone.js 应用时遇到了问题。我设置了一个 jsfiddle

这是 JavaScript:

var app = {};
$(document).ready(function() {

  app.Contact = Backbone.Model.extend({
    defaults: {
      firstName: '',
      lastName: '',
      email: ''
    },
    validate: function(attrs) {
      var errors = [];
      if (attrs.firstName.trim() == "") {
        errors.push({
          'message': 'Please enter a first name.',
          'field': 'firstName'
        });
      }
      if (attrs.lastName.trim() == "") {
        errors.push({
          'message': 'Please enter a last name.',
          'field': 'lastName'
        });
      }
      if (attrs.email.trim() == "") {
        errors.push({
          'message': 'Please enter an email address.',
          'field': 'email'
        });
      }
      if (errors.length) {
        return errors;
      } else {
        return false;
      }
    }
  });

  app.ContactList = Backbone.Collection.extend({
    model: app.Contact,
    localStorage: new Store('backbone-addressbook')
  });

  app.contactList = new app.ContactList();

  app.ContactView = Backbone.View.extend({
    tagName: 'tr',
    template: _.template($('#contact-template').html()),
    render: function() {
      this.$el.html(this.template(this.model.toJSON()));
      return this;
    },
    initialize: function() {
      this.model.on('change', this.render, this);
      this.model.on('destroy', this.remove, this);
      var self = this;
      this.model.on('invalid', function(model, errors) {
        _.each(errors, function(error, i) {
          console.log(self.el);
          $(self.el).find('[data-field="' + error.field + '"]').parent().addClass('has-error');
          $(self.el).find('[data-field="' + error.field + '"]').parent().find('.help-block').remove();
          $(self.el).find('[data-field="' + error.field + '"]').parent().append('<span class="help-block">' + error.message + '</span>');
        });
      });
      this.model.on('change', function(model, response) {
        //console.log(self.el);
        $(self.el).removeClass('editing');
        this.render;
      })
    },
    events: {
      'dblclick label': 'edit',
      'keypress .edit': 'updateOnEnter',
      'click .destroy': 'destroy',
      'click .save': 'close'
    },
    edit: function(e) {
      this.$el.addClass('editing');
      $(e.currentTarget).next('input').focus();
    },
    updateOnEnter: function(e) {
      if (e.which == 13) {
        this.close(e);
      }
    },
    close: function(e) {
      e.preventDefault();
      var updateObject = {};
      $(this.el).find('input[type="text"]').each(function() {
        node = $(this);
        updateObject[node.data('field')] = node.val();
      });
      this.model.save(updateObject, {validate: true});
    },
    destroy: function() {
      this.model.destroy();
    }
  });

  app.AppView = Backbone.View.extend({
    el: '#newContact',
    initialize: function() {
      $(this).find('.has-error').removeClass('has-error');
      $(this).remove('.help-block');
      app.contactList.on('add', this.addOne, this);
      app.contactList.fetch();
      var self = this;
      app.contactList.on('invalid', function(model, errors) {
        _.each(errors, function(error, i) {
          console.log(self.el);
          $(self.el).find('[data-field="' + error.field + '"]').parent().addClass('has-error');
          $(self.el).find('[data-field="' + error.field + '"]').parent().find('.help-block').remove();
          $(self.el).find('[data-field="' + error.field + '"]').parent().append('<span class="help-block">' + error.message + '</span>');
        });
      });
    },
    events: {
      'click .add': 'createContact'
    },
    createContact: function(e) {
      e.preventDefault();
      app.contactList.create(this.newAttributes(), {validate: true});
    },
    addOne: function(contact) {
      var view = new app.ContactView({model: contact});
      $('#contactList').append(view.render().el);
      $('form input[type="text"]').val('');
      $('form input[type="text"]').parent().removeClass('has-error');
      $('.help-block').remove();
    },
    newAttributes: function() {
      var updateObject = {};
      $(this.el).find('input[type="text"]').each(function() {
        node = $(this);
        updateObject[node.data('field')] = node.val();
      });
      return updateObject;
    },
  });

  app.appView = new app.AppView();

});

这是 HTML:

<div class="container">
  <section id="addressbookapp">
      <header id="header">
          <h1>Address Book</h1>
          <div class="well">
          <form id="newContact" action="#" role="form">
              <div class="form-group">
                  <label class="control-label" for="firstName">First Name</label>
                  <input data-field="firstName" class="newFirstName form-control input-sm" type="text" />
              </div>
              <div class="form-group">
                  <label class="control-label" for="lastName">Last Name</label>
                  <input data-field="lastName" class="newLastName form-control input-sm" type="text" />
              </div>
              <div class="form-group">
                  <label class="control-label" for="email">Email Address</label>
                  <input data-field="email" class="newEmail form-control input-sm" type="text" />
              </div>
              <button class="add btn-xs">Add</button>
          </form>
          </div>
      </header>
      <section id="main">
          <table class="table table-striped">
              <caption>Double-click to edit an entry.</caption>
              <thead>
                  <tr>
                      <th>First</th>
                      <th>Last</th>
                      <th>Email</th>
                      <th></th>
                  </tr>
              </thead>
              <tbody id="contactList"></tbody>
          </table>
      </section>
  </section>
</div>
<script id="contact-template" type="text/template">
    <form action="#" role="form">
      <td>
        <label class="control-label" for="firstName"><%- firstName %></label>
        <input data-field="firstName" class="firstName input-sm edit" value="<%- firstName %>" type="text" />
      </td>
    <td>
      <label class="control-label" for="lastName"><%- lastName %></label>
      <input data-field="lastName" class="lastName input-sm edit" value="<%- lastName %>" type="text" />
    </td>
    <td>
      <label class="control-label" for="email"><%- email %></label>
      <input data-field="email" class="email input-sm edit" value="<%- email %>" type="email" />
    </td>
    <td>
      <button class="btn-xs save">Save</button>
      <button class="btn-xs destroy">Delete</button>
    </td>
  </form>
</script>

具体来说,当用户编辑列表中的条目(通过双击)、清除输入(例如姓氏)然后尝试保存时,会(正确地)出现验证错误。问题是顶部的表单(用于创建新条目)也在响应无效事件。

我的问题不仅是如何防止这种情况发生,而且什么是组织事物的理想方式。这对我来说是一个学习练习,所以我非常感谢您提供任何提示 - 任何您看到的可以改进的地方。

最佳答案

这是由于您构建应用程序的方式:在“新建”和“编辑”表单中,您告诉应用程序“如果集合中存在验证问题则显示错误消息”。因此,当您尝试编辑现有模型并且存在验证问题时,"new"表单会更新以显示错误。

相反,您需要做的是以"new"形式使用新(空白)模型,如果未通过验证则显示错误,如果有效则将其添加到集合中。这样,两种形式的错误都由不同的机制处理,不会重叠。

参见 http://jsfiddle.net/n9yq2/3/

app.AppView = Backbone.View.extend({
    el: '#newContact',
    initialize: function() {
      this.model = new app.Contact();

    // edited for brevity

    this.model.on('invalid', function(model, errors) {
        _.each(errors, function(error, i) {



createContact: function(e) {
      e.preventDefault();
        var attrs = this.newAttributes();
        if(this.model.set(attrs, {validate: true})){
          app.contactList.create(attrs);
      }
    },

关于javascript - 多个 View 中出现 Backbone.js 验证错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23176293/

相关文章:

javascript - 使用 float 时如何消除垂直间隙

javascript - 当我有部分名称时,使用 getelementsbyname (在 Ajax html 响应中)。

JavaScript开发和生产模式

javascript - Backbone : Correct way of passing 'this' reference to anon functions in success/error callbacks

backbone.js - 哪些参数被传递给绑定(bind)到 Backbone.Model 更改事件的处理程序?

javascript - 如何在 Vue 3 中替换 this.$parent.$emit?

javascript - 使用 Django 模板变量时如何延迟 JavaScript?

javascript - knockoutjs - 渲染模板或 foreach 到自身

backbone.js - 无声模型有可能被破坏吗

javascript - Backbone SPA : Best practice for loading new routes?