主干-验证不用于创建,仅用于更新/编辑

Backbone - Validation not working on create, only update/edit?

本文关键字:用于 更新 编辑 创建 验证 主干      更新时间:2023-09-26

因此,当我编辑现有项目时,我能够很好地进行验证。然而,如果我想创建,出于某种原因的验证不会被启动。相反,我看到了以下错误:

//this is if the field I want to validate is empty
Uncaught TypeError: Object #<Object> has no method 'get'
//this is if everything in the form is filled out
Uncaught TypeError: Cannot call method 'trigger' of undefined

这是我js的相对部分。很抱歉,如果这是一个过载,我想添加尽可能多的内容,尽可能具体:

Comic = Backbone.Model.extend({
    initialize: function () {
        this.bind("error", this.notifyCollectionError);
        this.bind("change", this.notifyCollectionChange);
    },
    idAttribute: "ComicID",
    url: function () {
        return this.isNew() ? "/comics/create" : "/comics/edit/" + this.get("ComicID");
    },
    validate: function (atts) {
        if ("Name" in atts & !atts.Name) {
            return "Name is required";
        }
        if ("Publisher" in atts & !atts.Publisher) {
            return "Publisher is required";
        }
    },
    notifyCollectionError: function (model, error) {
        this.collection.trigger("itemError", error);
    },
    notifyCollectionChange: function () {
        this.collection.trigger("itemChanged", this);
    }
});
Comics = Backbone.Collection.extend({
    model: Comic,
    url: "/comics/comics"
});
comics = new Comics();
FormView = Backbone.View.extend({
    initialize: function () {
        _.bindAll(this, "render");
        this.template = $("#comicsFormTemplate");
    },
    events: {
        "change input": "updateModel",
        "submit #comicsForm": "save"
    },
    save: function () {
        this.model.save(
            this.model.attributes,
            {
                success: function (model, response) {
                    model.collection.trigger("itemSaved", model);
                },
                error: function (model, response) {
                    model.trigger("itemError", "There was a problem saving " + model.get("Name"));
                }
            }
        );
        return false;
    },
    updateModel: function (evt) {
        var field = $(evt.currentTarget);
        var data = {};
        var key = field.attr('ID');
        var val = field.val();
        data[key] = val;
        if (!this.model.set(data)) {
            //reset the form field
            field.val(this.model.get(key));
        }
    },
    render: function () {
        var html = this.template.tmpl(this.model.toJSON());
        $(this.el).html(html);
        $(".datepicker").datepicker();
        return this;
    }
});
NotifierView = Backbone.View.extend({
    initialize: function () {
        this.template = $("#notifierTemplate");
        this.className = "success";
        this.message = "Success";
        _.bindAll(this, "render", "notifySave", "notifyError");
        comics.bind("itemSaved", this.notifySave);
        comics.bind("itemError", this.notifyError);
    },
    events: {
        "click": "goAway"
    },
    goAway: function () {
        $(this.el).delay(0).fadeOut();
    },
    notifySave: function (model) {
        this.message = model.get("Name") + " saved";
        this.render();
    },
    notifyError: function (message) {
        this.message = message;
        this.className = "error";
        this.render();
    },
    render: function () {
        var html = this.template.tmpl({ message: this.message, className: this.className });
        $(this.el).html(html);
        return this;
    }
});
var ComicsAdmin = Backbone.Router.extend({
    initialize: function () {
        listView = new ListView({ collection: comics, el: "#comic-list" });
        formView = new FormView({ el: "#comic-form" });
        notifierView = new NotifierView({el: "#notifications" });
    },
    routes: {
        "": "index",
        "edit/:id": "edit",
        "create": "create"
    },
    index: function () {
        listView.render();
    },
    edit: function (id) {
        listView.render();
        $(notifierView.el).empty();
        $(formView.el).empty();
        var model = comics.get(id);
        formView.model = model;
        formView.render();
    },
    create: function () {
        var model = new Comic();
        listView.render();
        $(notifierView.el).empty();
        $(formView.el).empty();
        formView.model = model;
        formView.render();
    }
});
jQuery(function () {
    comics.fetch({
        success: function () {
            window.app = new ComicsAdmin();
            Backbone.history.start();
        },
        error: function () {
        }
    });
})

那么,我的创作不应该也得到验证吗?为什么不是?

创建模型的新实例时,不会调用validate方法。根据主干文档,只有在设置或保存之前才会调用验证。

我也在努力解决这个问题,并在相关问题中找到了解决方案:

  • 您可以创建一个新模型,然后设置其属性(请参见问题9709968)
  • 一种更优雅的方法是在初始化模型时调用validate方法(参见问题7923074)

我对这些解决方案并不完全满意,因为当触发错误时,不应该像骨干文档中描述的那样创建模型的新实例。不幸的是,在这两种解决方案中,您仍然需要使用模型的新实例。

edit:被模型的一个新实例卡住实际上是很好的。通过这种方式,您可以向用户反馈为什么它没有通过验证器,并提供纠正他/她的输入的机会。

好。所以,我在这里取得了一些小小的成功。

首先,我编写了自己的验证框架Backbone.Validator,因为我不喜欢我发现的任何一个。

其次,通过在创建new Model期间提供的对象中设置silent: false,我能够获得验证框架来启动验证例程。

除了使用验证框架中的use_defaults参数外,我还能够在初始测试的设置过程中覆盖坏数据。我仍在做更多的测试,但从Chrome浏览器控制台来看,一切似乎都很顺利。