backbone model validation error - backbone.js

I got a validation based on backbone fundamentals by addyosmani, but when i try it on my view i can't get the error that the model generated.TIA
model.js
validate: function(attrs) {
var errors = this.errors = {};
if (!attrs.box)
errors.box= 'box value is required';
//console.log(errors.box);
if (!_.isEmpty(errors)) return errors;
}
view.js
validate: function(model) {
console.log("error text--" + model.errors[this.input] || '');
},

Should it be var errors = this errors || {} ;?

Related

Adding model to a collection after save method in backbone

I am using the save method when my data is submitted. On success callback of the save method, the collection should be updated with the model which i have saved since i want to get the id of the model from my server. My code is as below
var app = app || {};
app.AllDoneView = Backbone.View.extend({
el: '#frmAddDone',
events:{
'click #addDone':'addDone'
},
addDone: function(e ) {
e.preventDefault();
var formData = {
doneHeading: this.$("#doneHeading").val(),
doneDescription: this.$("#doneDescription").val(),
};
var donemodel = new app.Done();
donemodel.save(formData,
{
success :function(data){
/*my problem is here how do i listen to collection event add that has been
instantiated in intialize property to call renderDone . My tried code is
var donecollection = new app.AllDone();
donecollection.add(donemodel);
and my response from server is
[{id:145, doneHeading:heading , doneDescription:description,
submission_date:2014-08-27 03:20:12}]
*/
},
error: function(data){
console.log('error');
},
});
},
initialize: function() {
this.collection = new app.AllDone();
this.collection.fetch({
error: function () {
console.log("error!!");
},
success: function (collection) {
console.log("no error");
}
});
this.listenTo( this.collection, 'add', this.renderDone );
},
renderDone: function( item ) {
var doneView = new app.DoneView({
model: item
});
this.$el.append( doneView.render().el );
}
});
Collection is
var app = app || {};
app.AllDone = Backbone.Collection.extend({
url: './api',
model: app.Done,
});
Model is
var app = app || {};
app.Done = Backbone.Model.extend({
url: "./insert_done",
});
View is
var app = app || {};
app.DoneView = Backbone.View.extend({
template: _.template( $( '#doneTemplate' ).html() ),
render: function() {
function
this.$el.html( this.template( this.model.attributes ) );
return this;
}
});
In your success callback you create an entirely new collection, which doesn't have any listeners registered. This is the reason why the renderDone isn't triggered.
The model you receive from the server should be added to the collection which is attached directly to your view, this.collection:
var self = this,
donemodel = new app.Done();
donemodel.save(formData, {
success :function(data){
// this is the collection you created in initialize
self.collection.add(donemodel);
},
error: function(data){
console.log('error');
}
});

posting data with backbone form post

i am unable to get form post to work. below is snippet for form view with event handling but I am unable to see form data printed in console from getFormData. I am not sure if this is right approach to form handling but was just trying it out reading stuff from net.
define(['backbone', 'handlebars', 'jquery', 'events', 'models/article'], function(Backbone, Handlebars, $, Events, Article) {
var ArticleFormView = Backbone.View.extend({
events: {
"submit": "createArticle"
},
tagName: "form",
id: "article-form",
className: "articleform",
initialize: function() {
this.model = new Article();
this.render();
},
render: function() {
var template = $("#createarticletemplate").html();
console.log("template=" + template);
var compiled = Handlebars.compile(template);
var html = compiled(this.model.attributes);//passed when we do new View()
console.log("compiled template=" + template);
this.$el.html(html);
return this;
},
createArticle: function(e) {
e.preventDefault();
console.log("createArticle event happened" + $(this.el).parent().html());
var data = this.getFormData( $(this.el).parent() );
console.log(JSON.stringify(data));
this.model.save(data, {
success: function(model, response, options) {
console.log("create article success");
Events.trigger("router:navigate", "#");
},
error: function(model, response, options) {
return console.log("create article failure:" + response.responseText);
}
});
},
//Auxiliar function
getFormData: function(form) {
console.log(form);
var unindexed_array = form.serializeArray();
console.log(unindexed_array.length);
var indexed_array = {};
$.map(unindexed_array, function(n, i){
console.log("array:" + n);
indexed_array[n['name']] = n['value'];
});
return indexed_array;
},
}); //artifleformview
return ArticleFormView;
});
snippet of routes/index.js
exports.articles.createone = function(req, res) {
console.log(req.body);
//res.json(req.body);
db.articles.insert(req.body);
}
article.js model:
define(['backbone'], function(Backbone) {
var Article = Backbone.Model.extend({
url: "/article",
idAttribute: "_id"
});
return Article;
});
console log:
createArticle event happened<form id="article-form" class="articleform"><label>title </label><input type="text" name="title"><p></p><label>body </label><input type="text" name="body"><p></p><label>category </label><input type="text" name="category"><p></p><input type="submit" value="create article"></form> articleform.js:27
[div.form, prevObject: m.fn.init[1], context: form#article-form.articleform, jquery: "1.11.1", constructor: function, selector: ""…]
articleform.js:44
0 articleform.js:46
{} articleform.js:29
create article success articleform.js:33
index called on router
Adding createArticle error log:
POST http://localhost:3000/article net::ERR_EMPTY_RESPONSE jquery.js:4
send jquery.js:4
m.extend.ajax jquery.js:4
e.ajax backbone.js:1
e.sync backbone.js:1
i.extend.sync backbone.js:1
i.extend.save backbone.js:1
Backbone.View.extend.createArticle articleform.js:33
m.event.dispatch jquery.js:3
r.handle
If some one wants more code let me know I can put all code here but its too many files so better would be some link I attach if needed.
Above log for error prints in console thought the article is getting persisted fine.
Regards,
Miten.
Looks like you need to replace
var data = this.getFormData( $(this.el).parent() );
with
var data = this.getFormData(this.$('form'));
or
var data = this.getFormData(this.$el.closest('form'));

Backbone save callbacks never hit

I have a backbone model:
define(function() {
var ContactModel = Backbone.Model.extend({
urlRoot: 'http://www.somedomain.com',
defaults : {
'name' : null,
'email': '',
'phone': '',
},
validate: function(attrs) {
var name_filter = /[a-zA-Z'.,-\s]+/;
var email_filter = /^([a-zA-Z0-9_\.\-])+\#(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;
var errors = [];
if(attrs['name'].length<1){
errors.push({input_tag: 'name', error: 'Please enter your First Name'});
}
if(attrs['phone']==='' && attrs['email']===''){
//messages['name'] = 'You must include a phone number or email';
errors.push({input_tag: 'phone', error: 'You must include a phone number or email'});
}
if(attrs['email']!==''){
if (!email_filter.test(attrs.email)){
errors.push({input_tag: 'email', error: 'Please enter a valid email address'});
}
}
if(errors.length > 0){
return errors;
}
}
});
return ContactModel;
});
In my view, I set the attribute values like this:
this.model.set({
name:$('#name').val(),
phone:$('#phone').val(),
email:$('#email').val(),
});
I do the validation, then save the model with:
this.model.save({
success: function(model){
console.log('successfully saved and model is ');
console.log(model);
},
error: function(){
console.log('there was an error');
}
});
The model gets saved on the server, but success or error callbacks are never hit. What am I doing wrong?
Worked after I changed to:
this.model.save([], {
success: function(model){
console.log('successfully saved and model is ');
console.log(model);
},
error: function(){
console.log('there was an error');
}
});

Backbone model validate not triggering

I have overridden the Backbone.Model and extended my own Model with a validate method but it doesn't seem to trigger when updating my model with a set including the validate: true flag.
Mod.Field.Model = App.Base.Objects.BaseModel.extend({
url: "../WebServices/Myclass.asmx/GetData",
defaults: {
DisplayName: ""
},
validate: function (attrs) {
if (attrs.DisplayName == "") {
return "DisplayName cannot be an empty string.";
}
}
});
In my CollectionView:
item_view.model.set({ "DisplayName": event.target.value }, { silent: false, validate: true });
Nothing seems to trigger the validate method on the model when calling the set. I have tried called this as well:
item_view.model.isValid();
But that doesn't trigger it either.
Using Backbone version 1.1
This code below works....but still the question is why the code above will not work with the overridden model?
Mod.Test = {};
Mod.Test.Model = Backbone.Model.extend({
url: "",
defaults: {
DisplayName: ""
},
validate: function (attr) {
if (attrs.DisplayName == "") {
return "DisplayName cannot be an empty string.";
}
}
});
Mod.Test.ItemView = Marionette.ItemView.extend({
tagName: "div"
});
var newView = new Mod.Test.ItemView({
model: new Mod.Test.Model()
});
newView.model.set({ "DisplayName": 123 }, { validate: true });
newView.model.get("DisplayName");
Just tested another scenario. I replaced the Mod.Test.Model with my overridden one with the sample code and it works. The culprit seems to be the way I was getting the view back from the CompositeView for the model.
updateItem: function (event) {
var event_target = $(event.target);
var zero_length = event.target.value.length == 0 ? true : false;
var item_view = this.children.findByCid(event_target.attr("data-viewcid"));
The issue ended up being my Collection that I had overridden that was setting the default model to one that I was not actually using.
This fixed the issue:
this.collection = new App.Base.BaseCollection(this.model.get("mydata"), { model: Mod.Field.Model });

Backbone save model success and error

I have this backbone code, create a view and model, and calls the save method to save data to database:
var form = document.forms[0];
var RetailerModel = Backbone.Model.extend({
urlRoot: ' retailer.php',
defaults: {
name: 'company-name',
address: 'company-address',
phone: 'company-phone',
icon: 'http://localhost/icon.png'
}
});
var RetailerCollection = Backbone.Collection.extend({
});
var RetailerView = Backbone.View.extend({
className: 'retailer',
template: _.template($('#retailer-template').html()),
initialize: function() {
var obj = {
name: form.name.value,
address: form.address.value,
phone: form.phone.value
};
var o = this;
this.model.save(obj, {
success: function(model, response) {
console.log(model);
console.log(response);
o.render();
console.log('success');
},
error: function(model, response) {
console.log(model);
}
});
},
render: function() {
$('#retailer-list').append(this.$el.html(this.template(this.model.toJSON())));
return this;
}
});
var RetailerViews = Backbone.View.extend({
});
$('#submit').click(function(e){
var retailer_model = new RetailerModel();
var retailer_view = new RetailerView({model: retailer_model});
form.reset();
});
And the php code for receiving data is as follow:
<?php
$connect = mysql_connect('127.0.0.1','root','xxxxxx');
if (!$connect) {
die('Could not connect: ' . mysql_error());
}
mysql_select_db("retail", $connect);
if($_SERVER['REQUEST_METHOD'] == 'POST') //POST GET PUT DELETE
{
$data = json_decode(file_get_contents('php://input'), true);
}
$name = $data['name'];
$address = $data['address'];
$phone = $data['phone'];
$icon = $data['icon'];
if(!(mysql_query("INSERT INTO retailer (name, address, phone, icon)VALUES ('".$name."', '".$address."','$phone', '".$icon."')")))
{
echo 200;
}
else{
echo 'record has not been insert to db';
}
mysql_close($connect);
?>
One problem I'm having is that when the error function is called, the model returned from server still has modified attributes. I am wondering why this is happening and how can I make sure that if error happens, model stays unchanged.
Another question is in the php code, when the sql query is successful, if I echo 200, or '200', backbone will call success, but if I echo a string, backbone will call error, I'm wondering what's the logic behind it.
From the backbone docs:
Pass {wait: true} if you'd like to wait for the server before setting
the new attributes on the model.
If you don't want the model to update until after the save is success full pass wait: true as an option.
this.model.save(obj, {
success: function(model, response) {
console.log(model);
console.log(response);
o.render();
console.log('success');
},
error: function(model, response) {
console.log(model);
},
wait: true // Add this
});
The Backbone
save( so are others like fetch, update...)
returns a promise. You can use
save().done(
function( data ) {}, // success
function( err ) {} // fail
)
just like how you handle promises. The done() method is guaranteed to execute after the server has returned stuff.
See the jQuery API docs for AJAX.jqXHR for more information.
Backbone returns a promise.
Here is what I have to get it works.
save({wait: true}).success(function(data){
console.log(data); //returned data from server
}).error(function(error){
console.log(error); //error returned from server
});

Resources