简体   繁体   中英

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

So, I am able to validate just fine when I am editing an existing item. However, if I want to create, validation for some reason is not getting kicked off. Instead, I am seeing the errors below:

//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

Here is(what I think is) the relative portion of my js. Sorry if its an overload, I wanted to add as much as I can to be as specific as possible:

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 () {

        }
    });
})

So, shouldnt my create be getting validated too? Why isnt it?

When creating a new instance of a model, the validate method isn't called. According to the backbone documentation the validation is only called before set or save.

I am also struggling with this problem and found solutions in related questions:

  • You could make a new model and then set its attributes (see question 9709968 )
  • A more elegant way is calling the validate method when initializing the model (see question 7923074 )

I'm not completely satisfied with these solutions because creating a new instance of the model like described in the backbone documentation shouldn't happen when an error is triggered. Unfortunately, in both solutions you're still stuck with a new instance of the model.

edit: Being stuck with a new instance of the model is actually quite nice. This way you can give the user feedback about why it didn't pass the validator and give the opportunity to correct his/her input.

OK. So, I'm having some mild success here.

First, I wrote my own validation framework, Backbone.Validator since I didn't like any of the ones out there that I found.

Second, I am able to get the validation framework to set off the validation routine by setting silent: false with in the object provided during the new Model creation.

Along with using the use_defaults parameter from my validation framework I am able to override bad data during setup in initial testing. I'm still working on doing some more tests on this, but it seems to be going OK from from the Chrome browser console.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM