Sencha Touch Combo Box using Model and Store - extjs

I have this on model
Ext.define('MyApp.model.job', {
extend: 'Ext.data.Model',
alias: 'model.job',
config: {
fields: [{
name: 'name',
type: 'string'
}, {
name: 'value',
type: 'string'
}]
}
});
And this on store
Ext.define('MyApp.store.job', {
extend: 'Ext.data.Store',
alias: 'store.job',
requires: [
'MyApp.model.job'
],
config: {
autoLoad: true,
data: [
{
name: '--Please Select--',
value: ''
}, {
name: 'Job 1',
value: 'Job1'
}, {
name: 'Job 2',
value: 'Job2'
}, {
name: 'Job 3',
value: 'Job3'
}
],
model: 'MyApp.model.job',
storeId: 'jobStore'
}
});
And this is the View
{
xtype : 'selectfield',
name : 'job',
label : 'Job',
displayField : 'name',
valueField : 'value',
store: 'jobStore'
}
But I got the following error on Console
"Uncaught TypeError: Cannot call method 'on' of undefined"
Can someone help me?

In the job store, remove the unneccessary line storeId: 'jobStore' and in the view edit store to store: 'job' and your code will be working fine.
Beside this, i would ask you to remove few line of code from your snippet(Because in standard Sencha coding, we follow certain rules).
requires: [
'MyApp.model.job'
],
alias: 'store.job'
alias: 'model.job'
Happy coding. :)
EDIT
In app.js of your application, you should write
models: ['job'],
stores: ['job']
instead model and store.

Related

Data binding associations in ExtJS admin template

I'm unsuccessful in getting binding associations working in the admin dashboard template (with the desired behavior of selecting a record from a combobox and pulling up associated records in a grid).
My main viewModel is defined as:
Ext.define('Admin.view.main.MainModel', {
extend: 'Ext.app.ViewModel',
alias: 'viewmodel.main',
stores: {
patients: {
model: 'md_registry.model.Patient',
autoLoad: true
}
}
});
I added a leaf node to Pages in NavigationTree.js:
{
text: 'Pages',
iconCls: 'x-fa fa-leanpub',
expanded: false,
selectable: false,
//routeId: 'pages-parent',
//id: 'pages-parent',
children: [
{
text: 'Proc',
iconCls: 'x-fa fa-send',
rowCls: 'nav-tree-badge nav-tree-badge-hot',
viewType: 'procedure',
leaf: true
}]
}
With the procedure view being:
Ext.define('Admin.view.pages.Procedure', {
extend: 'Ext.panel.Panel',
xtype: 'procedure',
requires: [
'Ext.panel.Panel',
'Admin.model.Patient',
'Admin.model.Procedure'
//'Admin.model.Diagnosis'
],
anchor : '100% -1',
referenceHolder: true,
width: 1000,
height: 1000,
referenceHolder: true,
layout: {
type: 'hbox',
align: 'stretch'
},
viewModel: 'main',
session: {},
items: [
// https://www.sencha.com/forum/showthread.php?299301-Bind-combobox-displayField-value-to-displayfield
{
xtype: 'fieldset',
layout: 'anchor',
items: [{
xtype: 'combobox',
listeners : {
select : function() {
console.log(arguments)
console.log(arguments[1].data.birth_date)
console.log(arguments[1].data.first_name)
console.log(arguments[1].data.last_name)
console.log(arguments[1].data.sex)
}
},
bind: {
store: '{patients}'
},
reference: 'patientCombo',
publishes: 'id',
fieldLabel: 'Patient Search',
displayField: 'mrn',
//anchor: '-',
// We're forcing the query to run every time by setting minChars to 0
// (default is 4)
minChars: 2,
queryParam: '0',
queryMode: 'local',
typeAhead: true,
// https://www.sencha.com/forum/showthread.php?156505-Local-combobox-with-any-match-filter
doQuery: function(queryString, forceAll) {
this.expand();
this.store.clearFilter(!forceAll);
if (!forceAll) {
this.store.filter(this.displayField, new RegExp(Ext.String.escapeRegex(queryString), 'i'));
}
}
}, {
// https://www.sencha.com/forum/showthread.php?299301-Bind-combobox-displayField-value-to-displayfield
xtype: 'displayfield',
fieldLabel: 'Selected Patient',
bind: {
html: '<p>Name: <b>{patientCombo.selection.first_name}, ' +
'{patientCombo.selection.last_name} </b></p>' +
'<p>Sex: {patientCombo.selection.sex}</p>' +
'<p>Birthdate: {patientCombo.selection.birth_date}</p>'
}
}]
},
{
title: 'Procedures',
xtype: 'grid',
bind: '{patientCombo.selection.procedures}',
flex: 1,
margin: '0 0 0 10',
columns: [{
text: 'Procedure Date', dataIndex: 'proc_date', flex: 1
}, {
text: 'Procedure', dataIndex: 'proc_name', flex: 1
}],
plugins: [{
ptype: 'rowexpander',
rowBodyTpl : new Ext.XTemplate(
'<p><b>Proc Name Orig:</b> {proc_name_orig}</p>',
'<p><b>Proc Code:</b> {proc_code}</p>',
'<p><b>Proc Code Type:</b> {proc_code_type}</p>')
}],
viewConfig: {
emptyText: 'No procedures',
deferEmptyText: false
}
}]
});
My Patient and Procedure models are simply:
Ext.define('Admin.model.Procedure', {
extend: 'Ext.data.Model',
idProperty: 'id',
fields: [
//{ name: 'id', type: 'string' },
{ name: 'proc_code', type: 'string' },
{ name: 'proc_name', type: 'string' },
{ name: 'proc_code_type', type: 'string' },
{ name: 'proc_name_orig', type: 'string' },
{ name: 'proc_date', type: 'date', format: 'Y-m-d' },
{
name: 'patient_id',
type: 'string',
reference: {
parent: 'Admin.model.Patient',
//type: 'md_registry.model.Patient',
inverse: 'procedures',
autoLoad: false
}
}
],
proxy: {
type: 'rest',
url: 'http://127.0.0.1:5000/procedureview/api/read',
reader: {
type: 'json',
rootProperty: ''
}
}
});
and
Ext.define('Admin.model.Patient', {
extend: 'Ext.data.Model',
requires: [
'Ext.data.proxy.Rest'
],
fields: [
{ name: 'id', type: 'string' },
{ name: 'mrn', type: 'string' },
{ name: 'birth_date', type: 'date', format: 'Y-m-d' },
{ name: 'sex', type: 'string' },
{ name: 'first_name', type: 'string' },
{ name: 'last_name', type: 'string' }
],
proxy: {
type: 'ajax',
url: 'http://127.0.0.1:5000/patientview/api/read',
reader: {
type: 'json',
rootProperty: ''
}
}
});
respectively.
The data for my Patients store are getting loaded into the combobox just fine, but when I select an item from the combo list it is not firing off the call to grab the associated procedures data (see image: .
However, the binding associations work as expected with Side Navigation Tabs (see image: , and show up within the object prototype chain, as expected... see
(whereas for the admin dashboard, the associations are empty).
I cannot for the life of me get these working in the Admin Dashboard. I noticed a tool called the bind inspector, but I am running the GPL version of the SDK, so I do not have access to this. Beyond this, I cannot figure out a way to debug why the binding association is not working in the admin dashboard, but otherwise works perfectly well in Side Navigation Tabs.
I would set up a Fiddle, but I have no idea how to do it using the Admin Template.
I just figured it out. It was a namespace issue.
My reference in the procedure model should be:
reference: {
parent: 'Patient',
inverse: 'procedures',
autoLoad: false
}
Voila, all the associated data get loaded as expected!

How to do Data binding in extjs 6

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.

Sencha touch Error: Uncaught Error The following classes are not declared even if their files have been loaded: 'Ext.data.model'

"Uncaught Error: The following classes are not declared even if their files have been loaded: 'Ext.data.model'. Please check the source code of their corresponding files for possible typos: 'touch/src/data/model.js "
I am getting this error which I have no idea why is being generated. Here is my code have a look because i have turned every stone But still no answer. It seems every tiem i write a code few hours goes to figuring out what is wrong with sencha touch
App.js
//<debug>
Ext.Loader.setPath({
'Ext': 'touch/src',
'TutsPlus': 'app'
});
//</debug>
Ext.application({
//http://docs.sencha.com/touch/2-1/#!/api/Ext.app.Application
name: 'TP',
views: ['Main'],
models: ['mtask'],
stores: ['stask'],
launch: function() {
// Destroy the #appLoadingIndicator element
Ext.fly('appLoadingIndicator').destroy();
// Initialize the main view
Ext.Viewport.add(Ext.create('TP.view.Main'));
}
});
In Store stask.js
Ext.define('TP.store.stask', {
extend: 'Ext.data.Store',
config: {
//Define which model we are going to use for our store
model: 'TP.model.mtask',
data: [
{label: 'Make the change'},
{label: 'Take the trash'},
{label: 'Clear the room'},
{label: 'Wake Up Early'}
]
}
});
In Model mtask.js
Ext.define('TP.model.mtask', {
extend: 'Ext.data.Model',
config: {
fields: [
{name: 'label', type: 'string'},
{nae: 'done', type: 'boolean', defaultValue: false}
]
}
});
In view folder Main,js
Ext.define('TP.view.Main', {
extend: 'Ext.Panel',
xtype: 'main',
requires: [
'Ext.TitleBar',
'Ext.dataview.List'
],
config: {
layout: 'vbox',
items: [
{
docked: 'top',
xtpe: 'titlebar',
title: 'Note Taker',
items: [
{
iconCls: 'add',
iconMask: true,
align: 'right',
id: 'add-button'
}
]
},
{
xtype: 'list',
store: 'stask'
}
]
}
});
For some reason, your model class is not getting declared. Try finding out the reason with syntax errors and cases.
Try changing:
nae: 'done' to name: 'done'

Load data to form in mvc

In my appliacation , I have a list and detail(form).I want to load data to Detail view(set data to textfields of form) when list item is clicked. For both list and detail, I am getting data from remote server. I am following MVC.
Now, When listItem is clicked, I am able to get data from server and save it to store and also showing detail view. But I am not able to bind data from store to textfields in form.
Model
Ext.define('App.model.Details', {
extend: 'Ext.data.Model',
config: {
fields: [
{name: 'Name', type: 'string'},
{name: 'BillingStreet', type: 'string'},
{name: 'BillingCity', type: 'string'}
]
}
});
Store
Ext.define('App.store.Details', {
extend: 'Ext.data.Store',
config: {
model: 'App.model.Details',
autoLoad :true,
grouper : function(record) {
return record.get('Name')[0];
},
}
});
list view
Ext.define('App.view.View', {
extend: 'Ext.List',
alias:'widget.contactlist',
fullscreen: true,
id: 'contactlist',
config:{
disableSelection:true,
store:'Contacts',
itemTpl:'{Name}',
items:[
{
xtype:'toolbar',
docked:'top',
title:'Leeds List'
}
]
}
});
Detail view
Ext.define("App.view.ListDetail", {
extend: "Ext.form.Panel",
requires: "Ext.form.FieldSet",
alias: "widget.listDetail",
config:{
scrollable:'vertical'
},
initialize: function () {
this.callParent(arguments);
var topToolbar = {
xtype: "toolbar",
docked: "top",
title: "Details"
};
this.add([
topToolbar,
{ xtype: "fieldset",
items: [{
xtype: 'textfield',
store: 'Details',
value : 'Name',
label: 'Name'
},
{
xtype: 'emailfield',
store: 'Details',
value : 'BillingStreet',
label: 'Email'
},
{
xtype: 'passwordfield',
store: 'Details',
value : 'BillingCity',
label: 'Password'
}
]
}
]);
}
});
Controller
Ext.define('App.controller.Main', {
extend: 'Ext.app.Controller',
config: {
refs: {
// We're going to lookup our views by xtype.
contactlist: "contactlist",
contactdetail: "listDetail",
//f_name:"#f_name"
},
control: {
contactlist: {
// The commands fired by the notes list container.
itemtap: "oneditLeadCommand"
}
},
routes: {
'contactlist': 'activateList'
}
},
activateList: function ()
{
Ext.Viewport.animateActiveItem(this.getContactlist(), this.slideRightTransition);
},
slideLeftTransition: { type: 'slide', direction: 'left' },
slideRightTransition: { type: 'slide', direction: 'right' },
oneditLeadCommand: function (list, index, target, record, e, eOpts)
{
console.log("onEditLead"+record.data.Id);
this.activateLeadDetail(record);
},
activateLeadDetail: function (record)
{
var contactDetail = this.getContactdetail();
//console.log("activateLeadDetail"+contactDetail.textfield);
//contactDetail.setRecord(record); // load() is deprecated.
//this.getF_name().setDisplayField("");
store = Ext.StoreMgr.get('Details');
//console.log("activateLeadDetail"+store);
store.setProxy({
type: 'ajax',
url : 'http://10.0.2.2:8080/SalesForce/leads/get-lead-details/00D90000000jvoU!AR4AQB6Xcjz4UNBKf12WOcYHWc31QxK2.fXTcbCvOq.oBosCrjBezhqm8Nqc1hrf8MKK5LjLAu8ZC5IqB1kdpWvJGLdWd5pJ/'+record.data.Id, // the json file that holds all our contact info.
reader: {
type: 'json'
}
});
store.load();
var record1 = Ext.StoreMgr.get('Details').getAt(0);
console.log("activateLeadDetail"+record1);
Ext.StoreMgr.get('Details').each(function(test){
console.log("for loop"+test.data);
});
contactDetail.setRecord(record1);
Ext.Viewport.animateActiveItem(contactDetail, this.slideLeftTransition);
},
// Base Class functions.
launch: function () {
this.callParent(arguments);
console.log("launch");
},
init: function () {
this.callParent(arguments);
console.log("init");
}
})
Please help to bind data to detail view.
So I'm guessing your Contacts Store is defined somewhere else but since this one is working you didn't paste the code here.
So one quick note on the model, where you should always define an idProperty. This is what Sencha use internally to define the "primary key" on your store and therefore work properly when you reload/refresh your store.
Ext.define('App.model.Details', {
extend: 'Ext.data.Model',
config: {
idProperty: 'Name', // Or something from your server maybe?
fields: [
{name: 'Name', type: 'string'},
{name: 'BillingStreet', type: 'string'},
{name: 'BillingCity', type: 'string'}
]
}
});
Secondly, why did you use the initialize method in your ListDetail view when you used the config method in your listView? if you specify the config instead, you will be able to to reuse some of this component in a more easy way somewhere else by doing something like
items: [
{
xtype: 'ListDetail',
anyOtherAttribute: value
}
]
But that's kinda out of scope here. But anyway. So what is wrong here I think is that you have defined a Store for each field of your panel. I'm sorry i can't test my hypothesis, but here is what I would do:
Ext.define("App.view.ListDetail", {
extend: "Ext.form.Panel",
requires: "Ext.form.FieldSet",
alias: "widget.listDetail",
config:{
scrollable:'vertical'
items:[
{
xtype: "toolbar",
docked: "top",
title: "Details"
},
{
xtype: "fieldset",
itemId: 'detailedListFiledset', //Overall, prefer itemId
items: [
{
xtype: 'textfield',
value : 'Name',
label: 'Name' // may be you want placeholders here?
},
{
xtype: 'emailfield',
value : 'BillingStreet',
label: 'Email' // and here..
},
{
xtype: 'passwordfield',
value : 'BillingCity',
label: 'Password' // and here..
}
]
}
]
}
});
Alright, and now the issue seems to be in your controller:
Add a ref to your fieldset
Add a reference to your store
create a afterload callback when your store is loaded (Details)
Either clear the store every time or append data and apply to filter to get the correct record (this is why the idProperty is very useful)
set the record of the fieldset and not the panel
I haven't had the chance to try that, but I'll do it later tonight. But git it a go though.
-- EDIT --
Ok I've finally been abe to code something for you.
A few issues were in your code. I don't really know why you need two stores, but let's say you do. I'm going to give you all the files I used (the two stores, the two models, the three views and the controller). Three main thing were wrong in your code:
you should not load the second store and try to get the record right after. use and 'load' or 'refresh' event for that
SetValues for a form is the correct function to use
You were missing the name property in your form so that the form know to which value of the store/model to bind to the field.
ContactModel:
Ext.define('App.model.Contact', {
extend: 'Ext.data.Model',
config: {
idProperty: 'id',
fields: [
{name: 'id', type: 'int'},
{name: 'name', type: 'string'}
]
}
});
ContactStore:
Ext.define('App.store.ContactStore', {
extend: 'Ext.data.Store',
requires:['App.model.Contact'],
config: {
storeId: 'ContactStore',
model: 'App.model.Contact',
autoLoad :true,
data: [
{id: 0, name: 'Foo'},
{id: 1, name: 'Bar'}
]
}
});
DetailModel:
Ext.define('App.model.Detail', {
extend: 'Ext.data.Model',
config: {
idProperty: 'id',
fields: [
{name: 'id', type: 'int'},
{name: 'name', type: 'string'},
{name: 'billingStreet', type: 'string'},
{name: 'billingCity', type: 'string'}
]
}
});
DetailStore:
Ext.define('App.store.DetailStore', {
extend: 'Ext.data.Store',
config: {
model: 'App.model.Detail',
autoLoad :true,
data: [
{id: 0, name: 'Foo', billingStreet:'here', billingCity: 'Somewhere'},
{id: 1, name: 'Bar', billingStreet:'there', billingCity: 'Somewhere else'}
]
}
});
ContactView:
Ext.define('App.view.ContactList', {
extend: 'Ext.List',
xtype: 'contactList',
fullscreen: true,
config: {
itemId: 'contactList',
store:'ContactStore',
emptyText: 'test',
itemTpl: new Ext.XTemplate(
'{name}'
),
items:[
{
xtype:'toolbar',
docked:'top',
title:'Leeds List'
}
]
}
});
DetailView:
Ext.define('App.view.Detail', {
extend: 'Ext.form.Panel',
requires: ['Ext.form.FieldSet'],
xtype: "detail",
config:{
scrollable:'vertical',
items: [
{
xtype: 'toolbar',
docked: 'top',
title: 'Details'
},
{
xtype: 'fieldset',
itemId: 'detailForm',
items: [{
xtype: 'textfield',
store: 'Details',
name: 'name',
placeHolder : 'Name',
label: 'Name'
},
{
xtype: 'textfield',
store: 'Details',
placeHolder : 'BillingStreet',
name: 'billingStreet',
label: 'BillingStreet'
},
{
xtype: 'textfield',
store: 'Details',
placeHolder : 'BillingCity',
name: 'billingCity',
label: 'BillingCity'
}
]
}
]
}
});
Main view:
Ext.define('App.view.Main', {
extend: 'Ext.Container',
xtype: 'main',
config: {
layout: 'hbox',
items: [
{
xtype: 'contactList',
flex:1
},
{
xtype: 'detail',
flex:2.5
}
]
}
});
Main Controller:
Ext.define('App.controller.Main', {
extend : 'Ext.app.Controller',
requires: [
'Ext.Toolbar',
'Ext.List',
'App.store.ContactStore',
'App.store.DetailStore',
'App.view.Detail',
'App.view.ContactList'
],
config: {
//#private
detailStore: null,
currentListIndex: -1,
views : [
'App.view.ContactList',
'App.view.Detail'
],
refs: {
list: 'contactList',
detail: 'detail',
detailForm: 'detail #detailForm'
},
control: {
list: {
itemtap: 'handleItemTapList'
}
}
},
launch: function() {
var store = Ext.getStore('DetailStore');
store.on('refresh', 'handleDetailStoreLoad', this);
this.setDetailStore(store);
},
handleItemTapList: function(list, index, target, record) {
this.setCurrentListIndex(index);
this.getDetailStore().load();
},
handleDetailStoreLoad: function (store) {
debugger;
var record = store.getAt(this.getCurrentListIndex());
this.getDetail().setValues(record.data);
}
});
We could argue on a few things but I tried to go straight to the point and make it work. If you have more questions please ask but this example is working for me. In my opinion, you might not need the second store, as the contact detail could be nested in the COntact store, and you could use the hasMany property of the store.
use form.setRecord() to load a record into a form
make sure your form elements have name property values that match the model name properties
as you have a store, you will have to get a reference to ONE model to load, using say getAt() or find() methods to get or find a model in your store

Sench Touch 2 - Rendering a List

I have a simple MVC Sencha Touch application, with 1 store, 2 models and 2 views - a toolbar and a list. My toolbar renders fine, but the list does not. No exception is thrown and I can't find what I'm doing wrong.
The store (Books.js):
Ext.define('App.store.Books', {
extend: 'Ext.data.Store',
model: 'App.model.Book',
autoLoad: true,
data: [
{ id: '1', name: '1984', publisher: 'Orwell' },
{ id: '2', name: 'Biography', publisher: 'abcde' },
{ id: '3', name: 'The Old Man and the Sea', publisher: 'Hemingway' }
]
});
The view (List.js - I have another Bar.js which renders fine):
Ext.define('App.view.List', {
extend: 'Ext.List',
store : 'Books',
xtype : 'mylist',
itemTpl: '<div><strong>Name: {name}</strong>Publisher: {publisher}</div>'
});
The viewport (Viewport.js) - extends Ext.Container as I saw in several examples:
Ext.define('App.view.Viewport', {
extend: 'Ext.Container',
requires : [
'App.view.Bar',
'App.view.List'
],
config: {
fullscreen: true,
layout: 'fit',
items: [
{
xtype : 'toolbar',
docked: 'top'
},
{
xtype: 'mylist'
}
]
}
});
As I wrote - my toolbar is shown, my list ('mylist') isn't.
What am I missing or doing wrong?
Thanks
Try adding a config to your view
Ext.define('App.view.List', {
extend: 'Ext.List',
config: {
title: 'Books',
cls: 'books',
store: 'Books',
itemTpl: '<div><strong>Name: {name}</strong>Publisher: {publisher}</div>'
}
});

Resources