How to get data from fieldset in Sencha Touch 2? - touch

I hava a fieldset in Sencha Touch 2 as follows:
{
id:'contactForm',
xtype: 'fieldset',
title: 'Information',
items: [
{
xtype: 'textfield',
label: 'First Name',
placeHolder: 'Your First Name',
name:'firstName',
id:'firstName',
},
{
xtype: 'textfield',
label: 'Last Name',
placeHolder: 'Your Last Name',
name:'lastName'
},
{
xtype: 'emailfield',
label: 'Email',
placeHolder: 'email#example.com'
},
{
xtype: 'button',
height: 37,
style: 'margin-left:35%',
width: 100,
iconAlign: 'center',
text: 'Submit',
action:'ContactSubmit'
},
{
xtype: 'hiddenfield',
id: 'HNumberOfBedRoom',
value:'2'
},
{
xtype: 'hiddenfield',
id: 'HPetFriendlyId',
value:'2'
}
]
}
In my controller,
I have the following:
refs: {
contactForm: '#contactForm'
}
I can retrive the value by using
var frmItems=this.getContactForm().getItems();
console.log(frmItems.items[1]._value);
This works fine but i want to retrieve the values something like
frm.get('name/id of component')
is there any way to achieve this?

Use a Ext.form.Panel as your primary container.
example snippet
Ext.define('App.view.ContactForm',
{
extend : 'Ext.form.Panel',
xtype : 'contactform',
id : 'contactForm',
config : {
items : [
{
xtype : 'fieldset',
items : [
{
{
xtype: 'textfield',
label: 'First Name',
placeHolder: 'Your First Name',
name:'firstName',
},
]
}
});
in your controller
refs : { contactForm : '#contactForm' }
then in your function you can either do
this.getContactForm().getValues().firstName
(uses the name value of the field)
or
var vals = this.getContactForm().getValues();
vals.firstName;
Avoid using Ext.getCmp() or a flat Ext.get() at the top level if you absolutely can help it. If you're building custom controls you might have to make use of those, otherwise you're making things too hard on yourself.

You should be able to assign an id to your field, and then Ext.getCmp('-yourId-'); or Ext.get('-yourId-');
( http://docs.sencha.com/touch/2-0/#!/api/Ext.Component-cfg-id )

Dont struggle too much
first assign the id to that field and get the value using id thats it..
{
xtype: 'textfield',
id: 'username', // id
name: 'username',
placeHolder: '------UserName------',
},
Ext.getCmp('username').getValue(); // now get value using that id..

refs:[
{
ref:'contentForm',
// selector:'#contentForm'
contentForm:'#contentForm'
}
],
-
var form = Ext.getCmp('contentForm');
console.log(form.getValues());

Assign itemId: firstName to textfield
And in Controller, where you want to get the value, use this:
Ext.ComponentQuery.query('textfield[itemId=firstName]')[0].getData();

Related

ExtJS - How to implement a container with its own isValid and hasInvalidField methods

For example, let's say we have three phone number fields: mobile, home, business, that we want to encapsulate as a contact item.
The phone number fields can be blank or, if not, have their own validity checks, the contact item has its own validity check in that at least one number must be provided.
I'm thinking about doing something like this:
Ext.define('My.widgets.contact', {
// To make use of Ext.form.Labelable mixin
extend: 'Ext.form.fieldcontainer',
xtype: 'contact',
alias: 'widget.contact',
requires: [
'My.widgets.phone'
],
mixins: [
// To link in isValid and other methods
'Ext.form.field.Field'
],
items: [
{
xtype: 'phone',
fieldLabel: 'mobile'
},
{
xtype: 'phone',
fieldLabel: 'home'
},
{
xtype: 'phone',
fieldLabel: 'business'
}
],
isValid: function() {
let valid = false;
if (this.callParent(arguments)) {
for (const item in this.getItems()) {
if (item.getValue() != '') {
valid = true;
break;
}
}
}
return valid;
}
});
Is this the right way to do this?
The idea is to have the minimum extra fluff. For example, form panels have dockable, button, header and footer elements which aren't needed. Also, I've read about problems in ExtJS having multiple form items on a page, so want to avoid sequential or nested forms on a single page.
Another approach might be to extend Ext.container.Container with the Ext.form.Labelable and Ext.form.field.Field mixins. Would that work?
In ExtJs fieldcontainer have method query so you use this to check your Validation.
Query retrieves all descendant components which match the passed selector. Executes an Ext.ComponentQuery.query using this container as its root.
As you have used this.getItems() it will return all the items of fieldcontainer as whatever it contain. In this case you need to maintain condition to check getValue() only for fields.
Query will return only that component as you want to check.
I have created an Sencha Fiddle demo hope this will be help you to achieve your solution.
//Custom xtype for phone
Ext.define('Ext.form.field.Phone', {
extend: 'Ext.form.field.Text',
alias: 'widget.phone',
xtype: 'phone',
maskRe: /[\d\.]/,
regex: /^\d+(\.\d{1,2})?$/,
maxLength: 11,
enforceMaxLength: true
});
//Contact details
Ext.define('ContactForm', {
extend: 'Ext.form.FieldContainer',
alias: 'widget.contact',
xtype: 'contact',
flex: 1,
layout: 'vbox',
defaults: {
xtype: 'phone'
},
items: [{
fieldLabel: 'mobile'
}, {
fieldLabel: 'home'
}, {
fieldLabel: 'business'
}],
isValid: function () {
return this.query('phone[value=""]').length > 0;//you can also use like this { this.query('phone[value!=""]') };
}
});
//Panel this will contain contact
var panel = Ext.create('Ext.panel.Panel', {
itemId: 'myPanel',
bodyPadding: 5,
width: 300,
renderTo: Ext.getBody(),
title: 'Contact Details',
items: [{
xtype: 'contact'
}],
buttons: [{
text: 'Submit Details',
handler: function () {
var contactFrm = this.up('#myPanel').down('contact'), //you also use like this this.up('panel').down('contact')
title = 'Success',
msg = 'Good you have entered the contact details..!';
if (!contactFrm.isValid()) {
title = 'Error';
msg = 'Plese enter at least one contact detail..!'
}
Ext.Msg.alert(title, msg);
}
}]
});

extjs how to bind a field to another existing form

i have a form A containing some fields about questions(a model in my application),but it can not submit directly by form.getForm().submit().the buttons in form A will open another window,and a field on that window.i want to attach the field to form A ,so i can submit those fields together.
the detail is as follows:
enter image description here
In this case, I would try to give two different ID's to forms. Next, retrieve the values from them and merge If the field names are different.
var first_form_values = Ext.getCmp('first-form').getForm().getValues();
var second_form_values = Ext.getCmp('second-form').getForm().getValues();
var all_values = Ext.Object.merge(first_form_values , second_form_values);
Then you have all the values and you can send them by Ext.Ajax etc.
Full example:
Ext.create('Ext.window.Window', {
title: 'First Form',
height: 200,
width: 400,
layout: 'fit',
items: {
xtype: 'form',
id: 'first-form',
items: [
{
xtype: 'textfield',
fieldLabel: 'First field',
name: 'first-field',
}
]
},
buttons: [
{
text: 'Show second form'
handler: function()
{
Ext.create('Ext.window.Window', {
title: 'Second Form',
height: 200,
width: 400,
layout: 'fit',
items: {
xtype: 'form',
id: 'second-form',
items: [
{
xtype: 'textfield',
fieldLabel: 'Second field',
name: 'second-field',
}
]
},
buttons: [
{
text: 'Submit'
handler: function()
{
var first_form = Ext.getCmp('first-form'),
second_form = Ext.getCmp('second-form');
if(first_form && second_form)
{
var fist_form_values = first_form.getForm().getValues(),
second_form_values = second_form.getForm().getValues();
var values = Ext.Object.merge(fist_form_values, second_form_values);
// You have all values from two forms
}
}
}
]
}).show();
}
}
]
}).show();

extjs form panel set default value textfield

This seems like a trivial issue, but... I have a list of addresses in a panel to which I wish to add geolocation coordinates (and to display them on a map) that is rendered in a form panel, so that when I click on the address of interest in the panel an onTap is fired to do execute the onSelectGeolocation given below to open the form panel rendered in the ViewPort and to add any existing records to the associated form elements:
onSelectGeolocation: function(view, index, target, record, event) {
console.log('Selected a Geolocation from the list');
var geolocationForm = Ext.Viewport.down('geolocationEdit');
if(!geolocationForm){
geolocationForm = Ext.widget('geolocationEdit');
}
geolocationForm.setRecord(record);
geolocationForm.showBy(target);
}
The line that uses the setRecord method to write any existing records in my store to the form elements, however, is preventing the default values in my form panel below from getting written to the desired form elements. When I comment this out, all is good. Problem is that I need to grab those records that exist in my store, e.g., address, to display in my form. How can I do this AND write default values to my textfield elements in my form?
My form panel that is rendered as a ViewPort via the onTap is:
Ext.define('EvaluateIt.view.GeolocationEdit', {
extend: 'Ext.form.Panel',
alias : 'widget.geolocationEdit',
requires: [
'Ext.form.Panel',
'Ext.form.FieldSet',
'Ext.field.Number',
'Ext.field.DatePicker',
'Ext.field.Select',
'Ext.field.Hidden'
],
config: {
// We give it a left and top property to make it floating by default
left: 0,
top: 0,
// Make it modal so you can click the mask to hide the overlay
modal: true,
hideOnMaskTap: true,
// Set the width and height of the panel
width: 400,
height: 330,
scrollable: true,
layout: {
type: 'vbox'
},
defaults: {
margin: '0 0 5 0',
labelWidth: '40%',
labelWrap: true
},
items: [
{
xtype: 'datepickerfield',
destroyPickerOnHide: true,
name : 'datOfEvaluatione',
label: 'Date of evaluation',
value: new Date(),
picker: {
yearFrom: 1990
}
},
{
xtype: 'textfield',
name: 'address',
label: 'Address',
itemId: 'address'
},
{
xtype: 'textfield',
name: 'latitude',
label: 'Latitude',
itemId: 'latitude',
value: sessionStorage.latitude,
},
/* {
xtype: 'textfield',
name: 'longitude',
label: 'Longitude',
itemId: 'longitude',
value: sessionStorage.longitude
},
{
xtype: 'textfield',
name: 'accuracy',
label: 'Accuracy',
itemId: 'accuracy',
value: sessionStorage.accuracy
},*/
{
xtype: 'button',
itemId: 'save',
text: 'Save'
}
]
}
});
Behavior is as expected. I will use Ext.getCmp on the id's for each item instead.

use form for add and update data,how is that possible in extjs4?

i have a form panel and a tree panel
the form is used to add new users, the tree is used to show the list of users
what i want is to right click a node in my tree ,click edit (already can do that) then i have my data in the add form panel and be able to modify there and update my user
so basically use the same form for adding and updating
this is how im trying to do up to know
but its not working at all
i added a model to my tree,i used loadRecord(rec), but i dont know how to bind my tree data with the form fields!
tried adding displayfield with same name from my tree model!!
my tree model and store:
Ext.define('TreeModel', {
extend: 'Ext.data.Model',
fields: [
{ name: 'text' },
{ name: 'id' }
]
});
window.ATreeStore = Ext.create('Ext.data.TreeStore', {
model: 'TreeModel',
root: Ext.decode(objt.TreeToJson()),
proxy: {
type: 'ajax'
},
sorters: [{
property: 'leaf',
direction: 'ASC'
}, {
property: 'text',
direction: 'ASC'
}]
});
my tree menu:
var myContextMenu = new Ext.menu.Menu({
items: [{
text: 'Edit',
handler: function () {
Ext.getCmp('addaform').getForm().loadRecord(rec);
}
}
}]
my form:
Ext.define("Ext.app.Adduser", {
extend: "Ext.form.Panel",
title: 'Add user',
id : 'addform',
closable: true,
collapsible: true,
animCollapse: true,
draggable: true,
resizable: true,
margin: '5 5 5 5',
height: 400,
frame: true,
fieldDefaults: {
labelAlign: 'top',
msgTarget: 'side'
},
defaults: {
anchor: '100%'
},
items: [{
layout: 'column',
border: false,
items: [{
padding: '5',
columnWidth: .5,
border: false,
layout: 'anchor',
defaultType: 'textfield',
items: [{
fieldLabel: ' Name',
name: 'name',
allowBlank: false,
displayfield:'id',//
anchor: '95%'
}]
}, {
padding: '5',
columnWidth: .5,
border: false,
layout: 'anchor',
defaultType: 'textfield',
items: [{
fieldLabel: 'First name',
name: 'fname',
allowBlank: false,
anchor: '95%'
}, {
xtype: 'textarea',
fieldLabel: 'Profile',
name: 'prof',
anchor: '95%'
}]
}],
buttons: [{
text: 'Save',
handler: function () {
this.up('form').getForm().submit
({
url: 'AddData.ashx',
params: { action: 'add' },
success: function (form, action)
{
Ext.MessageBox.show({ title: 'Success !',
msg: 'User added successfully<br />',
icon: Ext.MessageBox.INFO,
buttons: Ext.MessageBox.OK
}) }
}) }]
thank you
If your TreePanel uses a TreeStore which in turn has a Ext.data.Model, then when you right click on a node (say nodeA), you should be just able to do form.loadRecord(nodeA), the API for loadRecord is here
If it's still not clear, I think this blog post could help, it talks about loading a grid record into a form. I know it's not ExtJS 4, but the key functions are the same.
Ok, let me show this with a super simple example, hope it will help.
First we create the form that we want to display stuff in, note that the renderTo property is bound to a div inside my HTML, so you might need to change that. Also note that the name property of the textarea and textfield, they are the key for the loadRecord to work, they have to match the fields defined in the model later.
var form = Ext.create('Ext.form.Panel',{
renderTo : 'form-div',
items : [{
xtype : 'textarea',
fieldLabel : 'label 1',
name : 'name'
},{
xtype : 'textfield',
fieldLabel : 'label 2',
name : 'age'
}]
});
Next, we create the tree to display our data, we start by creating a simple model :
Ext.define('Person',{
extend : 'Ext.data.Model',
fields : [{
name : 'name',
type : 'string'
},{
name : 'age',
type : 'int'
}]
});
Then we create a TreeStore that uses that model and initialize it with some inline data:
var store = Ext.create('Ext.data.TreeStore',{
model : 'Person',
root : {
expanded : true,
children : [{
name : 'John',
age : 10,
leaf : true
},{
name : 'Joe',
age : 100,
leaf : true
}]
}
});
Then we create the tree to display the data in the store. (Note that the nodes will show up as "undefined" because we are not using the default "text" property of a Node)
var tree = Ext.create('Ext.tree.Panel',{
height : 300,
width : 300,
store : store,
rootVisible : false,
renderTo : 'tree-div',
listeners : {
itemclick : function(view, record){
form.loadRecord(record);
}
}
});
Now, you should see a tree with two nodes both displayed as "undefined" on your page, as well as a Form with a textarea and a textfield. If you click on a node inside the tree, the form will display the name and age of the selected node.

Extjs can't dynamically add/remove fields in formpanel

I have a form panel that uses a table layout to display a form. I need to add in functionality to add /remove a set of components.
The add button should add a new row of components underneath the existing elements & the remove button should remove that last added row.
The formpanel can add a new field but it's appearing below the buttons and the form is not increasing in width (see screen shot below). I've tried this with both the insert and add function but both have the same effect.
Does anyone know how:
1) I can add a series of components in the next row?
2) How I can remove the next row.
Partial formPanel code & button code:
![SearchForm = Ext.extend(Ext.FormPanel, {
id: 'myForm'
,title: 'Search Form'
,frame:true
,waitMessage: 'Please wait.'
//,labelWidth:80
,initComponent: function() {
var config = {
items: [{
layout:{
type:'table',
columns:5
},
buttonAlign:'center',
defaults:{
//width:150,
//bodyStyle:'padding:100px'
style:'margin-left:20px;'
},
items:[//row 1
{
xtype: 'label',
name: 'dateLabel',
cls: 'f',
text: "Required:"
},
{
xtype: 'container',
layout: 'form',
items: {
xtype: 'datefield',
fieldLabel: "From Date",
value: yesterday,
width: 110,
id: 'date1'
}
}][1]
buttons: [{
text: 'Add More Criteria (max 10 items)',
id: "addBtn",
scope: this,
handler: function(){
alert('hi');
/*this.items.add({
xtype : 'textfield',
fieldLabel : 'Extra Field',
name : 'yourName',
id : 'yourName'
}); */
this.insert(4,{
xtype: 'textfield',
id: 'input20',
//hideLabel: true,
width: 180,
fieldLabel: 'hi'
});
this.doLayout();
}
}
Easiest way would be to have a fieldset in the form to hold all the 'rows' and then add a row to this fieldset using fielset.add()
(Your 'row' can be another fieldset that has all the fields)
Dynamic form fields generation seems to be obvious and there are lots of examples and some blogs for mootools etc but in extjs world i couldn`t find a working example(probably because most people use powerful Extjs grid).I had to invent one by myself for MedAlyser project! and im sharing it with you.she might have bugs and/or be incomplete but i hope she helps a bit.
function addressCounter(incr) {
if (!this.no) {
this.no = 0;
} else {
this.no = this.no + 1;
};
};
var counter = new addressCounter();
console.log(counter.no);
//put below code inside your form items
{
xtype: 'button',
text: 'Add address ',
id: 'addaddress',
handler: function () {
counter.no = counter.no + 1;
console.log(counter.no);
Ext.getCmp('patientaddress').add([{
xtype: 'combo',
store: 'AddressType',
displayField: 'name',
valueField: 'name',
fieldLabel: 'Address Type',
id: 'addresstype' + counter.no,
name: "Patientaddress[addresstype][]",
value: 'Home'
}, {
fieldLabel: 'zip',
width: 160,
maxLength: 10,
enforceMaxLength: true,
maskRe: /[\d\-]/,
regex: /^\d{5}(\-\d{4})?$/,
regexText: 'Must be in the format xxxxx or xxxxx-xxxx',
name: "Patientaddress[zip][]",
id: 'zip' + counter.no
}, {
fieldLabel: 'Address 1',
name: "Patientaddress[address1][]",
id: 'address1' + counter.no
}, {
fieldLabel: 'Address 2',
name: "Patientaddress[address2][]",
id: 'address2' + counter.no
}, {
fieldLabel: 'City',
name: "Patientaddress[city][]",
id: 'city' + counter.no
}, {
fieldLabel: 'State',
name: "Patientaddress[state][]",
id: 'state' + counter.no
}, {
xtype: 'combo',
store: Ext.create('MA.store.Countries'),
displayField: 'name',
valueField: 'id',
forceSelection: true,
fieldLabel: 'Country',
typeAhead: true,
queryMode: 'local',
name: "Patientaddress[country][]",
id: 'country' + counter.no
} // eof
// countries;
,
Ext.getCmp('addaddress'), {
xtype: 'button',
text: 'Remove address',
id: 'removeaddress' + counter.no,
handler: function (
thisButton, eventObject) {
activeRemoveButtonId = thisButton.getId().split('removeaddress')[1];
console.log('activeRemoveButtonID:' + activeRemoveButtonId);
Ext.getCmp('patientaddress').remove('address1' + activeRemoveButtonId);
Ext.getCmp('patientaddress').remove('address2' + activeRemoveButtonId);
Ext.getCmp('patientaddress').remove('city' + activeRemoveButtonId);
Ext.getCmp('patientaddress').remove('state' + activeRemoveButtonId);
Ext.getCmp('patientaddress').remove('country' + activeRemoveButtonId);
Ext.getCmp('patientaddress').remove('removeaddress' + activeRemoveButtonId);
Ext.getCmp('patientaddress').remove('addresstype' + activeRemoveButtonId);
Ext.getCmp('patientaddress').remove('zip' + activeRemoveButtonId);
Ext.getCmp('patientaddress').doLayout();
}
}]);
Ext.getCmp('patientaddress').doLayout();
} // eof function
}, // eof Add button
Removing fields was more complicated because the remove button needs to know exactly which field has to be removed. This code creates new fields and removes them correctly as you asked for.Any suggestions are welcome.