ChatGPT解决这个技术问题 Extra ChatGPT

Easiest way to reset Backbone's model to initial defaults?

My models already have a defaults hash. When parts of the view/page are reset, I wish to reset the models back to their original defaults.

Currently, I explicitly set each attribute to its default value. Is there anything built in or a JavaScript/Underscore.js/Backbone.js/jQuery function that I could use to do this in a single statement?


P
Peter Lyons
myModel.clear().set(myModel.defaults);

This is kinda dangerous though, because if you didn't specify {id: null} in your defaults, it will have the same id as before and using save() will PUT it to the server, overwriting the old object in the server with default values!
If you want a completely different model, construct a new one: myModel = new MyModel().
True, but it's useful to use the same object if others are bound to it.
Note: Any properties that are not listed in defaults will not be cleared from the model. You'll probably want to call .clear() first.
you can use {silent:true} as the parameter for the clear to prevent the change event from firing
s
saabeilin

I came up with the following approach:

reset: function () {
    this.clear({silent: true});
    this.set(this.defaults);
}

Having {silent: true} in the clear() call ensures that the change event is not fired; it will be fire only on set() call.


c
codeboy

I do this when the model has non-null initial object properties.

first, define defaults as a function

var MyModel = Backbone.Model.extends({

    defaults:function(){

        return {
            AnArrayTypeProp:[]
        };
    }

});

second, when needed to reset model to default

model.clear().set(model.defaults());

Use _.result(model, 'defaults)` to handle both an object or a function defaults property.
C
Community

Based on saabeilin's answer and Backbone's annotated source, I came with an optimal function to fill the need for resetting a model.

Reusable reset

/**
 * Clears the model's attributes and sets the default attributes.
 * @param  {Object} attrs to overwrite defaults
 * @param  {Object} options  to pass with the "set" call.
 * @return {Backbone.Model}  this object, to chain function calls.
 */
reset: function(attrs, options) {
    // adds default option reset to true
    options = _.extend({ reset: true }, options);

    // ensure default params
    var defaults = _.result(this, 'defaults');
    attrs = _.defaults(_.extend({}, defaults, attrs), defaults);

    // apply
    this.clear({ silent: true }).set(attrs, options);

    // triggers a custom event, namespaced to model in order
    // to avoid collision with collection's native reset event
    // when listening to a collection.
    if (!options.silent) this.trigger('model:reset', this, options);

    return this;
},

The following line ensures that even if an attribute is passed as undefined { test: undefined }, it'll still have its default value.

attrs = _.defaults(_.extend({}, defaults, attrs), defaults);

Here's an example:

var defaults = { test: 1 }, 
    attrs = { test: undefined };

_.extend({}, defaults, attrs);                       // {test: undefined}
_.defaults(_.extend({}, defaults, attrs), defaults); // {test: 1}

Extending Backbone

And if you want it with all Backbone models, you can extend Backbone itself:

_.extend(Backbone.Model.prototype, {
    reset: function(attributes, options){
        /* ... */
    }
});

Disclaimer: Don't do this if you're writing a JavaScript lib or Backbone plugin, as it could collide with another lib or it could cause a different behavior than the one expected by the person using your code.


J
Johnny

I also thought about using model.clear() and model.set() in conjunction. Then I ran across the problem, that I trigger the change event twice now. Using the silent option when calling model.clear() is not an option, because I also want to have a change event fired, when a property gets unset.

I ended up with adding a model.reset() method. It takes a new attributes hash and fills this hash with undefined values for old attributes keys not being present in the new attribute hash.

Model.prototype.reset = function(attrs, options) {
    for (var key in this.attributes) {
        if (key in attrs) continue;
        attrs[key] = void 0;
    }

    return this.set(attrs, options);
};

This way you reset the models old attributes and get a valid change event for every old and new attribute.


This code doesn't deal with Model.prototype.changedAttributes()
To deal with the lack of event when unsetting with model.clear({silent: true}), I trigger a custom event model:reset.
i
ismnoiet

What about overriding the value of current model with a new empty model :

myModel = new model(); // default values will be considered

This works, but it will destroy any events bound to the model. If I have a change event on myModel and I overwrite it like this, a) it will not fire a change event, and b) any previously bound events would be lost.
D
Daniel Ortegón

My solutions is:

model.clear({silent: true}).set(model.defaults);

关注公众号,不定期副业成功案例分享
Follow WeChat

Success story sharing

Want to stay one step ahead of the latest teleworks?

Subscribe Now