Form validation + api call with semantic ui - ajax

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
}
});

Related

Jquery Autocomplete with Ajax Call not working

Im adding enhancements to an existing rails 5.1 app. I need to add autocomplete with data retrieved from a Mysql database. The application has Jquery, simple_form, and materialize all included. My autocomplete is not working. It is not even getting to the controller. I have tried different examples found online and none work. I am hoping someone can help me.
HTML in HAML code snippet (only snippet)
= simple_form_for #vehicle, url: url_for(controller: 'trip_permits', action: 'update'), html: { method: :patch } do |v|
.input-field.col.s12.m4
=v.label :registration_number
= v.text_field :registration_number, input_html: { class: 'force-upcase' }
.cssbuttons.alternate
-# = link_to 'Cancel', '#', onclick: "$('.new_vehicle').hide();", class: 'btn btn-grey'
%button{ type: 'submit', class: 'btn btn-green', id: 'add'}
Add
Id of field is generated to trip_permits_vehicles_form_registration_number
JQUERY SNIPPET
`
$(document).ready(function () {
``
$("#trip_permit_vehicle_form_registration_number").autocomplete(
{
search: function () {},
source: function (request, response)
{
$.ajax(
{
url:'/customers/trip_permits/autocomplete_vehicle_registration_number',
dataType: "json",
data:
{
term: request.term,
},
success: function (data)
{
response(data);
}
});
},
minLength: 2,
select: function (event, ui)
{
var test = ui.item ? ui.item.id : 0;
if (test > 0)
{
alert(test);
}
}
});
}
});
I know I am missing something. Im not worried right now about the results because I cant even get the ajax call to work.
Can someone please help????
I have tried all the examples I could find online
Ive tried select2, simple_form_autocomplete, materialize-autocomplete
How about this?
$("#trip_permit_vehicle_form_registration_number").autocomplete({
search: function () {},
source: function(request, response) {
$.getJSON(
"/customers/trip_permits/autocomplete_vehicle_registration_number",
{term: request.term },
response
);
},
minLength: 2,
select: function (event, ui){
var test = ui.item ? ui.item.id : 0;
if (test > 0) { alert(test); }
}
})

How to validate model using collection.create()

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.

How to load json data from ajax in ExtJs

I try to get started with ExtJs, and I have quite basic question.
I have a model
Ext.define('Mb.model.User', {
extend: 'Ext.data.Model',
fields: [
{ name: 'id', type: 'int' },
{ name: 'name', type: 'string' },
...
],
proxy: {
type: 'ajax',
url : 'server/gui/getUser.php'
}
});
getUser.php returns a json string (it is the logged in user, and not a user out of a user table):
{"id":"1","name": ... }
I tried the following to load the data, but I get an error Uncaught TypeError: Object [object Object] has no method 'load'
Ext.define('Mb.Application', {
...
launch: function() {
....
user = Ext.create('Mb.model.User');
user.load();
}
});
What is the correct way to load that data ?
An additional question: What is the benefit of using Modelhere ?
Couldn't I do something like this ?
Ext.Ajax.request({
url: 'server/gui/getUser.php',
success: function(response){
var user = Ext.JSON.decode(response.responseText);
}
});
In this case load is a static method. You can load a model from your server by passing the id.
Mb.model.User.load(id, {
success: function(rec) {
console.log('loaded', rec.getData());
}
});
The advantage to using a model is the layer of abstraction, + the extra functionality you get from using a model.
You can do, but with little changes
myRequest = Ext.Ajax.request({
url: 'getdata.php',
method: 'GET',
callback: function(response) {
console.log(response.responseText);
}
});

Kendo UI does not call create if a function is specified

Using Kendo.web.js versions 2013.2.716 and 2012.3.1315, I am trying to use a function in my transport.create rather than calling a URL. What I find is that the function does not get called. Instead a default URL is called and the resulting HTML appears to cause an error in the bowels of kendo because it is expected to be JSON instead.
I assume that this is some type of configuration error, but I can't figure out where the problem is.
Here is a snippet of the code:
var clientListDS = new kendo.data.DataSource({
transport: {
read: {
url: window.baseUrl + 'HealthCheck/ClientSummary',
dataType: 'json',
type: 'POST'
},
create: function(a,b,c) { alert('Create'); },
createY: window.baseUrl + 'HealthCheck/DontCallMe',
createX: {
url: window.baseUrl + 'HealthCheck/DontCallMe',
dataType: 'json',
type: 'POST'
},
whatWeWantCreateToDo: function () {
showChooseDialog('Some Random String', 'Select Client', OnRefreshInactiveClientList);
},
destroy: function () {
alert('destroy');
},
update: function () {
alert('update');
}
},
autoSync: true,
schema: {
model: {
id: 'ID',
fields: {
ID: { required: false, type: 'number', nullable: true },
ClientName: { type: 'string' },
ClientTag: { type: 'string' },
Status: { type: 'string' }
}
}
}
});
Then I use the resulting data source to build a grid like this:
$('#cClientGrid').kendoGrid({
dataSource: clientListDS,
columns: [
{ field: 'ClientTag', title: 'Tag'},
{ field: 'ClientName', title: 'Name' },
{ field: 'Status' }
],
editable: {
mode: 'incell',
createAt: 'bottom'
},
edit: function (pEvent) {
if (pEvent.model.isNew())
alert('create');
else
alert('Edit');
},
toolbar: ['create']
});
Some behavior that is worthy of note:
You see several attempts at the create configuration. If I use CreateY or CreateX, it will call the resulting URL. If I use Create or WhatWeWantCreateToDo, I end up downloading the containing page with each element of my schema as get string items (I assume this is some type of default behavior as I can't find a reference to the URL which is downloaded).
When I turn off autoSync, the grid will call its edit function when I use the toolbar to create a new item. When I turn on autoSync, the edit function does not get called. Instead the data source create functionality runs.
Any thoughts or insight on how I might be able to call a function instead of a URL will be appreciated.
First make in transport everything being an URL or a function, do not mix them up.
If you need to implement read as a function, you simply do:
transport: {
read : function (options) {
$.ajax({
url: window.baseUrl + 'HealthCheck/ClientSummary',
dataType: 'json',
type: 'POST',
success : function (result) {
options.success(result);
}
});
},

Sencha Touch: how to Update data Store to list from controller

am facing problem while updating list from controller. I have store, model and list to show Json data. am able to get data but could not able update the list. and if do the ajax call in my store am able to data with list but listners are not getting called. So i moved the code to controller.
here is my store:
Ext.define('MyApp.store.StoreList', {
extend:'Ext.data.Store',
requires:['MyApp.model.ModelList'],
config:{
model:'MyApp.model.ModelList',
autoLoad:'true',
storeId:'id_StoreList'
}
});
model:
Ext.define('MyApp.model.ModelList', {
extend: 'Ext.data.Model',
xtype:'modelList',
config: {
fields:['name']
}
});
controller
Ext.define('MyApp.controller.Main', {
extend : 'Ext.app.Controller',
requires : ['MyApp.view.MyList'],
config : {
refs : {
loadbtn:'button[action=loadbtn]',
dataList: '#id_listitems'
},
control : {
"#dataList": {
itemtap: 'onListItemTap'
},
loadbtn:{
tap : 'handleloadbtn'
}
}
},
handleloadbtn: function(){
console.log('loadbtn tapped');
Ext.Viewport.setMasked({xtype:'loadmask',message:'loading...'});
this.ajaxCall();
},
ajaxCall:function(){
Ext.Ajax.request({
method: 'POST',
scope: this,
extraParams: {
Details: true
},
url:'http://localhost:9080/works',
actionMethods: {
create : 'POST',
read : 'POST', // by default GET
update : 'POST',
destroy: 'POST'
},
headers :{
"Content-Type" :'application/xml',
'Accept':'application/json'
},
reader:
{
type:'json'
},
success: function(response){
console.log('success');
// var list = Ext.getCmp('id_listitems')
//var store = Ext.getStore('id_StoreList');
var store = Ext.data.StoreManager.lookup('id_StoreList');
this.getDataList().setStore(store);
//Error : Uncaught ReferenceError: getDataList is not defined
console.log('test:',test);
Ext.Viewport.setMasked(false);
}
})
}
});
list:
Ext.define('MyApp.view.MyList',{
extend:'Ext.Panel',
xtype:'myList',
requires:['Ext.dataview.List'],
config:{
layout:'fit',
styleHtmlContent:'true',
styleHtmlCls:'showListCls',
items:[
{
docked:'top',
items:[
{
xtype:'button',
text:'Load',
ui:'Plain',
action:'loadbtn',
width:'180px',
height:'30px',
docked:'right',
margin : '5 15 5 0'
}
]
},
{
xtype:'list',
id: 'id_listitems',
action:'list_Item_Action',
store:'StoreList',
itemTpl:['{name}'
]
}
]
}
});
Can any one please help me out in resolving this? Thanks.
You need to use this.getDataList() like so:
Ext.Ajax.request({
method: 'POST',
extraParams: {
Details: true
},
url:'http://localhost:9080/works',
actionMethods: {
create : 'POST',
read : 'POST', // by default GET
update : 'POST',
destroy: 'POST'
},
headers :{
"Content-Type" :'application/xml',
'Accept':'application/json'
},
reader:
{
type:'json'
},
success: function(response){
console.log('success');
// var list = Ext.getCmp('id_listitems')
//var store = Ext.getStore('id_StoreList');
var store = Ext.data.StoreManager.lookup('id_StoreList');
this.getDataList().setStore(store);
//Error : Uncaught ReferenceError: getDataList is not defined
console.log('test:',test);
Ext.Viewport.setMasked(false);
},
scope: this
});
You also need to add scope: this to your request config object so that this in the success method is not the request but your controller.
Hope this helps.
I think you can try this.
your store would look like
Ext.define('MyApp.store.StoreList', {
extend:'Ext.data.Store',
requires:['MyApp.model.ModelList'],
config:{
model:'MyApp.model.ModelList',
autoLoad:'true',
clearOnPageLoad: false,
proxy: {
type: 'jsonp',
useDefaultXhrHeader: false,
url: 'http://localhost:9080/works',
reader: {
type: 'json',
rootProperty: "Items" //It depends on your json data structure
},
callbackKey: 'callback'
}
}
});
In the Controller "handleloadbtn" function , you can just call
Ext.getStore("StoreList").load(); //despite of the config "autoLoad:true"

Resources