I have a view defined as following:
Ext.define('senchaTest.view.ModelDetailsView', {
extend: 'Ext.Panel',
requires: [
],
xtype: 'modeldetailsview',
config: {
modelName: null
layout: 'vbox',
items: [
{
xtype: 'label',
itemId: 'modelinformationview-name-label'
}]
},
updateModelName: function(modelName) {
var components = Ext.ComponentQuery.query('.modelinformationview #modelinformationview-name-label');
if (components && components.length > 0) {
components[0].setHtml(modelName);
};
}
});
I want to reuse this view in a tab panel. I have two tabs in tab panel. Each will have an instance of the above defined view. However, each will have different data and role.
When I try to set the config values of instances of these views, only one config is used. I understand that this happens because Ext.ComponentQuery queries the same component (For example, '.modelinformationview #modelinformationview-name-label'). It returns two components from each instance of the created views, I pick the first one and use that. Hence only one view is used always.
I want to know how to reuse defined views like this. I have some idea that Controllers can play a role in achieving this. But I haven't yet figured the best way to do it. Please help.
Thanks.
this is an instance of the right modeldetailsview in the updateModelName() function, hence it is as simple as:
updateModelName: function(modelName) {
var component = this.down('[itemId=modelinformationview-name-label]');
component.setHtml(modelName);
}
[EDIT]
I made this example to show you how to reuse components identifying them by itemId: https://fiddle.sencha.com/#fiddle/45o.
I defined the Fiddle.view.Main with two instances of Fiddle.view.Reusable, then in the initialize event of the Main view I get a reference to Main view, and from it I use Ext.Container.getComponent() to get the instances of the components by itemId.
itemId is just a way of identifying an instance of a component without polluting the global id space, and you can use it both to get an item in a container with Ext.Container.getComponent('foo'); like I did in my example, or more generally with componentQuery('[itemId=foo]'); like I did to answer your question.
A simple example :
Ext.define('App.view.Mygrid', {
extend: 'Ext.grid.Panel',
alias: 'widget.myGrid',
itemId: 'myGrid',
}
Then later you can add this by adding it to the items property of a parent like this :
items:
[{ xtype: 'myGrid' }]
Note that you don't need the itemId in this case. The alias property makes it so that you can instantiate views using the alias as an xtype.
Related
For testing purposes, I made 2 views. One that requires the other view. Now I want people to be able to open components multiple times as a tab, so I obviously have to assign unique ID's to each tab and element inside of the component, right?
My question is, how can I access one of the root properties in a view from say the docketItems object?
In the code below, it will cause an undefined this.varindex error at id: 'accountSearchField' + this.varindex,. varindex is dynamically assigned from the other component. (I hardcoded it in the example code below)
Note that I will not know the exact ID, so I can not use something such as Ext.getCmp. I could make use of Ext.ComponentQuery.query('searchAccount') but perhaps there is a better way to do this?
Listed below is a portion of the code that is required by my main component.
Ext.define('cp.views.search.Account', {
extend: 'Ext.panel.Panel',
xtype: 'searchAccount',
varindex: "uniqueid_assigned_by_main_component",
listeners: {
beforerender: function(){
this.id = 'panelSearchAccount' + this.varindex
}
},
items: [
{
xtype: 'grid',
store: {
type: 'Account'
},
id: 'searchAccount' + this.varindex,
columns: [
///
],
dockedItems: [
{
xtype: 'fieldset',
items: [
{
id: 'accountSearchField' + this.varindex,
xtype: 'searchfield'
}
]
}]
}
]
});
Ext will generate IDs for DOM elements and ensure they are unique to the page, so it is unusual to use the id attribute for referencing components. There are two configuration properties with this purpose, itemId and reference.
There are multiple methods that can be used to acquire a component by itemId from a parent container or globally.
Ext.container.Container.getComponent
Ext.container.Container.query
Ext.container.Container.down
Ext.container.Container.child
Ext.ComponentQuery.query
Additionally, components can be acquired by Ext.app.Controllers using the refs configuration. These methods take a selector string. The selector for an itemId is the itemId prefixed with '#' (e.g. '#itemId'). You do not specify the '#' when configuring a component with an itemId.
Introduced along with support for MVVM in Ext JS 5, the reference identifier is unique to the component's container or ViewController. A component can be acquired by reference from components or ViewControllers using lookupReference. The lookupReference method takes only references as input and therefore, does not require a prefix.
If you want to be able to reference a component associated with a particular model instance (account), you can define the component class with an alias and configure the reference or itemId when you add each instance to the container.
for (var i = 0, ilen = accountModels.length; i < ilen; ++i) {
container.add({
xtype: 'accountpanel',
reference: accountModel[i].get('accountNumber')
});
}
In this example, an account's associated panel can be acquired later on using the account number.
var accountPanel = this.lookupReference(accountModel.get('accountNumber'));
Actually I may have figured it out. I simply moved the items inside of the beforerender event and made use of the this.add() function.
In extjs 6 how to achieve the multiple instances of store assign to the same grid.
I created a grid and bind the store by creating stores in the viewmodel of that view and did the binding through the "bind"
Now i want to open same grid in multiple tabs..so that user can see diff data in two diff tabs..as i am using same grid and same store how to achieve that.
You don't. Put a different grid instance in the different tabs, each with their own store.
I suppose if you really had to, you could use the tabchange event to swap the store out when the tab changes, but that's messy.
Why do you insist on having just the one grid instance? What are you trying to achieve?
Well, normally, you define the grid once:
Ext.define('MyApp.view.Grid.ContentGrid',{
extend:'Ext.grid.Panel',
xtype:'ContentGrid',
initComponent:function() {
var me = this;
Ext.apply(me,{
columns:[{
...
}],
listeners:{
cellcontextmenu: function() {
}
}
});
me.callParent(arguments);
}
});
and then, in the view, you can use it as often as you wish through either Component hierarchy definition (more or less static) or Ext.create (at runtime):
Ext.define('Ext.Window',{
layout:'card',
items:[{
xtype:'ContentGrid',
store:'ABCStore',
},{
xtype:'ContentGrid',
store:'DEFStore',
}],
listeners:{
boxready:function(window) {
window.add(
Ext.create('MyApp.view.Grid.ContentGrid',{
store:'GHIStore'
})
);
}
}
});
In ExtJs Best practices I gone through not to use Id for accessing Ext Components rather use ItemId, I am very new in accessing components using ItemID, does any one can help me in default syntax or the way to access components.
Also on click of yes in a message box I need to disable some components in masked page, whether this can be achieved with the help of ItemID? Please explain.
I feel when using ItemiD it may return array of elements/components, so if need to get an exact component I need to iterate again. I have this ques too....
Basic difference between id and itemId is
When you use an id for a component, there must be a single instance of this component, If you create another instance that has the same id, you will have problems as the DOM is confused.
when you use itemId, it should be unique only within the component's immediate container.the component's container maintains a list of children ids.
so the best practice is to use itemId instead of id
now How to access?
if you use id
Ext.getCmp('id')
or
document.getElementById('id')
or
Ext.ComponentQuery.query("#id")[0]
if you use itemId
parentContainer.getComponent('child_itemId'),
refer following example
e.g
var parentContainer= Ext.create('Ext.panel.Panel', {
initComponent: function(){
Ext.applyIf(me, {
//childrens
items: [{
xtype:'textfield',
itemId:'text'
},
{
xtype:'panel',
itemId:'childpanel',
items:[
{
xtype:'combobox',
itemId:'combo'
}
]
}]
});
this.callParent(arguments);
},
renderTo:Ext.getBody()
})
in above example
for accessing textfield use
parentContainer.getComponent('text');
for accessing combobox use
parentContainer.getComponent('childpanel').getComponent('combo');
or
Ext.ComponentQuery.query("#combo")[0];
this will return array of item with id combo in page
for these you should use unique itemId so you will get the first item you are searching for
or
parentContainer.queryById('combo');
you can also use Ext.util.MixedCollection
var fields = new Ext.util.MixedCollection();
fields.addAll(parentContianer.query('[isFormField]'));
var Combo = fields.get('combo');
Lets suppose you define Panel like below which have a button. Now to access this button you can use Extjs ComponentQuery api. To uniquely identify my button I can use Ext.ComponentQuery.query('myPanel button[itemId=myButton]')[0]. For more details check http://docs-origin.sencha.com/extjs/4.2.2/#!/api/Ext.ComponentQuery
Ext.define('app.view.panel.MyPanel', {
extend: 'Ext.form.Panel',
alias: 'widget.myPanel',
height: 360,
width: 480,
layout:'fit',
title: 'My Panel',
initComponent: function(){
var me =this;
me.items=[{
xtype:'button',
itemId: 'myButton'
...
}]
this.callParent(arguments);
}
})
You can search and access components by using the
Ext.Component.query and passing along the itemId, refer to following links:-
http://training.figleaf.com/tutorials/senchacomplete/chapter2/lesson5/2.cfm
http://devjs.eu/en/how-to-use-ext-component-query-in-ext-js-4/
I have a few set of layouts in which the I rearrange a set of components (views) in different order.
What I would like to achieve is that the same instance of the view should be rendered on different layouts so that the state of the view is maintained.
I have done something similar
Ext.define('MyApp.view.FirstView',{
extend:'Ext.container.Container',
alias:'widget.firstView'
});
Ext.define('MyApp.view.SecondView',{
extend:'Ext.container.Container',
alias:'widget.secondView'
});
Ext.define('MyApp.view.HboxLayout',{
extend:'Ext.container.Container',
layout:{ type:'hbox',align:'stretch'},
items:[
{ xtype:'firstView'},
{xtype:'secondView'}]
});
Ext.define('MyApp.view.VboxLayout',{
extend:'Ext.container.Container',
layout:{ type:'vbox',align:'stretch'},
items:[
{ xtype:'firstView'},
{xtype:'secondView'}]
});
Any help appreciated.
You can call remove method on container still keeping the reference to it provided that container is configured with autoDestroy:false.
Then you can add the view you still have the reference of to the other container with add or insert methods.
Here are some links:
http://docs.sencha.com/extjs/4.2.2/#!/api/Ext.container.AbstractContainer-cfg-autoDestroy
http://docs.sencha.com/extjs/4.2.2/#!/api/Ext.container.AbstractContainer-method-remove
http://docs.sencha.com/extjs/4.2.2/#!/api/Ext.container.AbstractContainer-method-add
I am using Sencha Touch 2,0,1.
I need to get an element from a View in a Controller.
At the moment I use this method, which get the View correctly, but I am not able to get the Item in the View. I do not get any error just test is undefined.
Any ideas?
In the Controller:
var test = this.getDetailView().items['editButton'];
Code in the View:
Ext.define('XXX.view.DetailView',{
...
items: [
{
xtype: 'button',
text: 'Edit XXX',
ui: 'custom-btn-dwn-timetable',
itemId: 'editButton'
}
],
...
}
There are a couple other ways to get the reference to the edit button. You can wire the edit button as a ref like this:
Ext.define('MyApp.Controller', {
extend: 'Ext.app.Controller',
config: {
refs: {
editButton: '#editButton'
}
},
Then in your controller you can call the automatically generated getterthis.getEditButton() to get the actual edit button component.
Another thing you can do is save the edit button as an instance variable on your view like this:
Ext.define('XXX.view.DetailView',{
...
items: [
this.editButton = Ext.widget{(
xtype: 'button',
text: 'Edit XXX',
ui: 'custom-btn-dwn-timetable',
itemId: 'editButton'
)}
],
...
}
So now to access your button in the controller you have to do: this.getDetailView().editButton
In general, if an element is something you access a lot you should have a saved reference to it, rather than querying the DOM (to avoid unnecessary performance hit). Using Ext.getCmp() is also slower due to execution stack (it has to go through the ComponentManager every single time just to get the reference).
You can use Ext.ComponentQuery in this case to get your button:
Ext.ComponentQuery.query('#editButton')[1];
You could try setting your button id to edit and then
Ext.getCmp('edit').hide();