Backbone validation return attribute name - javascript

In model:
validation: {
title: {
required: true
},
body: {
required: true
}
}
In view I call:
this.parent.model.isValid(['title', 'body']);
This only return my true/false, how to change validation to get parameters names which are not valid ?
I can't pass atributtes one by one, because It can be a lot.

It's explained in docs mate
Failed validations trigger an "invalid" event, and set the validationError property on the model with the value returned by this method.
var Chapter = Backbone.Model.extend({
validate: function(attrs, options) {
if (attrs.end < attrs.start) {
return "can't end before it starts";
}
}
});
var one = new Chapter({
title : "Chapter One: The Beginning"
});
one.on("invalid", function(model, error) {
alert(model.get("title") + " " + error);
});
In your case (code not tested, I hope you get the idea):
this.parent.model. = Backbone.Model.extend({
validate: function(attrs, options) {
var errors= new Array;
if (!attrs.title) {
errors.push("Title is required");
}
if (!attrs.body) {
errors.push("Body is required");
}
if errors.length
return errors;
}
});
this.parent.model.on("invalid", function(model, error) {
alert(error);
});
//You don't need to pass an attribute list
this.parent.model.isValid();
Note you'll keep the errors array (if any) at this.parent.model.validationError for later processing so you don't need to capture the "invalid" event on the model

Overwrite the validate function http://backbonejs.org/#Model-validate
perform wtv filter you want and return wtv object you want.
Hope it helps

Related

Updating a shadow field, via updateOne pre hook, in mongoose?

Can anyone explain how to use the updateOne pre-hook, in mongoose (5.9.5)?
I am need to create a normalised 'shadow field' (not sure the right term) to help with certain searches. While I am able to update the shadow field during a save, I am having trouble during update.
The save pre-hook:
personSchema.pre('save', function (next) {
if (this.isModified('name')) {
const name = this.name;
if (name && name.trim().length > 0) {
const shadowName = name.normalize('NFD').replace(/[\u0300-\u036f]/g, '');
this.shadowName = shadowName.toLowerCase();
} else {;
this.shadowName = name;
}
}
// do stuff
next();
});
Doing the equivalent for updateOne does not seem to work (shadowName stays with the value it was given during the initial save):
personSchema.pre('updateOne', function (next) {
const name = this.name;
if (name && name.trim().length > 0) {
const shadowName = name.normalize('NFD').replace(/[\u0300-\u036f]/g, '');
this.update({}, { shadowName: shadowName.toLowerCase() });
} else {
this.shadowName = name;
}
// do stuff
next();
});
The schema:
const personSchema = new mongoose.Schema({
resourceId: {
type: String,
required: true,
unique: true,
index: true,
uppercase: true
},
name:{
type: String,
required:true,
index: true
},
// can be used for searches, but don't update directly
shadowName: {
type: String,
index: true
},
});
BTW I can confirm the hook is called, but the field is not updated.
Turns out you can't access the field values directly and instead need to leverage the get() and set() methods on the query.
Changing the pre-updateOne hook to be the following works:
personSchema.pre('updateOne', function (next) {
const name = this.get('name');
if (name && name.trim().length > 0) {
const shadowName = name.normalize('NFD').replace(/[\u0300-\u036f]/g, '');
this.set('shadowName', shadowName.toLowerCase());
} else {
this.set('shadowName', name);
}
// do stuff
next();
});

A variable has no status key, but var.status gives string

Its a mongoose/express app, I have a route like this:
// ..
Posts.find({})
.then(function(posts) {
var data = _.chain(posts).filter(function(post) {
if(post.comment) {
return post.updatedAt <= post.comment.lastCreatedAt;
} else {
return true;
}
}).each(function(post) {
if(post.comment) {
post.status = 'OK';
} else {
post.status = 'NOT OK';
}
console.log("post")
console.log(post)
console.log("post.status")
console.log(post.status)
}).value();
})
// ..
But the log is
"post"
{
_id: ***,
title: 'test',
content: 'test',
user: ***
}
"post.status"
OK
why there's no status in first console.log(post) ?
The post is a Document object which means it has a custom toJSON method that only yields the properties of your schema and the _id.
You can get an object representation of the document via the toObject method.

backbone model sets value on false validate

I'm learning backbone.js and trying to figure out how to use the validation method. But my problem is when I call for validation the validation is triggered but it still saves the invalid data. As seen here player.set('firstName', '', { validate: true }); I set lastName variable to '' and it saves that values, and it shouldn't.
Edit - Updated code so now it works correctly
Backbone model.
var Player = Backbone.Model.extend({
defaults: {
firstName: "Not specified",
lastName: "Not specified",
position: "Not specified"
},
validate: function (attributes) {
// validate first name
if (!attributes.firstName || attributes.firstName === '') {
return 'you must have a first name';
}
// validate last name
if (!attributes.lastName || attributes.lastName === '') {
return 'you must provide a last name.';
}
// validate position
if (!attributes.position || attributes.position === '') {
return 'you must provide a position.';
}
},
initialize: function () {
// checks when firstName has changed
this.on('change:firstName', function () {
console.log("firstName attribute has changed.");
});
// checks when lastName has changed
this.on('change:lastName', function () {
console.log("lastName attribute has changed.");
});
// checks when position has changed
this.on('change:position', function () {
console.log("position attribute has changed.");
});
// check for valid inputs
this.on('error', function (model, error) {
console.log(error);
});
}
});
From within chrome dev tools I do the following code.
var player = new Player;
player.set({ firstName: "peter", lastName: "andrews", position: "outfield" }, { validate: true });
player.toJSON();
firstName attribute has changed. app.js:32
lastName attribute has changed. app.js:36
position attribute has changed. app.js:40
Object {firstName: "peter", lastName: "andrews", position: "outfield"}
player.set('firstName', '', { validate: true });
player.toJSON();
you must have a first name app.js:14
Object {firstName: "peter", lastName: "andrews", position: "outfield"}
From the Backbone docs:
If the attributes are valid, don't return anything from validate; if
they are invalid, return an error of your choosing.
Your validation function is printing the error strings with console.log but not returning anything.
Try changing your validate function to something like:
validate: function (attributes) {
// validate first name
if (!attributes.firstName || attributes.firstName === '') {
return 'you must have a first name';
}
// validate last name
if (!attributes.lastName || attributes.lastName === '') {
return 'you must provide a last name.';
}
// validate position
if (!attributes.position || attributes.position === '') {
return 'you must provide a position.';
}
},

Reference var from one model to another returns defaults in Backbone

I have a model which sets the defaults like so:
var CampModel = Backbone.Model.extend({
defaults: {
siteID: $.jStorage.get('currentSiteID'),
active: -1,
pending: -1,
},
url: function () {
//some url.
},
sync: function (method, model, options) {
var method = 'read';
var that = this,
options = options || {};
options.success = function(model, response, options){
if(response.errorMessage != "Session is over")
console.log('Update session');
if(response.success)
if(response.returnValue.length){
that.set('response', response.returnValue);
that.CountActiveAndPending(response.returnValue);
}
else {
that.set('response', []);
}
else console.log('report: bad request, error: '+ response.errorMessage);
}
Backbone.sync(method, model, options);
},
},
//Counts active and pending campaigns for front page.
CountActiveAndPending: function (data) {
var active = 0;
var pending = 0;
//var it = this;
$.each(data, function (index, val) {
if (val.ApprovedOnSite) active++;
else pending++;
});
this.set('active', active);
this.set('pending', pending);
}
});
and in a different model I try and get the models parameters like so:
this.set({
campModel: new CampModel(),
})
});
this.get('campModel').save();
console.log(this.get('campModel').get('active'));
},
Everything seems to run great but when I try to get the "active" param from the CampModel I get the -1 default value and not the value assigned in the model. Any thoughts as to why this happens?
Model#save is asynchronous, when you're doing:
console.log(this.get('campModel').get('active'));
the server hasn't responded yet, so CountActiveAndPending has never been called and active is still -1. Try to log its value in your success callback.

Backbone Model defaults - unnecessary code in todos.js example?

In the backbone.js ToDos example, The initialize method of the ToDo constructor sets the title attribute to the default title.
Isn't this unnecessary? I thought the point of defaults is that they get assigned automatically? Or am I missing something?
var Todo = Backbone.Model.extend({
// Default attributes for the todo item.
defaults: function() {
return {
title: "empty todo...",
order: Todos.nextOrder(),
done: false
};
},
// Ensure that each todo created has `title`.
initialize: function() {
if (!this.get("title")) {
this.set({"title": this.defaults().title});
}
},
///...
);}
A default value will only be applied if no corresponding attribute is passed to the constructor. In this case, it's probably to ensure that an item created with an empty string as a title gets displayed with something in it. Compare
var Todo1 = Backbone.Model.extend({
defaults: function() {
return {
title: "empty todo...",
done: false
};
},
initialize: function() {
if (!this.get("title")) {
this.set({"title": this.defaults().title});
}
}
});
var t1 = new Todo1({
title: ""
});
with
var Todo2 = Backbone.Model.extend({
// Default attributes for the todo item.
defaults: function() {
return {
title: "empty todo...",
done: false
};
}
});
var t2 = new Todo2({
title: ""
});
t1.get('title') will be empty todo... and t2.get('title') will be an empty string. Passing no argument to both constructors would indeed use the default values.
And a Fiddle http://jsfiddle.net/nikoshr/CeEDg/

Categories

Resources