I have a textfield which takes email as its value by using
vtype : 'email'
I am trying to validate this textfield using a button, wherein, when clicked, it should alert me if the textfield has email input or not. Based on my code, the validation always gives me false no matter the input. how should I do this? Here is my code:
Ext.create('Ext.form.Panel', {
title: 'Contact Info',
width: 300,
bodyPadding: 10,
renderTo: Ext.getBody(),
items: [{
xtype: 'textfield',
id: 'emailField',
fieldLabel: 'EmailAddress',
vtype: 'email',
allowBlank: false,
validator: function (val) {
var fieldValidation = Ext.form.field.VTypes.email(val);
if (fieldValidation === true) {
this.setFieldStyle("background-color : #BCF5A9");
} else {
this.setFieldStyle("background-color : #F6CECE");
}
},
}, {
xtype: 'button',
text: 'select',
handler: function () {
alert(Ext.getCmp('emailField').isValid());
}
}]
});
P.S: I understand that the problem is with the validator: function (val) I have used in the textfield. But I need it to change the color of the textfield based on the input. Is there any other way of doing this?
EDIT:
I got it working by changing the validator : function to a change : function
listeners: {
'change': function (thisField) {
if (thisField.isValid()) {
this.setFieldStyle("background-color : #BCF5A9");
} else {
this.setFieldStyle("background-color : #F6CECE");
}
}
}
Upon further investigation, your custom validator is messing up validation coming with default vtype:'email'. Remove the validator function and validation will work correctly.
If you just want to change the color of the textfield based on the validated input, all you need to do is override the css class (.x-form-invalid-field-default) which is added every time the textfield is invalid.
Hope it helps.
I got it working by changing the validator : function to a change : function
listeners: {
'change': function (thisField) {
if (thisField.isValid()) {
this.setFieldStyle("background-color : #BCF5A9");
} else {
this.setFieldStyle("background-color : #F6CECE");
}
}
}
Related
I have an extjs popup window with form panel inside and I wanted to know how can I send datas in the form panel to my spring controller ?
var formPanel = {
xtype : 'form',
height : 125,
autoScroll : true,
id : 'formpanel',
defaultType : 'field',
frame : true,
items : [
{
fieldLabel : 'Name'
},
{
fieldLabel : 'Age'
}
]
};
function openIFrame() {
Ext.create('Ext.window.Window', {
title : 'Import your devices',
width: 500,
height: 500,
layout: 'fit',
items: [formPanel]
}).show();
}
Get the form by some selector from controller and then call getForm().getValues() method. Method returns an object made by form fields and its values.
Then you can use send this object to the server using Ext.Ajax.request method (docs: http://docs.sencha.com/extjs/4.2.2/#!/api/Ext.Ajax-method-request)
You can send request to server with params via this code:
Ext.Ajax.request({
url: '/requestUrl',
params: {
param1: data1,
param2: data2
},
method: 'POST',
success: function(response) {
//do something...
}
})
Also you need to add this code to some listener on your popup, for example in onButtonClick
function openIFrame() {
Ext.create('Ext.window.Window', {
title : 'Import your devices',
width: 500,
height: 500,
layout: 'fit',
items: [formPanel],
buttons: [
{
text: 'Submit',
handler: function () {
//function which listed above
}
}
]
}).show();
And to handle request at BE you need create controller like this:
#ResponseBody
#RequestMapping(value = "/requestUrl")
public void handler(#RequestParam ("param1") String param1,
#RequestParam ("param2") String param2) throws Exception {
//do something with data
}
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.
I have declared a view as shown below:
Ext.define('App.view.About', {
extend: 'Ext.Panel',
id: 'about',
xtype: 'aboutpanel', // used as reference from Main.js
config: {
title: 'About',
iconCls: 'icon-file',
scrollable: true,
styleHtmlContent: true,
items: {
docked: 'top',
xtype: 'titlebar',
title: 'About'
},
html: 'This page will contain basic information.'
}
});
I have also declared a controller as shown below:
Ext.define('App.controller.About', {
extend : 'Ext.app.Controller',
config : {
refs : {
about : '#about'
}
},
init : function () {
var me = this;
me.getAbout().setHtml('Hello'); // just for testing
}
});
However in the Developer Tools of Chrome am getting an error "Cannot call method 'setHtml' of undefined". Therefore as I understand it, the controller is not getting the view by id. Am using Sencha Touch 2.2.1.
Any help please? Thanks in advance,
You won't have access to the refs in the init() function of the controller. To get similar functionality, you could do your code as an initialize listener on the about panel:
Ext.define('App.controller.About', {
extend : 'Ext.app.Controller',
config : {
refs : {
about : '#about'
},
control: {
about: {
initialize: 'initAbout'
}
}
},
initAbout: function () {
var me = this;
me.getAbout().setHtml('Hello'); // works now!
}
});
As a side note, it is redundant to give your components an id in in the definition. You should reserve id for when you're instantiating components (and you should probably use itemId instead of id in that case anyway).
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 created a custom component, in that there is a textfield on its keyup event i need to filter the store but i m not getting any variable at event generation, but at the time of object creation i am getting the objects.
Below is the code-:
WildCardWindow = Ext.extend(Ext.Window, {
width : 300,
height : 265,
resizable:true,
closeAction:'hide',
title:'WildCard Selection Window',
autoScroll:true,
iconCls:'icon-wildcard',
bodyStyle:'background-color:#FFFFFF',
//#cfg{Array} data-The array of fields/items to show in the window
data: null,
store:null,
/**
* #property
* #type String
* The message displayed when mouse over on an uncommitted field
*/
uncommittMsg : '<b>Warning!</b> This field has been newly added in
the form designer. ' + 'It <i>can</i> be used now,
but you should be sure to save the uncommitted
changes ' + 'in the open form designer window.',
defaultIconCls : '',
initComponent : function(){
this.createStore(this.data);
this.items = this.createDataView();
WildCardWindow.superclass.initComponent.call(this);
},
createDataView: function(){
this.dataView = new Ext.DataView({
store: this.store,
autoWidth:true,
tpl: this.createTpl(),
autoHeight:true,
singleSelect : true,
overClass:'icon-view-over',
selectedClass:'icon-view-selected',
itemSelector:'.icon-dataview-item',
style:'cursor:pointer'
});
this.textField = new Ext.form.TextField({
fieldLabel: 'To',
tabTip:'Start typing to filter by field name',
name: 'f_to',
enableKeyEvents :true,
listeners: {
keyup: function () {
this.store.filter('name',this.textField.getValue(),true,false);
//Here I am not getting this.store and this.textField ???
}}
});
return [this.dataView,this.textField]
},
createStore: function(data){
this.store = new Ext.data.JsonStore({
data:data,
autoDestroy:true,
fields:[
{name: 'id'},
{name: 'name'},
{name: 'fieldclass'},
{name: 'type'},
{name: 'options'},
{name: 'isMultiMember',type:'boolean'},
{name: 'isUnCommitted',type:'boolean'}
]
});
return this.store;
},
listeners:{
close: function(){
this.store.filter('name','',true,false);
}
}
})
In the keyup of textfield i am not getting this.store and this.textfield ??
Any suggestions or where i am wrong.
Please reply soon
Because you lose your scope when that function is called.
You can do two things:
Use the bind function to copy the scope:
http://docs.sencha.com/extjs/4.2.0/#!/api/Ext.Function-method-bind
I think this also works and is a more elegant solution:
var me = this;
this.textField = new Ext.form.TextField({
fieldLabel: 'To',
tabTip:'Start typing to filter by field name',
name: 'f_to',
enableKeyEvents :true,
listeners: {
keyup: function () {
me.store.filter('name',this.getValue(),true,false);
}}
});