I'm trying to make a form validated before submit. For this, I defined a create method within the View which is responsible to call collection.create() method to create the model.
Here is a sample code:
app.ContactCreateView = Backbone.View.extend({
template: _.template($('#tpl-create-contact').html()),
initialize: function () {
this.router = new app.ContactsRouter();
this.contacts = new app.ContactsCollection();
},
events: {
'click #btn-create' : 'create',
'click #btn-cancel' : 'cancel',
},
render: function() {
this.$el.html(this.template());
return this;
},
getAttributes: function () {
console.log('getAttributes()');
var attr = {
name: $('#input-name').val().trim(),
category: $('#input-category').val().trim(),
phone: $('#input-phone').val().trim(),
email: $('#input-email').val().trim(),
};
console.log('attr : ' + JSON.stringify(attr))
return attr;
},
create: function () {
console.log('create()');
// Create the Model
this.contacts.create(this.getAttributes(), {
wait : true,
success: function () {
console.log('success');
//this.hideErrors();
var router = new app.ContactsRouter();
router.navigate('contacts', true);
},
error: function () {
console.log('error(s)')
//this.showErrors(errors);
}
});
},
The 'success' callback is well called but I don't manage to get the 'error' callback called once the model.validate() method is failing.
Here is the model with the validate method :
app.ContactModel = Backbone.Model.extend({
urlRoot: '/user',
// Default attributes for the Contact
defaults: {
name: null,
phone: null,
email: null,
category: null,
photo: "/images/placeholder.png"
},
validate: function(attrs) {
console.log('validate() : ' + JSON.stringify(attrs));
var errors = [];
if (!attrs.name) {
errors.push({name: 'name', message: 'Please fill name field.'});
}
if (!attrs.category) {
errors.push({name: 'category', message: 'Please fill category field.'});
}
console.log('errors : ' + JSON.stringify(errors));
return errors.length > 0 ? errors : false;
}
});
And the collection:
app.ContactsCollection = Backbone.Collection.extend({
model: app.ContactModel,
url: '/user',
//localStorage: new Backbone.LocalStorage('contacts-backbone'),
getById: function (iId) {
return this.where({id: iId});
},
getByName: function (iName) {
return this.where({name: iName});
}
});
I really don't understand what I'm doing wrong... If somebody can help me :-(
Regards,
when the validation is failed error callback is not called , it trigger an "invalid" event on model, and set the validationError property on the model.
method 1(listening on model):
app.ContactModel = Backbone.Model.extend({
urlRoot: '/user',
//your error catched here
initialize : function(){
this.on("invalid",function(model,error){
alert(error);
});
defaults: {
name: null,
phone: null,
email: null,
category: null,
photo: "/images/placeholder.png"
},
validate: function(attrs) {
console.log('validate() : ' + JSON.stringify(attrs));
var errors = [];
if (!attrs.name) {
errors.push({name: 'name', message: 'Please fill name field.'});
}
if (!attrs.category) {
errors.push({name: 'category', message: 'Please fill category field.'});
}
console.log('errors : ' + JSON.stringify(errors));
return errors.length > 0 ? errors : false;
}
});
method 2 (check whether validationError property is set in your view):
create: function () {
console.log('create()');
// Create the Model
this.contactModel.save(this.getAttributes(), {
wait : true,
success: function () {
console.log('success');
this.contacts.add(this.contactModel);
var router = new app.ContactsRouter();
router.navigate('contacts', true);
},
error: function () {
console.log('error(s)')
}
});
//your error catched here
if (this.contactModel.validationError) {
alert(this.contactModel.validationError)
}
},
So I played around with this for a while in an app I'm currently working on and found it kind of irritating and never really got it to work.
Instead I went the jQuery validation route and found it very helpful for doing validations. I highly recommend checking it out! It has a lot of built in validations you can just use and you can also override the error messages that display (also built in).
Example - I wanted a number only text field (excuse the coffeescript) :).
jQuery.validator.setDefaults(
debug: true,
success: "valid")
if #model.get('number_only')
$('#number_only').validate({
debug: true,
rules: {
"number[entry]": {
required: true,
range: [#model.get('min_number'), #model.get('max_number')],
number: true
}
},
messages: {
"number[entry]": {
required: "This field is required. Please enter a numeric value.",
min: jQuery.validator.format("Please enter a value greater than or equal to {0}."),
max: jQuery.validator.format("Please enter a value less than or equal to {0}."),
number: "Please enter a numeric value"
range: jQuery.validator.format("Please enter a value between {0} and {1}.")
}
}
})
If that doesn't really get what you want (seemed like you maybe are more interested in displaying the errors your server sends back whereas this route would more be validating the content before saving your model) let me know and I can see if I can figure out your problem.
Related
I've been banging my head on this one for the whole day.
I have this JS code for semantic ui. Simple validation + api (ajax) call.
$('.ui.form')
.form({
fields: {
comment: {
identifier: 'comment',
rules : [
{
type : 'empty',
prompt: 'Please enter you comment.'
}
]
}
}
});
$('.ui.form .submit.button')
.api({
action : 'new lead comment',
method : 'POST',
serializeForm: true,
urlData : {
id: $('#lead_id').val()
},
onSuccess : function(response) {
alert('success');
console.log(response);
},
onFailure : function(response) {
alert('failure');
console.log(response);
}
});
The problem is that after (failed) form validation, API is called and that should not happen. Both .form and .api work great on their own but not in "team" like this. I am aware of few workarounds (using beforeSend to do jquery $.ajax call) but I know there HAS to be a "semantic" way of doing this otherwise someone coded all this logic for nothing :)
For future reference (and because semantic ui docs are not clear in this part) the solution (that's working for me) is to attach .form and .api on the semantic ui form element like this:
$('.ui.form')
.form({
fields: {
comment: {
identifier: 'comment',
rules : [
{
type : 'empty',
prompt: 'Please enter you comment.'
}
]
}
}
})
.api({
action : 'new lead comment',
method : 'POST',
serializeForm: true,
urlData : {
id: $('#lead_id').val()
},
onSuccess : function(response) {
alert('success');
console.log(response);
},
onFailure : function(response) {
alert('failure');
console.log(response);
}
});
onSuccess callback is what you need.
$('.ui.form')
.form({
fields: {
comment: {
identifier: 'comment',
rules : [
{
type : 'empty',
prompt: 'Please enter you comment.'
}
]
}
},onSuccess:function(event){
event.preventDefault();
alert('valid but not submitted');
//you can use api or ajax call here
}
});
I want to the priceMax was required, when title is empty.
I have code
self.searchParameters = {
title: ko.observable().extend({
refreshCountOffers: 500
}),
priceMax: ko.observable().extend({
required: {
onlyIf: function() {
return title==null;
}
},
refreshCountOffers: 500
})
};
,but I get error 'title is not defined'.
How to disable option, which show error for pattern validation, when user input first letter?
postCode: ko.observable().extend({
required: true,
pattern: {
message: 'Post code is not valid',
params: '[0-9]{2}-[0-9]{5}'
},
refreshCountOffers: 500
})
my jsfiddle
There are 2 problems with the onlyIf check:
you need to qualify the title property
title is observable so you need to access the value
The code below resolves both:
onlyIf: function() {
return self.searchParameters.title();
}
I am trying to implement ajax in laravel framework, where I am trying to check for the availability for the username, I was able to implement the same via core php but not able to get through laravel 4.
1) You have to define a method in your controller (i.e UserController)
public function postEmail()
{
$userCount = User::where('email', '=', Input::get('email'))->count();
if ($userCount == 0)
{
return "true";
} else {
return "false";
}
}
2) In your registration form you have to do jQuery validation like this to make a remote call on Controller method
$(document).ready(function() {
$('#registration-form').validate({
rules: {
email: {
required: true,
email: true,
remote: {
type: "POST",
url: '/user/email'
}
}
},
messages: {
email: {
remote: "The email has already been taken!"
}
},
success: function(date) {
console.log(data);
}
});
I am trying to pass entire model from View to Controller using jTable.
Here is the code for view
I am having a filter criteria based on which the table will be loaded.
Say DropdownList of ModelId and ModelName, on selection,followed by click of a button, the function below executes.
<script type="text/javascript">
function GetModels() {
var model = {
ModelId:$("#ModelId").val(),
ModelName:$("#ModelName").val(),
ModelAge:$("#ModelAge").val()
};
$(document).ready(function () {
$('#PersonTableContainer').jtable({
title: 'Table of Models',
actions: {
listAction: '/Controller/ActionName'
},
fields: {
ModelName: {
title: 'ModelName',
width: '30%',
list: false
},
ModelId: {
title: 'ModelId',
width: '30%',
key: true,
create: false,
edit: false
}
ModelAge: {
title: 'ModelAge',
width: '30%',
create: false,
edit: false
}
}
});
$('#PersonTableContainer').jtable('load', { ModelName: model });
});
}
Here is the code for the controller.
public JsonResult GetAppropriateModel( ModelName ModelName)
{
try
{
FillAppropriateModel(ModelName);
}
catch(Exception e)
{
return Json(new { Result = "Error", Message=e.Message });
}
}
I am kind of new in AJAX and I am facing an issue where in the returned model is null, However if I cause normal submit-button postaction, then the model is retained.. I googled and got examples where they pass discrete elements and not entire model.
--Edit --
This is the link I referred.
http://www.jtable.org/Demo/Filtering
Kindly help.
Thanks.
For some reason the MVC handler doesn't decode model objects properly when jTable sends them in. I've found that setting the contentType in your jTable ajaxSettings fixes this. In your jTable definitions, add this:
ajaxSettings: {
contentType: "application/json; charset=utf-8"
}
Then you have to stringify your parameter when you send it in:
$('#PersonTableContainer').jtable('load', JSON.stringify({ ModelName: model }));
I have a simple Sencha Touch 2.1 model class:
Ext.define('App.model.User', {
extend: 'Ext.data.Model',
config: {
fields: [
{ name: 'id', type: 'number', defaultValue: 0 },
{ name: 'first', type: 'string' },
{ name: 'last', type: 'string' },
{ name: 'email', type: 'string' },
{ name: 'lastUpdated', type: 'auto' }
]
},
fullName: function () {
var d = this.data,
names = [d.first, d.last];
return names.join(" ");
}
});
A collection of these models is in a store that I've configured to use sencha's Rest Proxy. When I add a new model to the store, and call the Sync method on the store, the new model is posted to a ASP.NET WebAPI Users controller and the following action is hit:
// POST api/Default1
public HttpResponseMessage PostUser(User user)
{
// this is a new user -- get rid of the ID
user.Id = 0;
if (ModelState.IsValid)
{
db.Users.Add(user);
db.SaveChanges();
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created, user);
response.Headers.Location = new Uri(Url.Link("DefaultApi", new { id = user.Id }));
return response;
}
else
{
return Request.CreateResponse(HttpStatusCode.BadRequest);
}
}
The problem is that the a string is being sent as the ID for the model, so it's not passing the ModelState.IsValid check on the controller. This is what's actually getting sent up:
{"id":"ext-record-5","first":"c","last":"d","email":"e","lastUpdated":null}
Any idea why the id field is being set to a string? Also, any idea how I can tell the post action in the Users controller not to validate the id field (as it should be handling creating a new item, it makes sense for the server to create the ID for the new item, not the client).
This link helped me figure it out. The updated model should be:
Ext.define('App.model.User', {
extend: 'Ext.data.Model',
config: {
fields: [
{ name: 'id', type: 'auto', persist: false },
{ name: 'first', type: 'string' },
{ name: 'last', type: 'string' },
{ name: 'email', type: 'string' },
{ name: 'lastUpdated', type: 'auto' }
],
},
fullName: function () {
var d = this.data,
names = [d.first, d.last];
return names.join(" ");
}
});
You need to set idProperty on the model. The field for id should also be set to type auto. See documentation here.