Error adding MixedCollection component to extjs form - javascript

I am trying to dynamically build a extjs form and when I try to add the dynamically built MixedCollection object to the form I get a TypeError: e.mixins.elementCt is undefined error.
<div id="form-#pageSpecificVar" class="grid-container even"></div>
<script>
Ext.define('HeaderForm', {
extend: 'Ext.form.Panel',
initComponent: function () {
var me = this;
Ext.applyIf(me, {
id: Ext.id(),
defaultType: 'textfield',
items: [{
xtype: 'container',
items: [{
xtype: 'textfield',
fieldLabel: 'Test'
}]
}]
});
me.callParent(arguments);
}
});
// Define our data model
Ext.define('HeaderModel', {
extend: 'Ext.data.Model',
fields: [
{ name: 'FieldA', type: 'int' }
]
});
var store = Ext.create('Ext.data.Store', {
model: 'HeaderModel',
proxy: {
type: 'ajax',
actionMethods: { create: 'POST', read: 'GET', update: 'POST', destroy: 'POST' },
url: '#Url.Content("~/Test/Header")',
timeout: 1200000,
listeners: {
load: function () {
}
}
}
});
store.load({
scope: this,
callback: function (records, operation, success) {
var form = new HeaderForm();
var formItems = new Ext.util.MixedCollection();
Ext.each(records[0].fields.items, function (item) {
console.log(item);
formItems.add(new Ext.form.DisplayField({
fieldLabel: 'Test'
}));
}, this);
console.log(formItems);
form.add(formItems);
form.loadRecord(records[0].data);
form.render('form-#pageSpecificVar');
}
});
</script>
Another thing I don't understand is, when I put the function inside the load listener, nothing happens. So I had to resort to using the callback event.
Update:
form.add method takes a component or component array, so instead of adding MixedCollection type I refer to formItems.items to add the array of displayfields components.
But for some reason the store listeners load is not getting triggered when store.load is executed, does anyone see a problem with that?
Nevermind this... I figured out... I placed the listener instead of the proxy instead of the store.
Q2
Also something weird is that during the callback method of store.load, the records is not return with the loaded values.
Nevermind this... I figured out... It was the json object I'm passing. Forgot to take it out of the error/data structure for form.
Thanks

MixedCollection isn't an accepted parameter for add, you need to use an array. This info is in the docs.

Related

Extjs6 apply property from config via function

I used to write this in extjs4:
Ext.define('Superstore', {
extends: 'Ext.data.Store'
config : {
customer : null,
},
applyCustomer : function (value) {
this.customer = value;
},
model : 'Supermodel'
});
I tried the same in extjs6, but with no success:ยด
Ext.define('Supermodel', {
extend: 'Ext.data.Model',
requires: ['Ext.data.reader.Json', 'Ext.data.proxy.Rest'],
config: {
customer: null
},
fields: [
{name: 'id', type: 'string'},
...
],
proxy: {
type: 'rest',
url: '/customers/{customer}/users',
reader: {
type: 'json'
}
},
applyCustomer: function (value) {
this.customer = value;
this.proxy.url.replace('{customer}', value);
}
});
Did they remove the magic?
Or is there any other, better, way to build my url like in my code?
I've already seen a few solutions, but none of them fitted to my application.
I get the customerId via session which is sent by the backend after login. I would get the store via StoreManager, get the customer record and apply it to the proxy.
Thanks in advance.
If you don't need to manipulate the value use the update function instead:
updateCustomer: function(newValue){
this.proxy.url.replace('{customer}', newValue);
}
(And remove the applyCustomer function)

ExtJS 5: Accessing bound store in component

I'm having a real hard time understanding how to access the actual bound store instance on a component, like a ComboBox or Grid. It appears that when you use their getStore method, it returns a different instance.
In my example, I have a custom grid class, and in its initComponent, I want to add a load listener. Unfortunately, the load listener never gets hit, but the bound store's load listener does. You can see the listener is getting set up before the store is loaded, so that's not the issue. It looks like the store instance in initComponent is a memory store, so the bound store's instance is not synced to the component at this point.
I know I can have a load listener on the bound store, but this is a custom grid class, and for any custom grid class, I want there to be a listener set up... so I don't want to have to do this all over the place in my code... I just want it in one class, as they're all going to have the same logic carried out.
Can someone explain to me why my custom grid class's load listener is not getting hit, and what can I do to fix this? Can I somehow access the bound store instance?
Ext.application({
name: 'Fiddle',
launch: function() {
Ext.define('MyGrid', {
extend: 'Ext.grid.Panel',
xtype: 'myGrid',
initComponent: function() {
alert('initComponent')
this.callParent();
this.getStore().on('load', this.onLoad, this);
},
onLoad: function() {
alert('grid store loaded');
}
});
Ext.define('MyViewController', {
extend: 'Ext.app.ViewController',
alias: 'controller.myview',
onLoadBoundStore: function() {
alert('loaded bound');
}
})
Ext.define('MyViewModel', {
extend: 'Ext.app.ViewModel',
alias: 'viewmodel.myview',
stores: {
myStore: {
fields: ['name', 'value'],
autoLoad: true,
proxy: {
type: 'ajax',
url: 'data1.json',
reader: {
type: 'json'
}
},
listeners: {
load: 'onLoadBoundStore'
}
}
}
});
Ext.define('MyView', {
extend: 'Ext.form.Panel',
renderTo: Ext.getBody(),
controller: 'myview',
viewModel: {
type: 'myview'
},
items: [{
title: 'blah',
xtype: 'myGrid',
reference: 'myComboBox',
bind: {
store: '{myStore}'
},
columns: [{
text: 'Name',
dataIndex: 'name'
}, {
text: 'Value',
dataIndex: 'value'
}]
}]
});
Ext.create('MyView')
}
});
Can someone explain to me why my custom grid class's load listener is
not getting hit, and what can I do to fix this?
You are not initially providing any store to your grid (the store config option is required by the way). Hence the grid is creating its own, empty store as coded here:
store = me.store = Ext.data.StoreManager.lookup(me.store || 'ext-empty-store');
That empty store is the one that gets your onLoad listener attached. It is not getting hit because the store is never loaded.
Can I somehow access
the bound store instance?
Yes, use this:
this.lookupViewModel().getStore('myStore')
You can attach your listener to the bound store instead of the empty one and see the difference. The grid's empty store eventually gets replaced by the bound one (this is why you see data in the grid, after all), but this happens after initComponent is executed. You can track the moment of setting the bound store to the grid by overriding setStore method.
I know I can have a load listener on the bound store, but this is a
custom grid class, and for any custom grid class, I want there to be a
listener set up... so I don't want to have to do this all over the
place in my code... I just want it in one class, as they're all going
to have the same logic carried out.
Since you are using MVVC it is recommended to stick to the pattern and keep views declaring view aspects only. Listeners should be declared and handled in controllers (not even in viewmodels like in your example). Otherwise, if you continue sticking to pre Ext JS 5 style and put dynamic stuff in views (i.e. the grid in your case) there is no point in using MVVC.
This is so incredibly hacky that I don't even want to post it as an answer, but I'm going to just for posterity sake. Building on Drake's answer, I figured out how to get my store using what was passed in the initial config of my grid class. The bind comes in with the braces, so that's why I'm doing a replace on it. Like I said, this probably should never be used, but it's something.
initComponent: function() {
var store = this.lookupViewModel().getStore(this.config.bind.store.replace(/[{}]/g, ''));
store.on('load', this.onLoad, this);
this.callParent();
},
Just to add one more option to the mix, you can listen to the reconfigure event on the grid, as that's what fires after binding a store is complete... so something like this would work:
Ext.application({
name: 'Fiddle',
launch: function() {
Ext.define('MyGrid', {
extend: 'Ext.grid.Panel',
xtype: 'myGrid',
initComponent: function() {
alert('initComponent')
this.on('reconfigure', this.onReconfigureGrid, this);
this.callParent();
},
onReconfigureGrid: function(grid, store, columns, oldStore, oldColumns, eOpts) {
store.on('load', this.onLoad, this);
},
onLoad: function() {
alert('grid store loaded');
}
});
Ext.define('MyViewController', {
extend: 'Ext.app.ViewController',
alias: 'controller.myview',
onLoadBoundStore: function() {
alert('loaded bound');
}
})
Ext.define('MyViewModel', {
extend: 'Ext.app.ViewModel',
alias: 'viewmodel.myview',
stores: {
myStore: {
fields: ['name', 'value'],
autoLoad: true,
proxy: {
type: 'ajax',
url: 'data1.json',
reader: {
type: 'json'
}
},
listeners: {
load: 'onLoadBoundStore'
}
}
}
});
Ext.define('MyView', {
extend: 'Ext.form.Panel',
renderTo: Ext.getBody(),
controller: 'myview',
viewModel: {
type: 'myview'
},
items: [{
title: 'blah',
xtype: 'myGrid',
reference: 'myComboBox',
bind: {
store: '{myStore}'
},
columns: [{
text: 'Name',
dataIndex: 'name'
}, {
text: 'Value',
dataIndex: 'value'
}]
}]
});
Ext.create('MyView');
}
});

using extjs Store from Different JS file

this is CreateUI.js
Ext.onReady(function() {
Ext.QuickTips.init(); //tips box
Ext.define('RouteModel', {
extend: 'Ext.data.Model',
fields: [{name: '_id', type: 'number'}, 'Route_Code','Route_Name','Name','AddBy_ID']
});
Ext.override(Ext.data.Connection, {
timeout : 840000
});
var RouteNameStore = Ext.create('Ext.data.JsonStore', {
model: 'RouteModel',
autoLoad: true,
proxy: {
type: 'ajax',
url: 'get-routename.php',
api: {
create: 'insert-routename.php',
//read: 'http://visual04/ModuleGestion/php/Pays.php?action=read',
update: 'update-routename.php',
//destroy: 'http://visual04/ModuleGestion/php/Pays.php?action=destroy'
},
reader: {
type: 'json',
idProperty: '_id'
},
writer: {
type: 'json',
id: '_id'
}
}
});
})
routename.js
RouteNameStore.add ({
Route_Code: txtAddRouteCode,
Route_Name: txtAddRouteName,
AddBy_ID: getCookie('User_ID')
});
and this is the index.html page to link this two js file
<script type="text/javascript" src="CreateUI.js?"></script>
<script type="text/javascript" src="routename.js?"></script>
fire bug error
ReferenceError: RouteNameStore is not defined
RouteNameStore.add ({
I m trying to use the JSonStore on different JavaScript file, but failed.
how to fix this? thanks
You define RouteNameStore as local varible inside Ext.onReady handler function.
Because varible scope is inside function, it is not accessible from other functions.
If you want more informations about variable scopes in JavaScript you can look here: What is the scope of variables in JavaScript?
For accessing stores in ExtJS, you can add to your store configuration unique storeId and then get your store in other object by Ext.data.StoreManager
// create store
Ext.create('Ext.data.Store', {
...
storeId: 'myStore'
...
});
// get existing store instance
var store = Ext.data.StoreManager.lookup('myStore');

Sencha touch store - phantom data

I created a model like
Ext.define('MyApp.model.ContainerDetailsModel', {
extend: 'Ext.data.Model',
alias: 'model.ContainerDetailsModel',
config: {
fields: [
{
name: 'id',
allowNull: false,
type: 'string'
},
{
name: 'container_types_id',
type: 'string'
}
]
}
});
and a store like this
Ext.define('MyApp.store.ContainerDetailsStore', {
extend: 'Ext.data.Store',
requires: [
'MyApp.model.ContainerDetailsModel'
],
config: {
model: 'MyApp.model.ContainerDetailsModel',
storeId: 'ContainerDetailsStore',
proxy: {
type: 'ajax',
enablePagingParams: false,
url: 'hereIsServiceUrl',
reader: {
type: 'json'
}
}
}
});
Now somewhere in application I tried to get one record like:
var detailsStore = Ext.getStore("ContainerDetailsStore");
detailsStore.load();
var detailsRecord = detailsStore.last();
But it gaves me undefined. The json returned by service is ok, it use it in different place as source for list. I already tried to change allowNull to true, but there is no null id in source. I tried set types to 'int' with the same result.
So I have tried
console.log(detailsStore);
Result is like this (just important values):
Class {
...
loaded: true,
data: Class {
...
all: Array[1] {
length: 1,
0: Class {
container_types_id: "1",
id: "726",
....
}
...
}
...
},
...
}
In the same place
console.log(detailsStore.data);
returns (as it should):
Class {
...
all: Array[1] {
length: 1,
0: Class {
container_types_id: "1",
id: "726",
....
}
...
}
but (next line)
console.log(detailsStore.data.all);
returns
[]
And it's empty array. When i try any methods from the store it says the store is empty.
I wrote console.log() lines one after another - so for sure it doesn't change between them (I try it also in different order or combinations).
My browser is Google Chrome 23.0.1271.97 m
I use Sencha from https://extjs.cachefly.net/touch/sencha-touch-2.0.1.1/sencha-touch-all-debug.js
How can I take a record from that store?
store.load() Loads data into the Store via the configured proxy. This uses the Proxy to make an asynchronous call to whatever storage backend the Proxy uses, automatically adding the retrieved instances into the Store and calling an optional callback if required. The method, however, returns before the datais fetched. Hence the callback function, to execute logic which manipulates the new data in the store.
Try,
detailsStore.load({
callback: function(records, operation, success) {
var detailsRecord = detailsStore.last();
},
scope: this
});

How to get data from extjs 4 store

Im stack with ext js 4 at the very beginning. Im trying to get the current user data when starting the application using store. But Im not getting any data from the store, even the store.count return 0.
I found many description how to create store, but not how to access the data in it. I managed to get the data using Ext ajax request, but i think would be better using store and i cant avoid them..
My model:
Ext.define('MyApp.model.User', {
extend: 'Ext.data.Model',
fields: [
'id',
'username',
'email'
]
});
My store looks like:
Ext.define('MyApp.store.User.CurrentUser', {
extend: 'Ext.data.Store',
requires: 'MyApp.model.User',
model: 'MyApp.model.User',
autoLoad: true,
proxy: {
type: 'ajax',
method: 'POST',
url: Routing.generate('admin_profile'),
reader: {
type: 'json',
root: 'user'
}
}
});
The returned json:
{
"success":true,
"user":[{
"id":1,
"username":"r00t",
"email":"root#root.root"
}]
}
And the application:
Ext.application({
name: 'MyApp',
appFolder: '/bundles/myadmin/js/app',
models: ['MyApp.model.User'],
stores: ['MyApp.store.User.CurrentUser'],
//autoCreateViewport: true,
launch: function() {
var currentUser=Ext.create('MyApp.store.User.CurrentUser',{});
/*
Ext.Ajax.request({
url : Routing.generate('admin_profile'),
method: 'POST',
success: function(resp) {
var options = Ext.decode(resp.responseText).user;
Ext.each(options, function(op) {
var user = Ext.create('MyApp.model.User',{id: op.id,username:op.username,email:op.email});
setUser(user);
}
)}
});
*/
currentUser.load();
alert(currentUser.count());
}
});
The problem itself isn't that the store does not contain data, the problem is that the store load is asyncronous therefore when you count the store records, the store is actualy empty.
To 'fix' this, use the callback method of the store load.
currentUser.load({
scope : this,
callback: function(records, operation, success) {
//here the store has been loaded so you can use what functions you like
currentUser.count();
}
});
All the sencha examples have the proxies in the store, but you should actually put the proxy in the model, so that you can use the model.load method. the store inherits the model's proxy, and it all works as expected.
it looks like model.load hardcodes the id though (instead of using idProperty), and it always has to be an int, as far as I can tell.
good luck!

Categories

Resources