Ext JS 4 - how to change content of an item which can't be referenced by an ID - extjs4

I would really appreciate any help with the following problem:
I need to be able to change content of an item (div or textfield) but the problem is that there are going to be multiple instances of the same window so I cannot use div IDs.
I tried this little example:
var myBtnHandler = function(btn) {
myPanel.items.items[0].html = "Changed by click!";
myPanel.doLayout();
}
var fileBtn = new Ext.Button({
text : 'Change',
handler : myBtnHandler
});
var panel1 = {
html : 'Original content.'
};
var myPanel = new Ext.Window({
title : 'How to change it?',
items : [
panel1,
fileBtn
]
});
myPanel.items.items[0].html = "Changed on load!";
myPanel.show();
Referencing an element by myPanel.items.items[0] works on load but does not work when it's in the button handler - is it a scope-related problem? How to reference an element without its ID?
Thank you very much,
H.

The problem has nothing to do with scope. The first time you set the html property, the component has not yet been rendered, so on initial render it will read the html property off the component. The second time, you're just setting a property on an object, it's not going to react in any way.
Instead, you should use the update() method.
Ext.require('*');
Ext.onReady(function() {
var myBtnHandler = function(btn) {
myPanel.items.first().update("Changed by click!");
}
var fileBtn = new Ext.Button({
text: 'Change',
handler: myBtnHandler
});
var panel1 = {
html: 'Original content.'
};
var myPanel = new Ext.Window({
title: 'How to change it?',
items: [panel1, fileBtn]
});
myPanel.items.items[0].html = "Changed on load!";
myPanel.show();
});

There are several functions that go through elements that belongs to a container. Try using for example down():
btn = panel.down('button');
Where 'button' parameter would mean 'give me element which type is equal to 'button'. Check out Sencha doc for querying various elements too: http://docs.sencha.com/ext-js/4-0/#!/api/Ext.ComponentQuery

Following on from Sha's reply. To put his advice in context with your example.
var myBtnHandler = function(btn) {
btn.up('window').down('panel').update('Changed by click!');
}
var fileBtn = new Ext.Button({
text : 'Change',
handler : myBtnHandler
});
var panel1 = {
html : 'Original content.'
};
var myPanel = new Ext.Window({
title : 'How to change it?',
items : [
panel1,
fileBtn
]
});
myPanel.show();
myPanel.update('Changed on load!');

Related

Dojo ListItem with Child Inputs

I have a dojo list item that is clickable.. But at the same time we like to put input elements inside the list item. The problem is that if you click on the child element(example checkbox) the listitem onclick intercepts the call first(which seems opposite of the html bubble up format). So we cannot call stoppropagation on the child element to stop the listitem from changing the page.
In the example below you will see the listitem alert come up before the checkbox alert..
How do you handle having input elements in a listitem without triggering the listitem..
fiddle::http://jsfiddle.net/theinnkeeper/HFA36/1/
ex.
var list1 = registry.byId("myList");
var item = new ListItem ({
label: "A \"programmatic\" ListItem",
moveTo: "#",
noArrow:true,
onClick : function() {
alert("listItem clicked !" + event.target.type);
}
});
list1.addChild(item);
var check = new cb({onClick:function(){alert("checkbox clicked");event.stopPropagation();}});
check.placeAt(item.containerNode.firstChild);
check.startup();
I had a similar problem a while back and noticed that the dojox/mobile/ListItem is not really great when adding extra event handlers to it (checkboxes, touch gestures, ...), so to solve that I usually extend dojox/mobile/ListItem and fix the events by myself.
For example:
var CheckedListItem = declare("dojox/mobile/CheckedListItem", [ ListItem ], {
_initializeCheckbox: function() {
this.checkbox = new CheckBox({
});
domConstruct.place(this.checkbox.domNode, this.containerNode.firstChild, "last");
this.checkbox.startup();
this.checkbox.onClick = this.onCheckboxClick;
},
onCheckboxClick: function() { },
_setOnCheckboxClickAttr: function(handler) {
this.onCheckboxClick = handler;
if (this.checkbox !== null && this.checkbox !== undefined) {
this.checkbox.onClick = handler;
}
},
_onClick: function(e) {
if (e.target !== this.checkbox.domNode) {
this.inherited(arguments);
}
},
postCreate: function() {
this.inherited(arguments);
this._initializeCheckbox();
}
});
Due to overriding _onClick() and adding additional checks I managed to get the intended behavior.
A full example can be found here: http://jsfiddle.net/LQ6Mb/

Stop double click action on a action-column

I've a grid panel in extJS 4.1.1. With other columns I've an actioncolumn(xtype:'actioncolumn'). I include a handler with that column. When I click it , it works fine and open a new window with many things loading. But I got error when I double click on that column. Advance welcome for any help.......
{
text : 'Signature',
menuDisabled : true,
sortable : false,
id : 'signature',
xtype : 'actioncolumn',
width : 60,
items : [{
icon : "${resource(dir: 'images', file: 'ADD01003.png')}",
tooltip : 'Add Signature',
scope : this,
handler : function(grid, rowIndex, colIndex) {
var records = grid.getStore().getAt(rowIndex).data,
fullName = records.fullName,
nickName = records.nickName,
salutation = grid.getStore().getAt(rowIndex).raw.m00i012001.name,
searchValue = records.id ;
var filters = new Array();
var store =Ext.data.StoreManager.lookup('S02X004001');
store.clearFilter();
filters.push({property:'member', value:searchValue});
store.loadPage(1, {
filters : filters,
callback : function(records, options, success) {
var view = Ext.widget('v02x004001');
view.show();
Ext.getCmp('fullName-sv02x00400104').setValue(fullName);
Ext.getCmp('nickName-sv02x00400104').setValue(nickName);
Ext.getCmp('member-sv02x00400104').setValue(searchValue);
Ext.getCmp('salutation-sv02x00400104').setValue(salutation);
}
});
}
}]
}
Not to resurrect any Zombies, but for anyone having the same Problem in ExtJS 4, 5 or 6 this workaround should work (maybe the Classnames need to be slightly modified, pasted Code is proven to work in 5.1.1).
The trick is to not modify the actioncolumn but to fix the itemdblclick event handler one might have like so:
listeners:
{
itemdblclick: function(v, record, item, index, e)
{
var flyTarget = Ext.fly(e.target);
if(flyTarget.hasCls('x-action-col-icon') || flyTarget.hasCls('x-grid-cell-inner-action-col'))
{
e.stopEvent();
return;
}
//your code here
}
}

Dojo CompoButton - onClick event of MenuItem issue with its function

I have the following code in dojo creating a ComboButton with several MenuItems of the correlated Menu:
testfunc = function (input) {
//Code that uses input
}
var menu = new Menu({
id: "saveMenu"
});
//array has 10 json objects and each object has an "Id" field
for(var i=0; i<10; i++) {
var temp = array[i]["Id"];
var menuItem1 = new MenuItem({
label: "Option"+i,
onClick: function() { testfunc(temp); }
});
menu.addChild(menuItem1);
}
var comboButton = new ComboButton({
optionsTitle: "Options",
label: "Combo",
dropDown: menu,
---> onClick:function(){ console.log("Clicked ComboButton"); }
}, "combo");
comboButton.startup();
menu.startup();
I need for each MenuItem its onClick function to pass a different variable in the testfunc. Specifically the value of the array[i]["Id"] which is an array that has 10 json objects. With the above code the parameter that is passed in ALL the testfunc functions of ALL the MenuItems is the last one.
Is it possible to pass for each MenuItem the correct array[i]["Id"] value
i.e.
MenuItem0 -> onClick: testfunc(array[0]["Id"])
MenuItem1 -> onClick: testfunc(array[1]["Id"])
MenuItem2 -> onClick: testfunc(array[2]["Id"])
.
.
.
etc
Thanks
I have found a solution to my problem and I think I should share it.
The issue was solved by passing in the testfunc of the onClick event of the menuItem the parameters using the "this" token e.g.
var menuItem1 = new MenuItem({
id: array[i]["Id"],
label: "Option"+i,
onClick: function() { testfunc(this.id, this.label); }
});

Dojo populate combo box widget dynamically

Could someone please explain to me why this simple straight forward code isnt working,
var serviceStore = new dojo.data.ItemFileWriteStore({
data: {identifier: "serviceCode",items:[]}
});
//jsonObj is a json object that I obtain from the server via AJAX
for(var i = 0; i<jsonObj.length;i++){
serviceStore.newItem({serviceCode: jsonObj[i]});
}
var serviceFilterSelect = dojo.byId('serviceSelect');
serviceFilterSelect.store = serviceStore;
There is no error at all displayed but my combobox with the id "serviceSelect" doesn't display any options, the combo is declared in the html section of my code,
<input dojoType = "dijit.form.ComboBox" id="serviceSelect"></input>
Any pointers towards the right direction will be much appreciated.
First of all you should use dijit.byId to get dojo widget instead of dojo.byId.
Also every item in jsonObj should contains field "name". This field will be displayed in combobox. E.g:
dojo.require("dojo.data.ItemFileWriteStore");
dojo.require("dijit.form.ComboBox");
var storeData = {
identifier: 'serviceCode',
items: []
}
var jsonObj = [{
serviceCode: 'sc1',
name: 'serviceCode1'
},
{
serviceCode: 'sc2',
name: 'serviceCode2'
}]
dojo.addOnLoad(function () {
var serviceStore = new dojo.data.ItemFileWriteStore({ data: storeData });
for (var i = 0; i < jsonObj.length; i++) {
serviceStore.newItem(jsonObj[i]);
}
var serviceFilterSelect = dijit.byId('serviceSelect');
serviceFilterSelect.attr('store', serviceStore);
});
And HTML:
<select dojotype="dijit.form.ComboBox" id="serviceSelect" ></select>
It seems that it works.
I can't tell from the code you posted, but if you're having trouble getting the DOM nodes, they may not had a chance to get loaded.
You can try wrapping what you have above with a dojo.ready(function(){ ... });.
Have you put items in your store? I can't tell from the sample that you posted.
var serviceStore = new dojo.data.ItemFileWriteStore({
data: {
identifier: "serviceCode"
,items: [
{serviceCode:'ec', name:'Ecuador'}
,{serviceCode:'eg', name:'Egypt'}
,{serviceCode:'sv', name:'El Salvador'}
]
}
});
For dojo >= 1.6:
dojo.byId('serviceSelect').store=serviceStore;
For dojo < 1.6:
dojo.byId('serviceSelect').attr("store",serviceStore);

Dojo Exception on hiding a dijit.Dialog

I have a Dialog with a form inside. The following code is just an example of what I'm trying to do. When you close a dijit.Dialog, if you dont't destroy recursively his children, you just can't reopen it (with the same id).
If you don't want to destroy your widget you can do something like that :
var createDialog = function(){
try{
// try to show the hidden dialog
var dlg = dijit.byId('yourDialogId');
dlg.show();
} catch (err) {
// create the dialog
var btnClose = new dijit.form.Button({
label:'Close',
onClick: function(){
dialog.hide();
}
}, document.createElement("button"));
var dialog = new dijit.Dialog({
id:'yourDialogId',
title:'yourTitle',
content:btnClose
});
dialog.show();
}
}
I hope this can help but with this code the error thrown is :
exception in animation handler for: onEnd (_base/fx.js:153)
Type Error: Cannot call method 'callback' of undefined (_base/fx.js:154)
I have to say I'm a little lost with this one ! It is driving me crazy ^^
PS : sorry for my "French" English ^^
I'll introduce you to your new best friend: dojo.hitch()
This allows you to bind your onClick function to the context in which it was created. Chances are, when you push the button in your code, it is calling your .show() .hide() form the context of the global window. var dlg was bound to your createDialog function, so it's insides are not visible to the global window, so the global window sees this as undefined.
Here's an example of what I changed to your code:
var createDialog = function(){
// try to show the hidden dialog
var dlg = dijit.byId('yourDialogId');
dlg.show();
// create the dialog
var btnClose = new dijit.form.Button({
label:'Close',
onClick: function(){
dojo.hitch(this, dlg.hide());
}
}, document.createElement("button"));
dlg.domNode.appendChild(btnClose.domNode);
var btnShow = new dijit.form.Button({
label : 'Open',
onClick : function() {
dojo.hitch(this, dlg.show());
}
}, document.createElement("Button"));
dojo.body().appendChild(btnShow.domNode);
};
dojo.ready(function() {
createDialog();
});
Note the use of dojo.hitch() to bind any future calls or clicks of the various buttons to the context in which the dlg was created, forever granting the button's onclick method access to the inside of the createDialog function, where var dlg exists.
hi if i understand correctly, you didn't need to destroy dijit.Dialog every time. E.g.:
HTML: define simple button:
<button id="buttonTwo" dojotype="dijit.form.Button" onclick="showDialog();" type="button">
Show me!
</button>
Javascript:
// required 'namespaces'
dojo.require("dijit.form.Button");
dojo.require("dijit.Dialog");
// creating dialog
var secondDlg;
dojo.addOnLoad(function () {
// define dialog content
var content = new dijit.form.Button({
label: 'close',
onClick: function () {
dijit.byId('formDialog').hide();
}
});
// create the dialog:
secondDlg = new dijit.Dialog({
id: 'formDialog',
title: "Programatic Dialog Creation",
style: "width: 300px",
content: content
});
});
function showDialog() {
secondDlg.show();
}
See Example and reed about dijit.dialog