How to get an element in a View from a Controller? - extjs

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();

Related

Duplicate reference when maximizing/restoring dialog

When maximizing/restoring a dialog that contains some form fields with names, like:
Ext.create('Ext.Dialog', {
maximizable: true,
items: {
xtype: 'textfield',
name: 'id',
bind: '{record.id}'
},
buttons: [{
text: 'Save',
bind: {
disabled: '{!record.valid}'
}
}]
}).show();
we're getting an error:
Ext.mixin.Container.attachNameRef(): Duplicate name: "id" on ext-viewport between ext-textfield-1 and ext-textfield-5
Two found workarounds :
Disable animation
Ext.define('Override.Dialog', {
override: 'Ext.Dialog',
config: {
maximizeAnimation: false,
restoreAnimation: false
}
});
Make the proxy used for animation have no items (nor buttons since button disable state may not reflect the bounded value
Ext.define('Override.Dialog', {
override: 'Ext.Dialog',
config: {
maximizeProxy: {
items: null,
buttons: null
}
}
});
Background Information
During maximize and minimize ExtJS creates a shadow clone.
This will create a clone of the window, while you still have the original item.
Using an ID means, there can only be one identical one at any given time.
The clone tries to create the your textfield with the same ID, which does not work.
Typically you want to
for forms you usually do not need to grab each item as you can work with validator and getValues on the form
otherwise you might want to work with references in the view and lookupReference in the controller.
not use animation (because that does not create a clone)
write your own maximize animation and do the animation part yourself (write your own maximize function)

Using Id and itemId in Extjs to access components

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/

How to use itemId in Sencha touch

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.

sencha touch how to change titles in tab bar

I cannot change the tabbar titles in a tab Panel.
Edit: I'm working on a test app witch consists in a main tab panel with other three views, similar to the "getting started video" of the sencha-touch documentation.
Now, for localization purposes, I need to change dinamically the labels under the icons of the tab bar, representing the three links to the panels.
In the code below there is my attempt to change the label of the first button by changing the title of the related view, as the label display "Home", that is the title of the view.
I want to do that on the "activate" event of the view.
The result of this code is that if I log the title of the home view, it is changed but the tab bar button label remains the same.
I think that I miss something like "refreshing" the button, but I cannot find anything on this subject on the documentation.
I hope this edit explains better my question.
Here is the code:
Ext.define('lvzMobile.view.Main', {
extend: 'Ext.tab.Panel',
requires: ['Ext.TitleBar'],
xtype: 'main',
config: {
tabBarPosition: "bottom",
items: [
{
xtype: 'homePanel',
id: 'home',
},
{
xtype: 'catalogue',
id: 'catalogue'
},
{
xtype: 'infoPanel',
id: 'info'
}
],
listeners: {
activate: function() {
console.log("activate");
this.getAt(0).setTitle("emoh");
//the title changes but nothing happens in the tabbar...
}
}
}
});
Please, can you help me? I can't understand what's wrong.
The line that says:
this.getAt(0).setTitle('emoh')
…will change the title of your panel, but not the button itself. To change the button text, use:
this.getTabBar().getAt(0).setTitle('emoh')
Here's a fiddle with your code to demonstrate.
While there, here's a tip: use alias: 'widget.main' instead of xtype: 'main'. xtype is for configs, alias is for defining the alias which in turn can be used later with xtype (use prefix widget. to be used as a widget, store. to be used as a store, etc.).

How to get ExtJs 4 panel to update itself on data refresh

I'm using ExtJs 4.
I have a panel that looks something like this:
var panel = Ext.create('Ext.panel.Panel',{
title: 'Current Transaction Data',
width: 500,
items:[
{
id: 'field1',
xtype: 'textfield',
label:'Field 1',
},
{
id: 'field 2',
xtype: 'textfield',
label:'Field 1',
}
],
})
I have a function to issue an ajax request that looks something like this:
var myDataObject;
var getData= function(callback){
Ext.Ajax.request({
url: 'MY-URL-TO-GET-DATA',
success: function(response){
myDataObject= Ext.JSON.decode(response.responseText)}})}
What I want to do is that after I retrieve my data object, I want to tell the panel to update with the new data. I'm looking for a call like panel.update(data).
I have seen the update() method on panel, but don't understand how to use it. Do I override it? It says something about using templates, but I haven't found any good examples. I'm not even sure if that's the preferred approach for doing this.
I have done similar type things using grid panel and using a data store. In that case I can call refresh() on the data store, but I don't want to use a grid for this particular problem.
You could use panel.update(data) but that just injects the text as innerHTML effectively, using the configured tpl if necessary. What are the two text fields in your panel for? You could set the text of one of those fields to the data, or add a Ext.form.field.DisplayView to the panel, and set the value of that to the data.
EDIT: As suggested in the comments below, the answer is to subclass and add a method to do the data refresh.

Resources