After upgrading from Ext5 to 7.2 it is no longer possible to see a tooltip after programatically enabling a button.
Ext.define('X', {
extend: 'Ext.panel.Panel',
initComponent: function() {
this.tbar = [{
text: 'Foo',
disabled: true,
itemId: 'fooBtn',
tooltip: 'FooTip',
handler: function(btn){
this.setHtml('Test')
},
scope: this
},
{
text: 'Bar',
tooltip: 'BarTip',
handler: function(btn) {
this.down('#fooBtn').enable();
},
scope: this
}];
this.callParent();
}
});
Ext.application({
name: 'Fiddle',
launch: function() {
new X({
renderTo: document.body,
title: 'Foo',
width: 200,
height: 200
});
}
});
https://fiddle.sencha.com/#view/editor&fiddle/37o5
Strange bug. You can use the following override to fix it:
Ext.define('overrides.button.Button', {
override: 'Ext.button.Button',
setTooltip: function(tooltip, initial) {
var me = this,
targetEl = me.el;
if (me.rendered) {
if (!initial || !tooltip) {
me.clearTip();
}
if (tooltip) {
if (Ext.quickTipsActive && Ext.isObject(tooltip)) {
Ext.tip.QuickTipManager.register(Ext.apply({
target: targetEl.id
}, tooltip));
me.tooltip = tooltip;
}
else {
targetEl.dom.setAttribute(me.getTipAttr(), tooltip);
}
me.currentTooltipEl = targetEl;
}
}
else {
me.tooltip = tooltip;
}
return me;
}
});
You may try to add one line after enabling:
handler: function(btn) {
this.down('#fooBtn').enable();
******this.down('#fooBtn').setTooltip("FooTip");*****
},
Maybe a bad solution but less code is required.
Related
Can't find out why its isn't working..
I'm trying create a custom panel for multiple uses.
Is it the way? Or am i totally wrong.
I'm a beginner in ExtJS, so i'll be happy to a little explain..
thanks
(i'm trying to run this code on the fiddle to see the immediate result - )
Ext.application({
name: 'Fiddle',
launch: function () {
var custom = Ext.define('Ext.BET', {
renderTo: Ext.getBody()
});
}
});
Ext.define('Ext.BET', {
extend: 'Ext.panel.Panel',
alias: 'widget.bet',
constructor: function (cnfg) {
this.callParent(arguments);
this.initConfig(cnfg);
},
config: {
collapsible: true,
frame: true,
bodyStyle: 'background-color: #FFFFFF',
layout: {
type: 'hbox'
},
items: [{
xtype: 'textfield',
textarea: focus,
id: 'tbx'
}, {
xtype: 'button',
id: 'btn'
}, {
xtype: 'button',
id: 'search'
}]
},
afterRender: function () {
var btn = Ext.getCmp('btn');
var tbx = Ext.getCmp('tbx');
var btn2 = Ext.getCmp('search');
var totalWidth = btn2.getWidth() + btn.getWidth() + tbx.getWidth();
this.setWidth(totalWidth);
},
onRender: function() {
this.callParent(arguments);
}
});
You should use Ext.create instead of Ext.define.Refer this fiddle.
I have a window(Ext.window.Window) in which I have pane in card layout. I am adding grid dynamically to the panels item as:
Ext.define('Example.view.ProcessInfoLayout',{
extend: 'Ext.window.Window',
requires: [
'Ext.layout.container.Card',
'Example.view.SubProcessController',
'Example.view.Info'
],
xtype: 'app--processinfolayout',
controller: 'main-content-subprocesscontroller',
layout: 'fit',
initComponent: function(){
this.callParent();
this.header = {
titlePosition: 0,
items:[{
xtype: 'button',
text: 'Resubmission',
glyph: 'xf0e2#FontAwesome',
tooltip: 'Resubmit',
listeners: {
click: 'ResubmissionClick'
}
}]
};
console.log('thisw')
this.items = []
this.add({
xtype: 'panel',
frame: false,
border: false,
itemId: 'v6panel',
layout: {
type:'card',
deferredRender: true
},
defaultListenerScope: true,
bbar: ['->',
{
itemId: 'card-prev',
text: '« Previous',
handler: 'showPrevious',
disabled: true
},
{
itemId: 'card-next',
text: 'Next »',
handler: 'showNext'
}
],
items: [],
initComponent: function() {
var me = this;
me.callParent();
me.store = Ext.getStore('app-main-store-' + me.up('app-main-processinfolayout').processData.id);
if (!me.store) {
me.store = Ext.create('Example.store.ProcessInfo', {
storeId: 'app-main-store-' + me.up('app-main-processinfolayout').processData.id,
room: me.up('app-main-processinfolayout').processData.id
});
me.store.proxy.url = Ext.String.format(me.store.proxy.url,
me.up('app-main-processinfolayout').processData.id);
}
me.store.on('load', function(store, records, successful, eOpts) {
console.log('####')
me.fireEvent('refreshProcessInfoLayoutView', me, records);
});
},
listeners:{
beforerender: function(obj) {
console.log('Hey Australia')
obj.store.load();
},
refreshProcessInfoLayoutView: 'refreshProcessInfoLayoutView',
scope: 'this'
},
refreshProcessInfoLayoutView: function(obj, records) {
console.log('thise')
console.log(records[0].data.processes)
if (records[0].data.v6_processes) {
for (elem in records[0].data.processes) {
var subprocessInfo = {
xtype: 'app-main-cycle-info',
processId: records[0].data.processes[elem],
itemId: 'card-' + elem
};
obj.add(subprocessInfo);
}
}
},
showNext: function () {
this.doCardNavigation(1);
},
showPrevious: function (btn) {
this.doCardNavigation(-1);
},
doCardNavigation: function (incr) {
var me = this;
var l = me.getLayout();
var i = l.activeItem.id.split('card-')[1];
var next = parseInt(i, 10) + incr;
l.setActiveItem(next);
me.down('#card-prev').setDisabled(next===0);
me.down('#card-next').setDisabled(next===this.down('#v6panel').store.getCount() - 1);
}
})
}
})
It prints console log upto thisw . After that it gives error as...Uncaught TypeError: me.items.insert is not a function. What I am doing wrong. Please suggest.
Don't do this.callParent(); in your initComponent before specifying this.header and this.items. Do it after. This is because once you've called this.callParent(); your component is instantiated, therefore trying stuff like this.items = [] just screws things up.
Also, instead of:
this.items = [];
this.add({stuff});
do:
this.items = [{stuff}];
When dealing with nested items and initComponent functions, you can use the xhooks config so that callParent() can work properly :
Ext.define('Example.view.ProcessInfoLayout', {
// ...
xhooks: {
initComponent: function(){
this.callParent();
// ...
this.add({
xtype: 'panel',
// ...
items: [],
initComponent: function() {
// ...
}
});
}
}
});
Have a look at the Ext.Component constructor method.
i am very new to EXT.js; i need to submit the form when ENTER is pressed below is my code but i dont know what to call in the listener of the password field here is my code:
ie:what is the function to call in the listener
<script type="text/javascript">
Ext.onReady(function() {
Ext.tip.QuickTipManager.init();
Ext.create("Ext.container.Viewport", {
layout: "border",
rtl: <spring:theme code='theme.rtl' text='false' />
});
Ext.create("Ext.window.Window", {
title: "<spring:message code='title.login' text='Login' />",
height: 310,
width: 450,
closable: false,
layout: "border",
items: [{
xtype: "panel",
border: false,
bodyCls: "login-header",
height: 160,
region: "north"
}, {
id: "<%=loginFormId%>",
url: "<spring:url value='/secure/auth'/>",
xtype: "form",
layout: "form",
region: "center",
bodyPadding: 10,
border: false,
buttons: [{
handler: function() {
var form = this.up("form").getForm();
if (form.isValid()) {
Ext.getCmp("<%=submitBtnId%>").disable();
form.standardSubmit = true;
form.method = "POST";
form.submit();
}
},
id: "<%=submitBtnId%>",
text: "<spring:message code='button.submit' text='Submit' />"
}, {
handler: function() {
var form = this.up("form").getForm();
form.reset();
},
id: "<%=clearBtnId%>",
text: "<spring:message code='button.clear' text='Clear' />"
}],
defaultType: "textfield",
defaults: {
msgTarget: "side",
labelWidth: 100
},
items: [{
fieldLabel: "<spring:message code='input.username' text='Username' />",
name: "selfcare_username"
}, {
fieldLabel: "<spring:message code='input.password' text='Password' />",
name: "selfcare_password",
enableKeyEvents:true,
inputType: "password",
listeners: {
scope: this,
specialkey: function(f, e) {
if (e.getKey() === e.ENTER) {
}
}
}
}]
}]
}).show();
<c:if test="${not empty param.error}">
var errorMsg = "<c:out value="${SPRING_SECURITY_LAST_EXCEPTION.message}" />";
if (errorMsg !== "") {
Ext.MessageBox.show({
title: "<spring:message code='title.error' text='Error' />",
msg: errorMsg,
closable: false,
buttons: Ext.Msg.OK
});
}
</c:if>
});
</script>
These days it is better to use the defaultButton property on the form to designate the default button on the form. This is the button who's handler will handle your ENTER key.:
http://docs.sencha.com/extjs/6.0/6.0.2-classic/#!/api/Ext.panel.Panel-cfg-defaultButton
You should attach key event of the components listener, here is the sample which is working if the field not empty and pressed key ENTER or TAB inside the field.
suppliers is a JsonStore where I am loading store by params which means you can call whatever you wrote in the app.
{
xtype: 'textfield',
id: 'supplier-id',
flex: 1,
tabIndex: 1,
fieldLabel: 'SUPPLIER NO',
fieldStyle: 'text-align: right; font-size: 12pt',
margins: '0 5 0 0',
enablekeyEvents: true,
listeners: {
specialkey: function (field, e) {
if (field.getValue() != 'null') {
if (e.getKey() === e.ENTER || e.TAB) {
suppliers.load({
params: {'supplier': field.getValue(), 'type': 'supplier'},
callback: function () {
Ext.getCmp('supplier-name').setValue(suppliers.data.items[0].data['MATCH_NAME']);
}
});
}
}
},
focus: function (e) {
e.setValue('');
Ext.getCmp('supplier-name').setValue("");
suppliers.loadData([], false);
}
}
}
For Sencha:
listeners: {
specialkey: function(field, e){
if (e.getKey() == e.ENTER) {
//submitLogin();
}
}
},
Add listener with afterrender
listeners: {
afterRender: function(thisForm, options){
this.keyNav = Ext.create('Ext.util.KeyNav', this.el, {
enter: fnLogin,//give here to login function
scope: this
});
}
}
I want listen when file has been change like. But It not working
{
xtype: 'filefield',
id: 'form-file',
fieldLabel: 'Photo',
name: 'photo-path',
buttonText: '',
buttonConfig: {
iconCls: 'upload-icon'
},
listeners: {
'change': function(this, value){
alert('change');
}
}
}
You can't do it with filefield of Extjs
I have the solution.
Example: http://jsfiddle.net/e3M3e/e8V7g/
var itemFile = null;
Ext.create('Ext.panel.Panel', {
title: 'Hello',
width: 400,
html: "<input id='inputFile' type='file' name='uploaded'/>",
renderTo: Ext.getBody(),
listeners: {
afterrender: function() {
itemFile = document.getElementById("inputFile");
itemFile.addEventListener('change', EventChange, false);
}
}
});
function EventChange(e){
var files = itemFile.files;
console.log(files);
}
I found solution: function change must be:
change: function(f,new_val) { alert(new_val); }
I have form panel as a menu item. The problem is that it constantly looses focus and standard navigation controls like tab are not working. Is there some kind of config to make this work? Notice i extend Ext.panel.Panel instead of Ext.form.Panel. When i use the second one i get origin.on is not a function. Here is code:
this.tbar = [{
xtype: 'tbfill'
}, {
xtype: 'tbseparator'
}, {
xtype: 'button',
text: 'Wyszukiwanie',
iconCls: 'icon-magnifier',
menu: {
focusOnToFront: true,
items: [{
xtype: 'decision_quicksearch',
title: 'Panel wyszukiwania',
iconCls: 'icon-magnifier',
}]
},
listeners: {
afterrender: function () {
//register this btn to quicksearch panel so we can hide menu when search button is clicked
Ext.apply(this.menu.items.items[0], {
parentComponent: this
});
}
}
}];
And the form:
Ext.define('GSIP.view.decisions.DecisionQuickSearchPanel' ,{
extend: 'Ext.form.Panel',
alias : 'widget.decision_quicksearch',
layout:'anchor',
title:'Wyszukiwanie decyzji',
frame:true,
width:300,
defaults: {
anchor: '100%'
},
style: {
marginLeft: 'auto',
marginRight: 'auto'
},
bodyPadding:20,
initComponent: function() {
this.addEvents('quicksearch');
this.items = this.createForm();
this.buttons = [{
text:'Szukaj',
iconCls:'icon-magnifier',
scope:this,
handler:this.processForm
}],
this.callParent(arguments);
},
createForm:function() {
var items = [{
xtype:'textfield',
fieldLabel:'Znak',
labelWidth:40,
name:'sign'
},{
xtype:'textfield',
fieldLabel:'Numer',
labelWidth:40,
name:'number'
},{
xtype:'textfield',
fieldLabel:'Rok',
labelWidth:40,
name:'suffix',
}];
return items;
},
processForm:function() {
var result = this.buildFilter();
this.fireEvent('quicksearch', result);
this.parentComponent.hideMenu();
},
buildFilter:function() {
var sign = this.down('textfield[name=sign]').getValue();
var number = this.down('textfield[name=number]').getValue();
var suffix = this.down('textfield[name=suffix]').getValue();
var result = new Array();
var res = {
name:'documents.sign',
valuesType:'string',
filterType:'like',
values:[{id:1, value:sign}]
};
result.push(res);
var res = {
name:'documents.number',
valuesType:'string',
filterType:'like',
values:[{id:1, value:number}]
};
result.push(res);
var res = {
name:'documents.suffix',
valuesType:'string',
filterType:'like',
values:[{id:1, value:suffix}]
};
result.push(res);
return result;
}
});
I have accomplished a similar functionality but in a different way.
What I did is simply made the button generate an Ext.Window with no header and limited border and positioned it under the button on open. You can then use MouseOut events to close the window and it will operate just like a menu or you could put the header on the bottom and place a close tool and have the window "pin".
buttonClick: function (btn, e, opts) {
var popUpWindow = Ext.create('Ext.window.Window', {
width: 450,
maxHeight: 400,
resizable: false,
closable: false,
title: 'Report Filters',
headerPosition: 'bottom',
border: false,
draggable: false,
bodyStyle: 'background:white;padding:5px;',
items: [
//...your form
]
});
popUpWindow.showAt(btn.getBox(false).x - 3, btn.getBox(false).y - 7);
}
Here is what i ended up with. It seems that this is exactly as if i was using menu but using method provided by ViaoV
var me = this;
this.popUpWindow = Ext.create('Ext.window.Window', {
resizable: false,
closable: false,
constrainHeader: true,
title: 'Panel wyszukiwania',
iconCls: 'icon-magnifier',
border: false,
draggable: false,
items: [{
xtype: 'decision_quicksearch',
listeners: {
afterrender:function(me) {
Ext.getDoc().on('mousedown', function(o) {
console.log('mousedown');
if (!o.within(me.getEl())) {
me.parentComponent.toggle(false);
}
})
// me.getEl().on('blur', function() {
// console.log('blur');
// me.parentComponent.toggle(false);
// });
}
},
}]
});
this.tbar = [{
xtype:'tbfill'
}, {
xtype:'tbseparator'
}, {
xtype:'button',
text:'Wyszukiwanie',
iconCls:'icon-magnifier',
enableToggle:true,
menu: { },
listeners:{
afterrender:function() {
//register this btn to quicksearch panel so we can hide menu when search button is clicked
Ext.apply(me.popUpWindow, {
parentComponent:this
});
},
toggle: function(btn, pressed) {
if (pressed) me.popUpWindow.showAt(btn.getBox(false).x - 3, btn.getBox(false).y + btn.getBox(false).height);
else me.popUpWindow.hide();
}
}
}];
EDIT: After some testing the solution i ended up with is not a good one. I have comboboxes in my panel which are defined by boundlist as another dom, so when i pick item from cbox !o.within(me.getEl()) evaluates to true and hides my panel. I really need the functionality when the user clicks elsewhere the window hides.