I have used the following to add content to my view:
Ext.getCmp('mainpage').add({items:thecarousel});
thecarousel is an array representing my carousel and its content. This all works as I require it to. Here's the code for it:
var thecarousel = {
xtype: 'carousel',
width: '100%',
height: '100%',
itemId: 'thecarousel',
id: 'carousel',
defaults: {
styleHtmlContent:true,
},
items: allcharts,
}
Ext.getCmp('mainpage').add({items:thecarousel});
Ext.Viewport.setMasked(false);// remove loading message`
What I am looking for is an method to do the opposite of this and remove the carousel from the view.`
I have unsuccessfully tried the following:
Ext.getCmp('mainpage').remove('carousel',false)
Ext.getCmp('mainpage').remove({items:'carousel'})
Ext.getCmp('mainpage').remove('carousel',true)
If you are using id: 'carousel', you can do that like this:
Ext.getCmp('mainpage').remove(Ext.getCmp('carousel'))
You could also do it using a component query:
var main = Ext.getCmp('mainpanel');
main.remove(main.down('#carousel'));//added missing closing brackets
//OR, if there is only one component of xtype 'carousel' on your mainpanel:
main.remove(main.down('carousel'));
I personally would avoid using IDs and go with the second method (you could give the carousel an itemId: 'carousel' and still use main.remove(main.down('#carousel')) if you want).
Related
I've created a fiddle just to simulate my problem with class property not being reset on window destroy.
How to test:
Open fiddle, press OPEN button, ADD 3 panels, close ext window, press OPEN button again, and add a some more panels.
Panel numbers represent the length of the _panels array property in window.
Now to the problem.
As you can see panel NUMBER when adding new panels is not reset. So if you add 3 panels and close the window, reopen the window panels count shows 3 and then 4 and then 5 instead of 0 1 2 ...
My question is, why?
Fiddle example
Kind regards
Armando
EDIT : so one can see the solution
I ended fixing my application to work like this fiddle. I moved properties to constructor.
constructor: function() {
Ext.apply(this, {
width: 800,
height: 600,
layout: 'vbox',
_panels : []
});
this.callParent(arguments);
},
When you define
Ext.define('TestWindow', {
extend: 'Ext.window.Window',
_panel: []
});
The TestWindow definition class gets empty array property (no-primitive datatype). When you create an instance by var win = Ext.create('TestWindow'), the instance gets that property. However, when you set:
onDestroy: function() {
this._panels = [];
},
it sets empty array to property _panels of the instance win, not on the definition class TestWindow; TestWindow keeps the existing mutated _panel. And when next time you create new instance, it gets same _panel from class definition.
I understand you did it for demo purpose to show the problem. However, I prefer to let framework do all heavy-lifting (create and destroy etc):
Ext.define('TestWindow', {
extend: 'Ext.window.Window',
width: 800,
height: 600,
defaultListenerScope: true,
layout: 'vbox',
initComponent: function() {
this._panels = [];
this.callParent(arguments);
},
addPanel: function() {
console.log(this._panels.length);
var panels = this._panels;
panels.push(this.add({
xtype: 'panel',
title: 'Panel ' + panels.length,
height: 50,
width: '100%'
}));
},
tbar: [{
xtype : 'button',
text: 'add',
handler: 'addPanel'
}]
});
The simple answer for this is prototypal inheritance (see this MDN article). Basically your non-primitives will carry over to new instances because they exist on your prototype class, and because they're non-primitives, it's the same exact reference that's used. To fix this, I would recommend wrapping your _panels variable in the config block, like below, and encourage you to use the appropriate set/get methods, instead of accessing it directly:
config: {
_panels : []
}
A less than correct answer if the prototype behavior in the previous answer is "A feature/intentional bad code/ legacy code with unintended consequences"
Manually overwrite the prototype Value, following instantiation of the panel
I want to write a proof-of-concept app along these lines:
View
- a URL text input field at top with Go button
- a big DIV underneath consisting of the rest of the view
Controller
- upon Go pressed, validate the URL text
- set up the URL to the data source
- read data from the data source
- create a nested DIV element for each data, apply CSS rules
- add the element to the big DIV
Model
- define the fields
- define the default ordering
CSS
- define the styles
First, does what I have written above work within ExtJS or will I be fighting the framework? In particular, inserting plain HTML as element nodes.
Second, does anyone know of an existing project under GPL which could act as starting point? So far what I've seen are flashy examples with URLs hard-coded and set to auto-load.
There's nothing scary or otherwise disturbing in what you've written.
Although not much advertised, ExtJS handles custom HTML & CSS pretty well. You can set some using the html or tpl config options. The latter is powered by XTemplates, so you can do loops, etc. When using these options and/or custom CSS, Ext will calculate its layouts around the rendered result, accounting for your custom style automatically. Now, in practice, that's a whole lot of work for the framework, and it doesn't always work as expected, and it won't work at all on some browsers (like not so old IE, of course). One big pitfall you should be aware of is that you should always use integer value in px for your CSS, since if a dimension resolve to a decimal value in px, Ext will choke on that.
That said, since you're apparently going to back your data with a model, you should probably use a dataview. That's a component that let you use custom HTML over a regular Ext store. It then provides goodies for item selection, paging, etc. It's the base class of other advanced data views, like Ext grids.
Regarding URLs, you don't necessarily have to hardcode them in the model's proxy (or elsewhere). You can pass an URL to an existing store's load method (as documented here).
Finally, I don't know of existing projects, but your POC is really straightforward, so here's a fiddle to get you started. The code is not 100% clean, in particular defining everything in a single file, and thus missing all the requires... But it illustrates most of the points you've asked about. Read the docs about the components / methods that are used to learn how to go beyond this.
Here's the fiddle's code:
Ext.define('Foo.model.Item', {
extend: 'Ext.data.Model',
fields: ['name']
});
Ext.define('Foo.view.MainController', {
extend: 'Ext.app.ViewController',
alias: 'controller.main',
onGo: function() {
var view = this.getView(),
url = view.down('textfield').getValue(),
dataview = view.down('dataview'),
store = dataview.getStore();
if (this.isValidUrl(url)) {
store.load({url: url});
} else {
Ext.Msg.alert(
"Invalid URL",
"This URL cannot be loaded here: " + url
);
}
},
// private
isValidUrl: function(url) {
return ['data1.json', 'data2.json'].indexOf(url) !== -1;
}
});
Ext.define('Foo.view.Main', {
extend: 'Ext.Panel',
xtype: 'main',
controller: 'main',
layout: {
type: 'vbox',
align: 'stretch'
},
items: [{
xtype: 'container',
layout: 'hbox',
margin: 3,
defaults: {
margin: 3
},
items: [{
flex: 1,
xtype: 'textfield',
emptyText: "Valid inputs are 'data1.json' or 'data2.json'",
listeners: {
specialkey: function(field, e) {
if (e.getKey() === e.ENTER) {
// custom event, for the fun of it
field.fireEvent('enterkey', field, e);
}
},
// the custom can be bound to controller in "modern ext" way
enterkey: 'onGo'
}
},{
xtype: 'button',
text: "Go",
handler: 'onGo'
}]
},{
flex: 1,
xtype: 'dataview',
margin: '0 6 6 6',
cls: 'my-dataview', // for CSS styling
store: {
model: 'Foo.model.Item',
autoLoad: false
// default proxy is ajax and default reader is json,
// which is cool for us
},
tpl: '<tpl for=".">' + '<div class="item">{name}</div>' + '</tpl>',
itemSelector: '.item'
}]
});
Ext.application({
name : 'Foo',
mainView: 'Foo.view.Main'
});
Some CSS for the data view:
.my-dataview .item {
padding: 1em;
border: 1px solid cyan;
color: magenta;
float: left;
margin: 6px;
width: 100px;
}
And an example JSON response (this is the bare minimum to be functional... read about proxies & reader to go further):
[{
name: 'Foo'
},{
name: 'Bar'
},{
name: 'Baz'
}]
Is there a way to define a window as unique ?
What I mean exactly is: when the window is already open, I want it to get focus, instead of opening it again.
For now my menu click event just does:
onMenuItemClick: function(){
Ext.create('Mb.view.UniqueWindow').show()
},
Give it a unique id, then verify if it already exists before creating it, otherwise just show it, something like
function onMenuItemClick() {
var wnd = Ext.getCmp('myUniqueWindow');
if (!wnd) {
wnd = Ext.create('Ext.window.Window', {
id: 'myUniqueWindow',
title: 'Unique Window',
height: 200,
width: 400,
layout: 'fit',
closeAction: 'hide', // This is really important otherwise closing it will destroy the window!
items: { // Let's put an empty grid in just to illustrate fit layout
xtype: 'grid',
border: false,
columns: [{
header: 'Hello World'
}], // One header just for show. There's no data,
store: Ext.create('Ext.data.ArrayStore', {}) // A dummy empty data store
}
});
} else {
wnd.getEl().highlight()
}
wnd.show();
}
You can see a working sample here
Save a reference to it:
if (!MyApp.someWin) {
MyApp.someWin = new Ext.window.Window();
}
MyApp.someWin.show();
I am getting an object using Ext.component.Query. I need to check whether the object exists or not. If object exists, I need to remove the object. Can anybody tell me how to do this?
Thanks
As other posters have mentioned, the method you're looking for is Ext.ComponentQuery, which returns an array which you can then check the length of via length, which will in turn tell you if the object exists or not. If the object exists, it can be destroyed via the destroy() method of the Ext.AbstractComponent
I have made a jsFiddle example demonstrating what you're trying to do here: http://jsfiddle.net/mPYPw/
Code from the fiddle:
Ext.create('Ext.panel.Panel', {
name : 'myPanel',
title: 'Panel 1',
width: 200,
html: '<b>Its a panel!</b>',
renderTo: Ext.getBody()
});
Ext.create('Ext.panel.Panel', {
name : 'myPanel',
title: 'Panel 2',
width: 200,
html: 'Look, another panel!',
renderTo: Ext.getBody(),
dockedItems: [{
xtype: 'toolbar',
dock : 'bottom',
items: [{
text: 'Destroy all panels!',
handler: function(){
// Here we can query for the panels
var panels = Ext.ComponentQuery.query('panel[name=myPanel]'),
trees = Ext.ComponentQuery.query('treepanel');
// #param {Ext.panel.Panel[]} panels Array of panel components
if(panels.length > 0){
alert("About to destroy " + panels.length + " Panels!");
Ext.each(panels, function(panel){
panel.destroy();
});
}
// There are no tree panels
if(!trees.length){
alert("There are no tree panels to destroy!");
}
}
}]
}]
});
Simple check with Ext.ComponentQuery
var check = Ext.ComponentQuery.query('yourXtype');
if (check.length > 0)
//do something
else
//do other something
I know the documentation was messed up on one of the versions... I don't know if it is still the same in Ext JS 4.2, but in 4.1.1 you can query for Ext JS objects by xtype using something similar to this:
Ext.ComponentQuery.query('xtype');
i.e.
Ext.ComponentQuery.query('gridpanel');
I think Ext.ComponentQuery-method-query explains it.
FIRST NOTE THAT Ext.getCmp("id") is suitable for small Apps..
If u tend to hav a big app u could go for a Component Query .
This can be done in two ways Either u could use a "Xtype" or "component Id"(note component id must be prefixed with a #).
Using ExtJs 4.1
Is there a way to query all floating components (windows, message boxes, etc.)?
My aim is to remove (destroy) all floating objects. It would be sufficient to "get" them on the first hand.
Well simply do it by using the Ext.WindowManager which is responsible for all floating components by default.
Following should work:
Ext.WindowManager.each(function(cmp) { cmp.destroy(); });
Here's a example JSFiddle:
Ext.create('Ext.window.Window', {
title: 'Hello',
height: 200,
width: 400,
layout: 'fit',
items: { // Let's put an empty grid in just to illustrate fit layout
xtype: 'grid',
border: false,
columns: [{header: 'World'}], // One header just for show. There's no data,
store: Ext.create('Ext.data.ArrayStore', {}) // A dummy empty data store
}
}).show();
Ext.Function.defer(function(){Ext.WindowManager.each(function(cmp) { cmp.destroy(); })}, 5000);
For further reading on DOM-Query
Edit destroy only defined types
For that case go with the xtype of the component and check it.
Ext.WindowManager.each(function(cmp) { if (cmp.xtype === 'window') cmp.destroy(); });