I'm trying to implement a web-based Desktop application for administration purpose of my website. When I tried to rewrite the BogusMenuModule and BogusModule which are examples of ExtJS, I was unable to get deeper nodes of JSON by using myDataStore.load({callback:function(){...}}) inside of Ext.define('MyDesktop.BasicWindowModule', {...}) . I'm only able to get the first layer's ID.
If myDataStore(...) is outside of Ext.define(...) it works, but the problem is that it's unable to set parameters to 'win' which is an inside variable of Ext.define(...) .
Why I'd like to modify them is that I wanna implement a base-class module in order to pass taskbar ID to it and create a new taskbar instead of creating a new js file for my taskbar every time.
What I mean by deeper nodes is that if there's only one layer in JSON, it worked fine. But it doesn't work if the JSON looks like:
{
"BasicWindows": [
{
"id": 0,
"window": {
"id": 0,
"name": "ControlPanel",
"hasButton": false,
"configs": [
{
"id": 0,
"title": "ControlPanel",
"width": 640,
"height": 480
}
]
}
},
{
"id": 1,
"window": {
"id": 1,
"name": "Customers",
"hasButton": true,
"configs": [
{
"id": 1,
"title": "Customers",
"width": 400,
"height": 300,
"button": [
{
"text": "Submit"
},
{
"text": "Cancel"
}
]
}
]
}
},
{
"id": 2,
"window": {
"id": 2,
"name": "Reports",
"hasButton": false,
"configs": [
{
"id": 2,
"title": "Reports",
"width": 600,
"height": 400
}
]
}
}
]
}
And my modified BogusModule looks like:
Ext.require([
'Ext.data.*',
'Ext.form.*',
'Ext.window.Window'
]);
Ext.define('BasicWindow',{
extend: 'Ext.data.Model',
fields: [
{name: 'id', type:'int'}
],
hasMany : {model : 'myWindow', name : 'window'}
});
Ext.define('myWindow',{
extend: 'Ext.data.Model',
fields: [
{name: 'id', type:'int'},
{name: 'name', type: 'string'},
{name: 'hasButton', type: 'boolean'}
],
hasMany : {model : 'myConfigs', name : 'configs'},
belongsTo: 'BasicWindow'
});
Ext.define('myConfigs', {
extend: 'Ext.data.Model',
fields: [
{name: 'id', type:'int'},
{name: 'title', type: 'string'},
{name: 'width', type: 'int'},
{name: 'height', type: 'int'}
],
hasMany : {model : 'myButton', name : 'button'},
belongsTo: 'myWindow'
});
Ext.define('myButton',{
extend: 'Ext.data.Model',
fields: [
{name: 'text', type:'string'}
],
belongsTo: 'myConfigs'
});
var myDataStore = Ext.create('Ext.data.Store', {
model: 'BasicWindow',
proxy: {
type: 'ajax',
url : 'js/extjs/src/desktop/json/BasicWinConfig.json',
reader:{
type:'json',
root: 'BasicWindows'
}
}
});
var windowIndex = 0;
//function GetWindowName
Ext.define('MyDesktop.BasicWindowModule', {
extend: 'Ext.ux.desktop.Module',
init : function(){
this.launcher = {
//text: 'Auto Search',
iconCls:'bogus',
handler : this.createWindow,
scope: this,
windowId:windowIndex
};
},
createWindow : function(src){
var desktop = this.app.getDesktop();
var win = desktop.getWindow('BasicWindow');
var form = new Ext.form.Panel({
border: false,
fieldDefaults: {
labelWidth: 60
}
});
if(!win){
win = desktop.createWindow({
autoShow: true,
id: 'BasicWindow',
//title: 'Auto Search',
//width: 240,
//height:200,
//minWidth: 240,
//minHeight: 200,
layout: 'fit',
plain: true,
items: form
});
myDataStore.load({callback:function(){
alert('This is inside load callback');
myDataStore.each(function(rec) {
var window = rec.get('window');
alert(window.getId());
rec.each(function(conf){
alert(conf.getId());
win.add({
title: config.get('title'),
width: config.get('width'),
height: config.get('height')
});
});
});
}});
}
win.show();
return win;
}
});
Any comment or answer would be appreciated.
I figured it out! Add the line outside of Ext.define
var me = this;
and then
me.myDataStore.load(...);
Another question comes out. How can I load myDataStore if I move Models and DataStore definition to another .js file?
Any suggestion?
Ext.data.StoreManager.lookup('myDataStore');
This function didn't work for ExtJS4 in my case.
Related
I have a data model that I want to be able to add a generic amount of filters to. I am specifying a name and a value. How can I add these hasMany associated fields as filters to my grid? I have attempted to write custom filtering option, but I can't have filters show up without an attached dataIndex, which is not available for the hasMany association.
Ext.define('AirGon.model.Project', {
extend: 'Ext.data.Model',
fields: [
{ name: 'Link', type: 'string' },
{ name: 'Title', type: 'string' },
{ name: 'Description', type: 'string' },
{ name: 'MappedMetadata', mapping: 'Metadata'},
{ name: 'XMax', type: 'float' },
{ name: 'XMin', type: 'float' },
{ name: 'YMax', type: 'float' },
{ name: 'YMin', type: 'float' }
],
hasMany: { model: 'Metadata', name: 'Metadata', associationKey: 'Metadata' }
});
Ext.define('Metadata', {
extend: 'Ext.data.Model',
fields: ['Name', 'Value']
});
This is my custom filtering attempt. I am getting the DataStore from the main store and then adding custom rendering, but I can't filter or sort this column because of the lack of a dataIndex.
var column = {
header: 'Meta',
//?????????dataIndex: 'MappedMetadata[0]',?????
sortable: true,
filterable: true,
filter: {
type: 'string'
},
renderer: function (value, meta, record) {
console.log(record.MetadataStore.data.items[index].data)
return record.MetadataStore.data.items[index].data.Value;
}
}
Data. The data is modeled so that a variable amount of metadata can be entered and the 'tag' will not be known by the system.
{
"Link": "link.com",
"Title": "project",
"Description": "descript",
"State": "",
"Metadata": [
{
"Name": "County",
"Value": "32"
},
{
"Name": "Info",
"Value": "info"
},
{
"Name": "State",
"Value": "TN"
}
],
"XMin": "-1",
"XMax": "-1",
"YMin": "1",
"YMax": "1"
}
I was able to solve this by dynamically flattening the data model and adding columns once the store has been loaded. Although this breaks the MVC structure this was the best solution I came up with so it might be able to help you.
var defaultColumns = [];
var store = Ext.getStore('store');
store.on('load', function (store) {
var model = store.model;
var fields = model.getFields();
store.getAt(0).MetadataStore.data.items.forEach(function (item, index) {
var header = item.data.Name;
//isField returns a boolean if the field is already part of the data model
if (!isField(fields, header)) {
//Add a new metadata field to the data model
var field = { name: header, mapping: 'Metadata[' + index + '].Value' }
fields.push(field)
//Add a new metadata column
var column = {
header: header,
dataIndex: header,
sortable: true,
filterable: true,
filter: {
type: 'list'
},
flex: 0.2
}
defaultColumns.push(column);
}
});
model.setFields(fields);
//reload the grid after adding columns
var gridView = Ext.ComponentQuery.query('gridpanel')[0];
gridView.reconfigure(store, defaultColumns);
});
//reload the data after creating new fields
store.load();
I then set the columns of the grid to defaultColumns.
{
xtype: 'grid',
store: 'Projects',
overflowX: 'auto',
autoScroll: true,
features: [filters],
columns: defaultColumns
}
i want to build a framework that dynamic. first, add "loanname" to be my title in tab to add to a tabpanel. second, dynamic add my product which the loanname measure the tab title's loanname.
the loanname in json be the title which i want to be the title on everytab:
{
"listjson" : [
{"loanname" : "xixi22" , "loandesc" : "use to architecture"},
{"loanname" : "xixi2" , "loandesc" : "use to education"},
{"loanname" : "xixi3" , "loandesc" : "use to plane and others"}
]
}
and the product which i want put it in list(a list contain the same loanname product), then put the list into the match tab:
{
"products" :[
{"loanname": "xixi22", "loannum": "A-0000001", "interests": "6.5", "timeline": "1 year"},
{"loanname": "xixi22", "loannum": "A-0000002", "interests": "7", "timeline": "2 year"},
{"loanname": "xixi2", "loannum": "B-0000001", "interests": "9", "timeline": "3 year"},
{"loanname": "xixi3", "loannum": "C-0000001", "interests": "11.5", "timeline": "4 year"}
]
}
the result view i want is similiar like under:
but i have encounter a problem the list contain the other product which not match the loanname in title and display for null
-------------edit part---------
my part code in view:
{
xtype: 'tabpanel',
itemId: 'tabfirst',
flex: 1,
//activeItem: 1,
tabBar: {
layout: {
pack: 'center'
}
},
defaultType: 'tablist'
}
the list view:
Ext.define('ylp2p.view.tablist',{
extend: 'Ext.dataview.List',
xtype: 'tablist',
config: {
title: '',
store: 'productstore',
itemTpl: '{loanname}'
}
});
my code in controller:
Ext.define('ylp2p.controller.addtab',{
extend: 'Ext.app.Controller',
config: {
refs: {
myTabPanel: '.makemoney #tabfirst',
},
controller: {
myTabPanel: {
activate: 'OnActivateTabPanel',
activateitemchange: 'OnActivateItemChangeTabPanel'
}
}
},
launch: function(){
var products = Ext.getStore('productstore');
products.filterBy(function(record, id){
return record.get('loanname') === 'xixi22';
});
},
OnActiveTabPanel: function(newActiveItem, viewport, oldActiveItem, eOpts){
var tabs = Ext.getStore('loanliststore');
tabs.each(function(record){
newActiveItem.add({
title: record.get('loanname')
});
});
},
OnActiveItemChangeTabPanel: function(cmp, value, oldValue, eOpts){
var products = value.getStore();
products.clearFilter(true);
products.filterBy(function(record, id) {
return record.get('loanname') === value.getTitle();
});
}
});
my store:1.tab store loanlist.js,2.product store prostore.js
Ext.define('ylp2p.store.loanlist',{
extend: 'Ext.data.Store',
config:{
model: 'ylp2p.model.list',
storeId: 'loanliststore',
autoload: true,
proxy: {
type: 'ajax',
url: 'resources/json/loanlist.json',
reader:{
type: 'json',
rootProperty: 'listjson'
}
}
}
});
and
Ext.define('ylp2p.store.prostore',{
extend: 'Ext.data.Store',
config: {
model: 'ylp2p.model.loanproduct',
storeId: 'productstore',
autoload: true,
proxy: {
type: 'ajax',
url: 'resources/json/product.json',
reader: {
type: 'json',
rootProperty: 'products'
}
}
}
});
app.js:
Ext.application({
name: 'ylp2p',
requires: [
'Ext.MessageBox'
],
views: [
'ylp2p.view.Main',
'ylp2p.view.makemoney',
'ylp2p.view.tablist'
],
stores: [
'ylp2p.store.datainterests',
'ylp2p.store.loanlist',
'ylp2p.store.picstore',
'ylp2p.store.prostore'
],
models: [
'ylp2p.model.data',
'ylp2p.model.list',
'ylp2p.model.picmodel',
'ylp2p.model.loanproduct'
],
controllers: [
'ylp2p.controller.viewdata',
'ylp2p.controller.viewlist',
'ylp2p.controller.loadpic',
'ylp2p.controller.addtab'
],
icon: {
'57': 'resources/icons/Icon.png',
'72': 'resources/icons/Icon~ipad.png',
'114': 'resources/icons/Icon#2x.png',
'144': 'resources/icons/Icon~ipad#2x.png'
},
isIconPrecomposed: true,
startupImage: {
'320x460': 'resources/startup/320x460.jpg',
'640x920': 'resources/startup/640x920.png',
'768x1004': 'resources/startup/768x1004.png',
'748x1024': 'resources/startup/748x1024.png',
'1536x2008': 'resources/startup/1536x2008.png',
'1496x2048': 'resources/startup/1496x2048.png'
},
launch: function() {
// Destroy the #appLoadingIndicator element
Ext.fly('appLoadingIndicator').destroy();
// Initialize the main view
Ext.Viewport.add(Ext.create('ylp2p.view.Main'));
Ext.getStore('interestsdata').load();
Ext.getStore('loanliststore').load();
Ext.getStore('imagestore').load();
Ext.getStore('productstore').load();
console.log('start Big weapon!!here is app.js launch function');
onUpdated: function() {
Ext.Msg.confirm(
"Application Update",
"This application has just successfully been updated to the latest version. Reload now?",
function(buttonId) {
if (buttonId === 'yes') {
window.location.reload();
}
}
);
}
});
In the activeitemchange listener you can filter the store based on the title of the tab (activeitem). I quickly created a fiddle for you to show you how I would do it:
https://fiddle.sencha.com/#fiddle/u50
var tabs = Ext.create('Ext.data.Store', {
fields: ['loanname', 'loandesc'],
data: [
{"loanname" : "xixi22" , "loandesc" : "use to architecture"},
{"loanname" : "xixi2" , "loandesc" : "use to education"},
{"loanname" : "xixi3" , "loandesc" : "use to plane and others"}
]
})
var products = Ext.create('Ext.data.Store', {
fields: ['loanname','loannum','interests','timeline'],
data: [
{"loanname": "xixi22", "loannum": "A-0000001", "interests": "6.5", "timeline": "1 year"},
{"loanname": "xixi22", "loannum": "A-0000002", "interests": "7", "timeline": "2 year"},
{"loanname": "xixi2", "loannum": "B-0000001", "interests": "9", "timeline": "3 year"},
{"loanname": "xixi3", "loannum": "C-0000001", "interests": "11.5", "timeline": "4 year"}
]
});
Ext.define('Fiddle.view.MyList', {
extend: 'Ext.dataview.List',
xtype: 'mylist',
config: {
title: '', // We have to config a title to let the framework generate getters and setters
store: products,
itemTpl: '{loannum}'
}
});
Ext.application({
name : 'Fiddle',
launch : function() {
var tabPanel = Ext.create('Ext.TabPanel', {
fullscreen: true,
defaultType: 'mylist',
items: [],
listeners: {
activate: function( newActiveItem, viewport, oldActiveItem, eOpts) {
products.filterBy(function(record, id) {
return record.get('loanname') === 'xixi22';
});
},
activeitemchange: function( cmp, value, oldValue, eOpts ) {
products.clearFilter(true);
products.filterBy(function(record, id) {
return record.get('loanname') === value.getTitle();
});
}
}
});
tabs.each(function(record){
tabPanel.add({
title: record.get('loanname'),
iconCls: 'home',
});
});
}
});
Use this code. It will work.
var items = [];
var store = Ext.getStore('YourStore'); // write your store here
var loanname = record.get('loanname');
store.each(function (r) {
if (r.get('loanname') == loanname) {
items.push(r.data);
}
});
var myPanel = Ext.create('Ext.List', {
title: 'loanname',
data: items,
itemTpl: '{loannum}'
});
moneytab.add(myPanel);
Below code works fine with the data as in ReadOrder.json (below), however how to read the associated object when it is nested inside another object as in ReadOrderNested.json(below, within 'collection').
Question is more specifically can we use a mapping property or proxy's reader config with rootProperty (tried this approach with no luck)
Sencha fiddle : https://fiddle.sencha.com/#fiddle/9fb
Extjs version : 5.0.0
//Base Model
Ext.define('MyApp.model.Base', {
extend: 'Ext.data.Model',
fields: [{
name: 'id',
type: 'int'
}],
schema: {
namespace: 'MyApp.model'
}
});
//Order Model
Ext.define('MyApp.model.Order', {
extend: 'MyApp.model.Base',
fields: [{
name: 'customer',
type: 'string'
}, {
name: 'paymentStatus',
type: 'string'
}]
});
//PaymentDetail Model
Ext.define('MyApp.model.PaymentDetail', {
extend: 'MyApp.model.Base',
fields: [{
name: 'orderId',
reference: 'Order'
}, {
name: 'cardNumber',
type: 'string'
}, {
name: 'status',
type: 'string'
}]
});
Ext.define('MyApp.store.OrderStore', {
extend: 'Ext.data.Store',
model: 'MyApp.model.Order',
proxy: {
type: "rest",
url: 'Order.json',
appendId: false,
api: {
create: undefined,
read: 'ReadOrder.json',
update: 'UpdateOrder.json',
destroy: undefined
},
reader: {
type: 'json',
rootProperty: 'order'
},
writer: {
writeAllFields: true,
allDataOptions: {
persist: true,
associated: true
}
}
},
});
Ext.application({
name: 'MyApp',
launch: function() {
var orderStore = Ext.create('MyApp.store.OrderStore');
orderStore.load({
callback: function(records) {
var order = this.first();
debugger;
var paymentDetailList = order.paymentDetails();
paymentDetailList.each(function(paymentDetail) {
//Print initial values of payment detail
console.log(paymentDetail.get('cardNumber'));
console.log(paymentDetail.get('status'));
})
}
});
}
});
Data : ReadOrder.json
{ "success": true,
"order": [{
"id": 1,
"customer": "Philip J. Fry",
"paymentStatus": "AWAIT_AUTH",
"paymentDetails": [{
orderId : 1,
"cardNumber": "4111111111",
"status": 'CREATED'
}, {
orderId : 1,
"cardNumber": "4222222222",
"status": "CREATED"
}]
}]
}
How to read with this data when the associated object is nested inside 'collection', ReadOrderNested.json:
{ "success": true,
"order": [{
"id": 1,
"customer": "Philip J. Fry",
"paymentStatus": "AWAIT_AUTH",
"paymentDetails": {
"collection" : [{
orderId : 1,
"cardNumber": "4111111111",
"status": 'CREATED'
}, {
orderId : 1,
"cardNumber": "4222222222",
"status": "CREATED"
}]}
}]
}
I am using ExtJS 4, dunno whether there is a difference. I am using a model with fields like this:
fields: [{
name: 'id',
type: 'int'
},{
name: 'paymentDetails'
}],
and when loading one model into a form
form.load(record);
Ext.getStore("paymentDetailsStore").removeAll();
Ext.getStore("paymentDetailsStore").loadRawData(record.get("paymentDetails"));
with paymentDetailsStore bound to a grid which is in the same window as the form.
I have a problem with loading data from store. Please tell me what I do wrong. I am using ExtJS 4.1.
Request sends properly, i haven't troubles like file not found or something like that. It also works if I had few stores, and any of this stores loading one 'data type' to his model, for example urls1. But if I have one store and one big model, data don't display.
I have a JSON like this:
{
"root": {
"tName": "name",
"urls1": [{
"url": "http:// ..... :09'"
}, {
"url": "http:// ..... :10'"
}],
"perS": "",
"perD": "",
"urls2": [{
"url": "http:// ..... :0009'"
}, {
"url": "http:// ..... :0010'"
}],
"val2": "",
"list2": [{
"level": "lvl1"
}, {
"level": "lvl2"
}],
"types": [{
"type": "type2"
}, {
"type": "type4"
}],
"accs": [{
"login": "login",
"pass": "p1",
"port": "8858",
"conType": "type3",
}, {
"login": "login3",
"pass": "p13",
"port": "88583",
"conType": "type2",
}]
}
}
My Model:
Ext.define('ACT.model.myModel', {
extend: 'Ext.data.Model',
fields: [
{name: 'tname'},
{name: 'urls1'},
{name: 'psec'},
{name: 'pday'},
{name: 'urls2'},
{name: 'list2'},
{name: 'types'},
{name: 'accs'},
]
});
My Store:
Ext.define('ACT.store.dataStore', {
extend: 'Ext.data.Store',
storeId:'mStore',
model: 'ACT.model.myModel',
autoLoad: true,
proxy: {
type: 'ajax',
url: 'resources/data/configuration/MyConfig.json',
reader: {
type: 'json',
root: 'root',
successProperty: 'success'
}
}
});
and my initComponent function in view:
initComponent: function() {
var me = this;
this.columns = [
{
xtype: 'checkcolumn',
text: ' ',
width: 100,
sortable: false,
hideable: false,
allowBlank: false
},
{
text: 'URL',
width: '85%',
dataIndex: 'urls1',
sortable: true,
hideable: false
}]
this.callParent(arguments);
}
});
The above should load urls1 into the store correctly, however, the data type is array. So the data is in the store but it is only not displayed in the grid as dataIndex points to that array.
You can create another model for urls and associate it with the master model.
I just cannot seem to get the tree grid up and running.
I have defined the model, the store and the treegrid (as seen below).
The tree grid shows inside target, the data is loaded async (checked with fiddler, two rows came back) however the treegrid just shows two rows with empty cells.
I tried debugging and the store's root node indeed has two child nodes, the model data is under child's raw property (except some fields such as leaf and iconCls which are also in data property), yet the tree grid shows two empty rows, despite dataIndex pointing to a proper model field.
It's like tree grid cannot find the field defined by the model?!?
Here's the source (I am using sandbox because I am integrating this into salesforce vforce, the salesforce merge fields {!} are also valid and render properly)
Ext4.onReady(function() {
var target = '{!$Component.childBlock.childTreeDiv}';
Ext4.define('ConfigurationItem', {
extend: 'Ext4.data.Model',
fields: [
{
id: 'id',
type: 'string'},
{
id: 'name',
type: 'string'},
{
id: 'recordType',
type: 'string'},
{
id: 'ciName',
type: 'string'},
{
id: 'alias',
type: 'string'},
{
id: 'model',
type: 'string'},
{
id: 'status',
type: 'string'},
{
id: 'description',
type: 'string'},
{
id: 'leaf',
type: 'bool'},
{
id: 'iconCls',
type: 'string'}
]
});
var store = Ext4.create('Ext4.data.TreeStore', {
model: 'ConfigurationItem',
root: {
nodetype: 'async',
id: '{!CI__c.Id}',
expanded: true
},
proxy: {
type: 'ajax',
url: 'json_CIChildren',
reader: {
type: 'json',
root: 'children'
}
}
});
tree = Ext4.create('Ext4.tree.Panel', {
width: document.getElementById(target).offsetWidth,
autoHeight: true,
title: 'Child Configuration Items',
collapsible: true,
titleCollapse: true,
renderTo: target,
rootVisible: false,
store: store,
multiSelect: true,
singleExpand: true,
columns: [
{
type: 'treecolumn',
text: 'CI#',
dataIndex: 'name'},
{
text: 'Type',
dataIndex: 'recordType'}
]
});
});
The request to json_CIChildren?_dc=1329830854458&node=a0NT0000006tYKzMAM was valid (the parentID in root.id got propagated ok) and came back with valid json:
{ "children" : [
{
"id": "a0NT0000006tswhMAA",
"name": "CI334593834",
"recordType": "Rack",
"ciName": "Empty rack",
"alias": "",
"model": "",
"status": "",
"description": "",
"leaf": "true",
"iconCls": "x4-ciicon-Rack"
},
{
"id": "a0NT0000006tYKuMAM",
"name": "CI2345234",
"recordType": "Service",
"ciName": "Business Connect - Premium",
"alias": "",
"model": "",
"status": "",
"description": "",
"leaf": "true",
"iconCls": "x4-ciicon-Service"
}
]}
What am I doing wrong? Why isn't the treegrid seeing name and recordType fields?
Is this because store only saw NodeInterface-like fields and there is none of my custom data in data property?
I think the problem is your model fields aren't mapped right. The "id" property for each field should be the 'name' property instead.