I have an attribute in the extjs code defined as :
datajson: {
'name' : 'Hello',
....
}
Now I need to set the value of a textfield to the name defined inside this attribute.
I have tried the following but its not working:
Ext.getCmp('name').setValue((this.datajson.xyz.name).toString());
The id of the textfield whose value I am trying to set is 'name'
Here is the full code structure.
Ext.define('Test', {
extend : 'Ext.Container',
alias : 'widget.myapp',
datajson:{
'xyz' : {
...
"name" : 'Hello',
...
}
},
initComponent : function() {
this.appcombo = Ext.create('Ext.form.field.ComboBox', {
store: Ext.create('Ext.data.Store', {
fields: ['text'],
data: [
{text: "a"},
{text: "b"},
{text: "c"}
]
}),
listeners: {
select: function(combo, record, index) {
Ext.getCmp('name').setValue((this.datajson.xyz.name).toString());
}
}
});
...
...
//Here we have a textfield within a Panel whose id is 'name'
So basically I am loading the page and then selecting one value in combo box which serves as the event to load the values in the text-fields with the data which is in datajson.
EDIT: More information added.
The scope within your select function no longer contains datajson. To continue to use this.datajson you can pass the required scope into the function using bind
Ext.application({
name: 'Fiddle',
datajson: {
'name': 'Hello'
},
displayName: function (combo, record, index) {
Ext.getCmp('name').setValue((this.datajson.name));
},
launch: function () {
Ext.create('Ext.form.Panel', {
title: 'Contact Info',
width: 300,
bodyPadding: 10,
renderTo: Ext.getBody(),
items: [{
xtype: 'combo',
store: Ext.create('Ext.data.Store', {
fields: ['text'],
data: [{
text: "a"
}, {
text: "b"
}, {
text: "c"
}]
}),
listeners: {
select: this.displayName.bind(this)
}
}, {
xtype: 'textfield',
id: 'name',
fieldLabel: 'Name'
}]
});
}
});
Related
I am new in Extjs. I have a container with card layout with 3 sub views including a grid, a form for creating and a form for updating using route.
items: [
{xtype: 'feature-grid',id:'feature-grid},
{xtype: 'create-form'},
{xtype: 'update-form'}
],
it works well at the first time but when I change the route and switch to this route again this error appears:
Uncaught Error: DOM element with id feature-grid in Element cache is not the same as element in the DOM. Make sure to clean up Element instances using destroy()
and when I remove the id the save button in my create form doesnt add record to the grid without any error!
my save button is like this:
var form = button.up('formpanel');
var values = form.getValues();
var user = Ext.create('App.model.User',values);
var cntr = this.getView('UserContainer')
var mainpanel = button.up('user-container');
var grid = mainpanel.down('grid');
grid.store.add(user);
form.reset();
this.redirectTo('users')
any idea?
As you are using routes so in this case first you need to check you view is already created or not. If view is already created then you can use that view otherwise you can create view.
In this FIDDLE, I have create a demo using cardlayout, grid and form. I hope this will help/guide you to achieve your requirement.
CODE SNIPPET
Ext.application({
name: 'Fiddle',
launch: function () {
//Define cotroller
Ext.define('MainController', {
extend: 'Ext.app.ViewController',
alias: 'controller.maincontroller',
routes: {
'application/:node': 'onViewChange'
},
//this event will fire whenver routing will be changed
onViewChange: function (xtype) {
var view = this.getView(),
newNode = view.down(xtype);
//if view is not crated then 1st created
if (!newNode) {
newNode = Ext.create({
xtype: xtype
});
}
// is new view is form then first reset the form
if (newNode.isXType('form')) {
newNode.reset();
}
// if new view type is update-form then load the record
if (xtype == 'update-form') {
newNode.setRecord(this.record)
this.record = null;
}
//If view is created then directly set active that view
view.setActiveItem(newNode);
},
//this event will fire when main view render
onMainViewAfterRedner: function () {
this.redirectTo('application/feature-grid');
},
//this event will fire when grid items clicked
onGridItemClick: function (grid, index, target, record, e, eOpts) {
this.record = record;
this.redirectTo('application/update-form');
},
//this event will fire when cancel button clicked
onCancelButtonClick: function () {
this.redirectTo('application/feature-grid');
},
//this event will fire when add new button clicked
onAddNew: function () {
this.redirectTo('application/create-form');
},
//this event will fire when save button clicked
onSaveButtonClick: function (button) {
var me = this,
form = button.up('formpanel'),
store = me.getView().down('grid').getStore(),
values = form.getValues();
if (form.xtype == 'update-form') {
store.findRecord('id', values.id).set(values);
} else {
if (values.name && values.email && values.phone) {
delete values.id;
store.add(values);
} else {
Ext.Msg.alert('Info','Please enter form details');
return false;
}
}
this.onCancelButtonClick();
}
});
Ext.define('AppForm', {
extend: 'Ext.form.Panel',
layout: 'vbox',
bodyPadding: 10,
defaults: {
xtype: 'textfield',
//flex: 1,
width: '100%',
margin: '10 5',
labelAlign: 'top',
allowBlank: false
},
items: [{
name: 'id',
hidden: true
}, {
name: 'name',
label: 'Name'
}, {
name: 'email',
label: 'Email'
}, {
name: 'phone',
label: 'Phone Number'
}, {
xtype: 'toolbar',
defaults: {
xtype: 'button',
ui: 'action',
margin: 5,
flex: 1
},
items: [{
text: 'Save',
formBind: true,
handler: 'onSaveButtonClick'
}, {
text: 'Cancel',
handler: 'onCancelButtonClick'
}]
}]
});
//this create-form.
Ext.define('CreateForm', {
extend: 'AppForm',
alias: 'widget.create-form',
title: 'Create form'
});
//this update-form.
Ext.define('UpdateForm', {
extend: 'AppForm',
alias: 'widget.update-form',
title: 'Update form'
});
//this feature-grid.
Ext.define('fGrid', {
extend: 'Ext.panel.Panel',
alias: 'widget.feature-grid',
title: 'User List grid',
layout: 'vbox',
items: [{
xtype: 'grid',
flex: 1,
store: {
fields: ['name', 'email', 'phone'],
data: [{
name: 'Lisa',
email: 'lisa#simpsons.com',
phone: '555-111-1224'
}, {
name: 'Bart',
email: 'bart#simpsons.com',
phone: '555-222-1234'
}, {
name: 'Homer',
email: 'homer#simpsons.com',
phone: '555-222-1244'
}, {
name: 'Marge',
email: 'marge#simpsons.com',
phone: '555-222-1254'
}]
},
columns: [{
text: 'Name',
dataIndex: 'name',
flex: 1
}, {
text: 'Email',
dataIndex: 'email',
flex: 1
}, {
text: 'Phone',
dataIndex: 'phone',
flex: 1
}],
listeners: {
itemtap: 'onGridItemClick'
}
}],
tools: [{
type: 'plus',
iconCls: 'x-fa fa-plus',
handler: 'onAddNew'
}],
flex: 1
});
//Define the main view form extending panel
Ext.define('MainView', {
extend: 'Ext.panel.Panel',
controller: 'maincontroller',
alias: 'widget.mainview',
layout: 'card',
listeners: {
painted: 'onMainViewAfterRedner'
}
});
//this will create main view that is card layout
Ext.create({
xtype: 'mainview',
renderTo: Ext.getBody(),
fullscreen: true
});
}
});
i have json like this.
firstName: 'xyz',
comments : [{
emailAddress : "abc#gmail.com", body : "PQR",
emailAddress : "xyz#gmail.com", body : "XYZ",
}]
i want to show firstName in the textfield which is editable. and want to show comments in the grid. i am not able to understand how to do it. please help me with that.
my view is following:
Ext.define("SampleView", {
extend: "Ext.panel.Panel",
alias: 'widget.sample',
id : 'sampleVId',
requires: ['StudentViewModel'],
viewModel: {
type: 'StudentViewModel'
},
layout: {
type: 'vbox',
align: 'stretch'
},
initComponent: function() {
Ext.apply(this, {
items: [this.form(), this.grid()],
});
this.callParent(arguments);
},
grid: function(){
return {
xtype: 'grid',
reference: 'samplegrid',
id : 'samplegridId',
bind: {
store: '{comment}'<-- not able to do the binding
},
flex:1,
margin: 10,
plugins: {
ptype: 'rowediting',
clicksToEdit: 2
},
columns: [{
text: 'Email',
dataIndex: 'email',
flex: 1,
editor: {
allowBlank: false
}
}, {
text: 'Role',
dataIndex: 'body',
}],
}
}
},
form : function(){
return{
xtype : 'form',
items:[{
xtype: 'textfield',
fieldLabel: 'First Name',
bind: {
value: '{firstName}'<---- how to bind this valuw to textfield
}
}]
}
}
});
my view model is like this:
Ext.define('StudentViewModel', {
extend: 'Ext.app.ViewModel',
alias:'viewmodel.StudentViewModel',
requires: [
'Student'
],
stores: {
orderStore: {
autoLoad:true,
type: 'sampleS'
}
}
});
my model is like this:
Ext.define('Student', {
extend: 'Ext.data.Model',
idProperty: 'Id',
schema: {
namespace: 'sample',
proxy: {
type:'ajax',
url: 'users.json',
reader:{
type:'json',
rootProperty:'data'
}
}
},
fields: [
{ name: 'Id', type: 'int' },
{ name: 'firstName', type: 'string' },
]
});
Your binding would have to be based on the record selected.
Your model for student needs to be defined to have a hasMany reference to a comments model so a proper store is built to be bound, or you would have to dynamically create a store based on the array data within the model. I would suggest just using a relation, its easier to do in the long run.
where you have the binding of
value: {firstName}
It should be
value: {student.firstName}
In your view controller you would have to bind student to the student model you are trying to display in the form using a line that looks like
vm.setValue('student', YOURMODELOBJECTHERE);
If the student model has a proper has many relation for comments, then the rest should be okay.
Let's say I've got a ViewController, ViewModel, and my View. In the View, I've got a form panel that gets a loaded record. When this record loads into the form, I want to hide or show a button based on the record's status field, so I figured do something with binding. However, it looks like binding is limited to only inverting, not actually using an expression. To get a better understanding, take a look at this code:
Ext.application({
name : 'Fiddle',
launch : function() {
Ext.define('User', {
extend: 'Ext.data.Model',
fields: ['name', 'status']
});
Ext.define('UserListController', {
extend : 'Ext.app.ViewController',
alias: 'controller.userlist'
});
Ext.define('UserListViewModel', {
extend: 'Ext.app.ViewModel',
alias: 'viewmodel.userlist'
});
Ext.define('UserList', {
extend: 'Ext.form.Panel',
controller: 'userlist',
viewModel: 'userlist',
tbar: [{
text: 'Add',
reference: 'addButton',
bind: {
//hidden: '{status == 2}'
}
}, {
text: 'Delete',
reference: 'deleteButton',
bind: {
//hidden: '{status == 1}'
}
}],
items: [{
xtype: 'displayfield',
name: 'name',
fieldLabel: 'Name'
}, {
xtype: 'displayfield',
name: 'status',
fieldLabel: 'Status'
}]
});
var myForm = Ext.create('UserList', {
width: 400,
height: 200,
renderTo: Ext.getBody()
});
var record = Ext.create('User', {
name: 'blah',
status: 2
});
myForm.loadRecord(record);
if (record.get('status') === 2) {
myForm.lookupReference('addButton').hide();
}
}
});
As you can see, I'm currently just probing the values of the record to hide the addButton. Is there anyway I can accomplish this with binding or some other approach? It's good to note that I also looked at formulas, but from what I'm understanding, that's only for changing how data is rendered, so it didn't seem like the proper route.
If your record is part of the view model data - use formulas, like:
formulas: {
hideDeleteButton: function (getter) {
return getter('record.status') === 2;
},
hideAddButton: function (getter) {
return getter('record.status') === 1;
}
}
And then in your view you can bind:
{
text: 'Add',
reference: 'addButton',
bind: {
hidden: '{hideAddButton}'
}
}, {
text: 'Delete',
reference: 'deleteButton',
bind: {
hidden: '{hideDeleteButton}'
}
}
A working example: https://fiddle.sencha.com/#fiddle/mcg
I'm trying to delegate an event for multiple items by a common class name, but, it seems not to be working. Delegating for multiple IDs should work but I'm getting an error message about: "Invalid ComponentQuery selector".
This is what I have at the moment:
Ext.define("App.view.Main", {
extend : "Ext.Container",
config : {
listeners : {
disclose : {
fn : "onElementDisclose",
delegate : [ "#onelist", "#anotherlist" ] // this don't work
// delegate : ".lists" <- this also don't work
// delegate : "#onelist, #anotherlist" <- this don't work either
// delegate : "#onelist" <- but this work!
}
},
},
initialize : function() {
this.callParent(arguments);
this.add([ {
xtype : "slideshow",
}, {
xtype : "onelist",
}, {
xtype : "anotherlist",
} ]);
},
onElementDisclose : function () {
console.log("click");
},
});
Both lists have "onItemDisclosure : true" and "cls: lists".
How can I achieve this?
This certainly works to a degree and you don't have to delegate it in the controller as demonstrated here:
Ext.application({
name: 'Fiddle',
launch: function() {
Ext.create('Ext.Panel', {
fullscreen: true,
title: 'Test',
layout: 'vbox',
items: [{
xtype: 'panel',
layout: 'fit',
flex: 1,
items: [{
docked: 'top',
xtype: 'titlebar',
title: 'List 1'
}, {
xtype: 'list',
name: 'list 1',
cls: 'myList',
id: 'list1',
onItemDisclosure: true,
itemTpl: "List1 item {name}",
model: Ext.define('User', {
extend: 'Ext.data.Model',
config: {
fields: [{
name: 'name',
type: 'string'
}]
}
}),
data: [{
name: 'John'
}, {
name: 'Jane'
}]
}]
}, {
xtype: 'panel',
layout: 'fit',
flex: 1,
items: [{
docked: 'top',
xtype: 'titlebar',
title: 'List 2'
}, {
xtype: 'list',
name: 'list 2',
cls: 'myList',
id: 'list2',
onItemDisclosure: true,
itemTpl: "List2 item {make}",
model: Ext.define('Car', {
extend: 'Ext.data.Model',
config: {
fields: [{
name: 'make',
type: 'string'
}]
}
}),
data: [{
make: 'Volkswagen'
}, {
make: 'Audi'
}]
}]
}],
listeners: {
disclose: {
fn: function(list, record, target, index, e, eOpts) {
console.log(list);
var greeting = '';
if (typeof(record.data.make) != 'undefined') {
greeting = "I am a car and my make is " + record.data.make + "!";
} else if (typeof(record.data.name) != 'undefined') {
greeting = "I am a user and my name is " + record.data.name + "!";
};
console.log('disclosing from list ' + list.config.name, greeting);
},
// delegate : 'list' // this works as you are querying by xtype of list
// delegate : 'component [onItemDisclosure]' // this works as you are targeting by attribute of onItemDisclosure
// delegate : '[onItemDisclosure]' // this works as you are targeting by attribute
// delegate : '[name="list 1"]' // this works as you are targeting by attribute of name = 'list 1'
// delegate : '[cls="myList"]' // this unfortunately doesn't work
// delegate : "#list1, #list2" <- this don't work either
// delegate : "#list1" <- but this work!
}
}
});
}
});
However there are some pitfalls with the above as you can see.
Demo: https://fiddle.sencha.com/#fiddle/g49
You cannot fire same function using common events on multiple control defining listeners in view.
Yes you can do the same in controller. it will work undoubtedly..
Thanks
Sachin
I am using extjs 4.1 and trying to do the event delegation which in my case is to attach a blur event to all the textfields of my form and it is not working and i am not getting any error in firebug too, i don't know where i am going wrong in attaching the event, is it the wrong place where i am putting the code and also i have noticed that as per the docs below link:
http://docs.sencha.com/ext-js/4-1/#!/api/Ext.form.Panel-method-on
the delegate property of the options object no longer exists. Below is my code:
Ext.onReady(function () {
var loadForm = function () {
Ext.getCmp('TestForm').getForm().setValues({ name: 'some text', email: 'first', dob: '12/12/2009' });
}
Ext.define('userForm', {
extend: 'Ext.form.Panel'
, alias: 'widget.userform'
, frame: true
, initComponent: function () {
Ext.apply(this, {
title: 'User Form'
, height: 350
, items: [{
xtype: 'textfield'
, fieldLabel: 'Name'
, name: 'name'
, id: 'nameId'
, enableKeyEvents: true
}, {
xtype: 'textfield'
, fieldLabel: 'Email'
, name: 'email'
, id: 'emailId'
}, {
xtype: 'datefield',
fieldLabel: 'DOB',
id: 'dob',
name: 'dob',
format: 'Y-m-d'
}, {
xtype: 'textfield',
fieldLabel: 'Age',
id: 'age',
name: 'age'
}, {
xtype: 'textfield',
fieldLabel: 'Guardian',
id: 'guardian',
name: 'guardian'
}]
});
this.callParent(arguments);
} //eoinitComponent
});
var userForm = Ext.create('userForm', {
renderTo: 'loadPanel',
id: 'TestForm',
listeners: {
afterrender: function (formCmp, eOpts) {
loadForm();
},
render: function (formCmp, eOpts) {
Ext.getCmp("TestForm").on(
'blur',
function (e, t) {
// handle blur
console.info(t.id);
},
this,
{
// filter the target element to be a descendant with the class '.x-form-field'
delegate: '.x-form-field'
}
);
}
}
});
});
To begin with, the on method does not take delegate as a parameter, so that line is completely unnecessary.
Then, within your render event, you can just use formCmp.on() rather than Ext.getCmp().on().
Lastly, you want blur event on every field, not on the form itself. The following code should work:
render: function (formCmp, eOpts) {
// For each field.
formCmp.getForm().getFields().each( function( aField ) {
// If it's a textfield.
if ( aField.is('textfield') ) {
aField.on( 'blur', this.onFieldBlur, this)
}
}, this ); // notice the this scope for the each method.
}