I want to clean up my code for better readability and put some code in extra js-files but nothing I've tried has worked.
It's a SubApp and part of a larger Project (Shopware) that is still using ExtJs 4.1.
I have a "main/window.js" that extends 'Ext.window.Window'.
initComponent looks like this:
initComponent: function () {
//...
me.dockedItems = [
me.createTopToolbar(),
];
//...
}
createTopToolbar is a Method inside "main/window.js" that return a Ext.toolbar.Toolbar with some elements.
My goal is to put this method in an extra file.
I tried to create a new static/singleton class like this
Ext.define('myapp.myplugin.view.main.Toptoolbar', {
singleton: true,
createTopToolbar: function(){
// ...
return toolbar;
}
But inside "main/window.js" i cannot call it using myapp.myplugin.view.main.Toptoolbar.createTopToolbar(), or main.Toptoolbar.createTopToolbar()
In app.js i tried to include it like this
views: [
'main.Window',
'main.Toptoolbar',
],
but it doesnt work.
I have no experience with ExtJs and search for hours...hope someone can help me.
Thank you
Edit
To answer the question why i'm building the toolbar within a function.
The whole functions looks like this:
createTopToolbar: function () {
var me = this;
var shopStore = Ext.create('Shopware.apps.Base.store.Shop');
shopStore.filters.clear();
shopStore.load({
callback: function(records) {
shopCombo.setValue(records[0].get('id'));
}
});
var shopCombo = Ext.create('Ext.form.field.ComboBox', {
name: 'shop-combo',
fieldLabel: 'Shop',
store: shopStore,
labelAlign: 'right',
labelStyle: 'margin-top: 2px',
queryMode: 'local',
valueField: 'id',
editable: false,
displayField: 'name',
listeners: {
'select': function() {
if (this.store.getAt('0')) {
me.fireEvent('changeShop');
}
}
}
});
var toolbar = Ext.create('Ext.toolbar.Toolbar', {
dock: 'top',
ui: 'shopware-ui',
items: [
'->',
shopCombo
]
});
return toolbar;
}
And i dont want the whole code inside my "main/window.js".
I'm not sure using the xtype solution provided by Jaimee in this context because i dont realy extend 'Ext.toolbar.Toolbar'. I just need a "wrapper" for my "shopCombo" code and return 'Ext.toolbar.Toolbar' with shopCombo as an item.
Create the toolbar as you would any other view, and create an 'xtype' to add it to your window.
Ext.define('myapp.myplugin.view.main.Toptoolbar', {
extends: 'Ext.toolbar.Toolbar',
xtype: 'mytoptoolbar',
dock: 'top',
ui: 'shopware-ui',
items :[
'->',
{
xtype: 'combobox',
name: 'shop-combo',
fieldLabel: 'Shop',
store: 'shopStore',
labelAlign: 'right',
labelStyle: 'margin-top: 2px',
queryMode: 'local',
valueField: 'id',
editable: false,
displayField: 'name',
listeners: {
'select': function() {
if (this.store.getAt('0')) {
me.fireEvent('changeShop');
}
}
}
}]
});
And then simply add it to your window's docked items like you would any other component:
initComponent: function () {
//...
me.dockedItems = [
{
xtype: 'mytoptoolbar'
}
];
//...
}
And the load listener can be added to the store.
Ext.define('Shopware.apps.Base.store.Shop', {
// ....
listeners:
{
load: function() {
Ext.ComponentQuery.query("combobox[name='shop-combo']")[0].setValue(...)
}
}
However, I'd suggest just setting a starting value for the combobox if it's a predictable value. You'll need to add the store to your controller's stores config if you haven't already.
You could use a factory pattern like so:
Ext.define('ToolbarFactory', {
alias : 'main.ToolbarFactory',
statics : {
/**
* create the toolbar factory
*/
factory : function() {
console.log('create the toolbar');
var toolbar = ....;
return toolbar;
}
}
});
Then you can create the Toolbar this way:
initComponent: function () {
//...
me.dockedItems = [
ToolbarFactory.factory();
];
//...
}
Depending on your build process you may need to add a requires statement.
Related
Here's a description of my Fiddle
I have defined a Window and a Form Panel
I have created instances of the Window and the Form panel defined above
Added the Form panel to the Window
Called the .show() on the Window to show the window (which
now also includes the form)
The form Panel declaration includes the buttons. But now the buttons do not show up.
Ext.application({
name: 'My Window',
launch: function () {
Ext.define('MyWindow', {
extend: 'Ext.window.Window',
title: 'My Window'//,
// renderTo: Ext.getBody()
});
Ext.define('MyForm', {
extend: 'Ext.form.Panel',
bodyPadding: 5,
width: 350,
// The form will submit an AJAX request to this URL when submitted
url: '',
// Fields will be arranged vertically, stretched to full width
layout: 'anchor',
defaults: {
anchor: '100%'
},
// The fields
defaultType: 'textfield',
items: [{
fieldLabel: 'First Name',
name: 'first',
allowBlank: false
}, {
fieldLabel: 'Last Name',
name: 'last',
allowBlank: false
}],
// Reset and Submit buttons
buttons: [{
text: 'Reset',
handler: function () {
this.up('form').getForm().reset();
}
}, {
text: 'Submit',
formBind: true, //only enabled once the form is valid
disabled: true,
handler: function () {
var form = this.up('form').getForm();
if (form.isValid()) {
form.submit({
success: function (form, action) {
Ext.Msg.alert('Success', action.result.msg);
},
failure: function (form, action) {
Ext.Msg.alert('Failed', action.result.msg);
}
});
}
}
}]
});
var myWindow = new MyWindow();
var myForm = new MyForm();
myWindow.items.add(myForm);
myWindow.show();
// var myForm = new MyForm();
}
});
Here's the fiddle
This must be related to some documented behavior of the Form or the Window. What could that be?
Also, architecturally, I would like to define these components separately and use them as needed. So is there a design pattern that is better than this?
Any component that is going to contain other components will generally need to have a layout specified. Add layout: 'fit' to your MyWindow config and it should work.
Google ExtJS MVC for guidelines on the recommended way to design ExtJS applications. I also find that the ExtJS 6 examples page can be quite useful. The KitchenSink one is nice because it contains a ton of different examples of small applications built using the MVC design pattern. (Pick an example from that link and then expand the Details pane on the right.)
I am trying to get this to work in Sencha Fiddle. The problem I am facing is that I get an error on this line
MyApp.app.getView('MyApp.view.test2').test();
When you click inside the textbox, it fails with an error (in console log) Uncaught TypeError: MyApp.app.getView(...).test is not a function
//Controller
Ext.define('MyApp.controller.test', {
extend: 'Ext.app.ViewController',
alias: 'controller.test',
myVar:0,
init: function() {
}
});
//View
Ext.define('MyApp.view.test', {
extend: 'Ext.form.field.Text',
alias:'widget.test',
controller: 'test',
title: 'Hello',
listeners: {
focus: function(comp){
MyApp.app.getView('MyApp.view.test2').test(); //Fails with an error that test is not a function }
},
renderTo: Ext.getBody()
});
//View
Ext.define('MyApp.view.test2', {
extend: 'Ext.form.Panel',
alias:'widget.test2',
title: 'Hello2',
renderTo: Ext.getBody(),
test:function()
{
alert('in MyApp.view.test2');
}
});
Ext.application({
name: 'MyApp',
launch: function() {
Ext.create('MyApp.view.test');
Ext.create('MyApp.view.test2');
}
});
The getView() function just returns the class and not the instance of the view. See ExtJs 5.1.1 Controller.getView() :
Returns a View class with the given name. To create an instance of the view, you can use it like it's used by Application to create the Viewport:
this.getView('Viewport').create();
To get the created view instance you can archive it with a Ext.ComponentQuery.
//query returns an array of matching components, we choose the one and only
var test2View = Ext.ComponentQuery.query('test2')[0];
// and now we can execute the function
test2View.test();
See the running minimalistic fiddle.
//View
Ext.define('MyApp.view.test', {
extend: 'Ext.form.field.Text',
alias: 'widget.test',
title: 'Hello',
listeners: {
focus: function (comp) {
//query returns an array of matching components, we choose the one and only
var test2View = Ext.ComponentQuery.query('test2')[0];
test2View.test();
//MyApp.app.getView('MyApp.view.test2').test();//Fails with an error that test is not a function
}
},
renderTo: Ext.getBody()
});
//View
Ext.define('MyApp.view.test2', {
extend: 'Ext.form.Panel',
alias: 'widget.test2',
title: 'Hello2',
renderTo: Ext.getBody(),
test: function ()
{
alert('in MyApp.view.test2');
}
});
Ext.application({
name: 'MyApp',
launch: function () {
Ext.create('MyApp.view.test');
Ext.create('MyApp.view.test2');
}
});
I want to add a button into a panel to the exact position where I clicked.
SO I have tried like as follows, this the structure of my Ext.widget element
Ext.widget({
xtype : 'mz-form-widget',
itemId: 'shopableImage',
anchor: "100%",
defaults: {
xtype: 'textfield',
listeners: {
controller: '',
change: function (cmp) {
controller = cmp;
cmp.up('#shopableImage').updatePreview();
}
}
},
items: [
{
xtype: "tacofilefield",
itemId: "imageUploadButton",
text: "Upload images"
},
{
xtype: 'panel',
width: 350,
height: 350,
itemId:'container',
id:'container',
bodyStyle:{"background":"url('http://www.easyvectors.com/assets/images/vectors/vmvectors/jeans-girl-vector-27.jpg')","border":"1px solid #eee"},
listeners: {
click: {
element: 'el', //bind to the underlying el property on the panel
fn: function(a,b,c,d){
console.log(a.browserEvent.clientX - b.offsetLeft);
console.log(a.browserEvent.clientY - b.offsetTop);
console.log(c);
this.down('#container').addItem({"xtype":"button","text":"+"});
}
},
dblclick: {
element: 'body', //bind to the underlying body property on the panel
fn: function(){ console.log('dblclick body'); }
}
}
}
The following line throwing me error.
this.down('#container').addItem({"xtype":"button","text":"+"});
UPDATE
this.down('#container')
is returning null.
Please give me your suggestions regarding this?
There are two problems here, one is causing the error and another is a potential time bomb:
addItem does not exist, the correct method name is add
You use id's on components and that is a very bad practice, however, it does not the immediate cause of the error
In my code, I create a panel object like below:
var grid = Ext.create('Ext.grid.Panel', {});
Then I am trying to define a widget which should contain the above panel as one of it's items.
I got the definition of my widget working fine. But how can I include the above grid object so that it is rendered as part of the widget:
Ext.define('Ext.simplegridwidget.GridTest', {
extend: 'Ext.panel.Panel',
alias: 'widget.gridtest',
title: 'User Management'
});
An even better approach so that everything related to my widget stays within the class definition...
Ext.define('Ext.simplegridwidget.GridTest', {
extend: 'Ext.panel.Panel',
alias: 'widget.gridtest',
title: 'User Management',
initComponent: function() {
var grid = Ext.create('Ext.grid.Panel', {});
Ext.apply(this, {
items: [ grid, details]
});
return this.callParent(arguments);
}
});
Ok.. figured it out. Not too difficult after all...
var grid = Ext.create('Ext.grid.Panel', {});
Ext.define('Ext.simplegridwidget.GridTest', {
extend: 'Ext.panel.Panel',
alias: 'widget.gridtest',
title: 'User Management',
items: [grid]
});
I've written a program in sencha, which worked fine. Since my files are getting too big, I am trying to split them into multiple small files using xtypes.
Basically, I am trying to have one main.js file calling an xtype list.js calling another xtype details.js also calling needed xtypes...
My problem is that since I've started to split my code, I am getting this error: Uncaught Attempting to create a component with an xtype that has not been registered.
I am sure that every single file is correctly link in my index.html.
Here is a sample of my code :
Details.js
var details = Ext.extend(Ext.Panel, {
layout: 'card',
cardSwitchAnimation: 'slide',
initComponent: function(){
Ext.apply(this,{
items:[]
})
details.superclass.initComponent.apply(this,arguments);
}
});
Ext.reg('details', details);
List.js
var Details = {xtype: 'details'};
var ListWrapper = new Ext.Panel({
id: "listwrapper",
layout: 'fit',
items: [List],
dockedItems: [homeTitleBar]
});
var Home = new Ext.Panel({
id: "home",
layout: 'card',
cardSwitchAnimation: 'slide',
items: [ListWrapper, Details]
});
var HomeTab = Ext.extend(Ext.Panel, {
iconCls: 'home',
title: 'Home',
layout: 'card',
initComponent: function() {
Ext.apply(this,{
items: [Home]
});
HomeTab.superclass.initComponent.apply(this,arguments);
}
});
Ext.reg('home', HomeTab);
Main.js
var menuBar = Ext.extend(Ext.TabPanel, {
layout: 'card',
cardSwitchAnimation: 'slide',
fullscreen: true,
tabBar: {
dock: 'bottom',
layout: {pack: 'center'}
},
items:[
{xtype: 'home'}
]
});
Ext.reg("menuBar", menuBar);
Check the ordering of your <script> tags. It sounds like you are loading your files in the wrong order (maybe main.js before list.js or list.js before details.js).
I would also only use Ext.reg if you are going to be re-using your defined components, in your case it's looks like you are just using them once so there's not much to gain and you could just pass in the Component rather than a redundant extra Object + xtype