I'm trying to extend a MessageBox within a view so I can reuse it throughout my application.
It seems that when I do so, I lose some of the default functionality that makes the messagebox useful (msg, button definitions, icon definitons, default drag constraints, etc). Documentation is a little confusing as it seems configs should be defined within the show() function, and I'm unsure of how to set them within my view.
How can I truly extend a messagebox component as a view?
Basic MessageBox (what I want to create with my view):
Ext.Msg.show({
title:'Error',
msg: 'There was an error.',
buttons: Ext.Msg.YESNOCANCEL,
icon: Ext.Msg.QUESTION
});
Renders:
but when I show my view:
Ext.create('IOL.view.app.Message').show();
I basically end up with a vanilla Panel/Window component
Ext.define('IOL.view.app.Message', {
extend : 'Ext.window.Window',
config: {
},
constructor: function(config) {
this.initConfig(config);
this.callParent(arguments);
},
initComponent : function() {
Ext.apply(this, {
xtype: 'messagebox',
width: 400,
height: 200,
title:'Error',
html: 'There was an error.',
buttons: [
{ text: 'Button 1' }
]
});
this.callParent(arguments);
}// initComponent
});
Renders:
It seems you are extending an Ext.window.Window and applying the messagebox configs to it. Why not just extend Ext.window.MessageBox:
Ext.define('IOL.view.app.Message', {
extend : 'Ext.window.MessageBox',
width: 400,
height: 200,
title: 'Error',
html: 'There was an error.',
buttons: Ext.Msg.YESNOCANCEL,
icon: Ext.Msg.ERROR,
// whatever else you want to do
initComponent : function() {
this.callParent(arguments);
}
});
#EricCook brings up a good point below. The MessageBox class is designed for reuse in the app as a singleton not really for subclassing.
In your question you said:
I'm trying to extend a MessageBox within a view so I can reuse it
throughout my application
I can understand that if you want to create a different type of messagebox that you would call with the normal Ext.Msg.show method, you could extend the MessageBox with your own buttons or icons I suppose.
But for regular use this isn't something you need to extend. For repeated use in your app you could hold a reference to the message box config you want in the controller like:
// SomeController.js
errorMsg: {
title:'Error',
msg: 'There was an error.',
buttons: Ext.Msg.YESNOCANCEL,
icon: Ext.Msg.QUESTION
},
Then whenever you want to call that type of message you could use (assuming the scope is the controller itself, or you could get a reference to the controller beforehand):
Ext.Msg.show(this.errorMsg);
Related
I was trying to set a fontawesome icon inside an Ext.MessageBox title and i managed to accomplish it using the code below:
Ext.Msg.show({
//iconCls: 'x-fa fa-times-circle',
title: '<span class="x-fa fa-exclamation"> Error Title</span>',
message: 'An error occured!!!!!',
buttons: Ext.MessageBox.OK,
width: 400
});
Reading the docs i found out that i could set the title using a config object for the Ext.panel.Title component.
But setting the config object like the example below was making the title invisible.
title: {
text: 'Error Title',
iconCls: 'x-fa fa-exclamation'
}
Also inspecting the view from the Elements tab of Chrome's Developer tools i saw that there is a div element for icons inside the x-paneltitle class.
<div class="x-icon-el x-font-icon" id="ext-element-15"></div>
How can i set the MessageBox title using the Ext.panel.Title config?
You have fallen into a documentation trap there.
The title config is available on the Ext.Panel class instantiation and therefore, technically, also on the Ext.MessageBox instantiation, but not on its show method, which you call on a singleton that has been pre-instantiated for you by Sencha.
The following would technically instantiate a Message Box with a custom title config:
Ext.create('Ext.MessageBox',{
title: {
text: 'Error Title',
iconCls: 'x-fa fa-exclamation'
}
});
However, to show the Ext.MessageBox, you have to call the show method, which has been overridden so as to overwrite every custom setting you add to the title config.
This works for me:
Ext.Msg.show({
title: {
text: 'Error Title',
iconCls: 'x-fa fa-exclamation'
},
message: 'You are closing a tab that has unsaved changes. Would you
like to save your changes?',
buttons: Ext.Msg.YESNOCANCEL,
icon: Ext.Msg.QUESTION,
fn: function(btn) {
if (btn === 'yes') {
console.log('Yes pressed');
} else if (btn === 'no') {
console.log('No pressed');
} else {
console.log('Cancel pressed');
}
}
});
Used it here:
https://docs.sencha.com/extjs/6.0.2/classic/Ext.window.MessageBox.html
It is Classic 6.0.2 but it should still work.
I have created some generic component which I am using in different product. Now here I have one window and window controller which is generic and I am overriding window class to make use of that in our product.
My Generic window.
Ext.define('App.win.Panel', {
extend: 'Ext.window.Window',
closeAction:'destroy',
maximizable:true,
hideToolbar:false,
requires: [
'App.MyWinCon.PanelController'
],
xtype: 'MyWin',
name:'MyWin',
controller: 'MyWinCon',
layout: {
type: 'border'
},
gridConfigs:{},
initComponent:function(){
var p=this;
p.items = [{
//items
}];
p.callParent(arguments);
}
});
And In my Product app I am using overriding like this way :
var Window1 = Ext.create('App.win.Panel', {
title: Windo,
modal:true,
height: '90%',
width: '95%',
parentGridObj:gridObj,
});
Window1.show();
There is no problem in that part. Window is coming.
Now in similar passion I have written controller in generic. I will show you small piece of code
Ext.define('App.MyWinCon.PanelController', {
extend: 'Ext.app.ViewController',
alias: 'controller.MyWinCon',
init: function(){
var p = this;
p.control({
#:{
beforeclose : function(this){
// SOme code
}
}
});
}
Now can anybody help me how to access this beforeclose or similar kind of methods in my app which is written in generic class.
Thanks for all the help.
You can't, or it's at least really really complicated; but there is a really really easy way with a minimum of refactoring:
Ext.define('App.MyWinCon.PanelController', {
extend: 'Ext.app.ViewController',
alias: 'controller.MyWinCon',
init: function(){
var p = this;
p.control({
#:{
beforeclose : p.beforeClose // just a reference to function below!
}
});
},
beforeClose: function(component){ // thou ought not use a variable named "this"!
// SOme code
}
Now you can access the function from your view:
view.getController().beforeClose()
I'm trying to edit open source program called PartKeepr (v0.1.9). In a specific part of program I want to add a button that opens a new Ext.window.Window. My codes are as following which doesn't work (I'm pretty new in extjs but I'm given a hard task I guess, so I'm open to all advice for where to start learning, I'm just trying to learn from existing codes and apply some things by looking similar parts of available code)
Ext.define('PartKeepr.FindWindow',{
extend:'Ext.window.Window',
constrainHeader: true,
title: i18n("Find Number"),
initComponent: function() {
this.okButton=Ext.create("Ext.button.Button",{
text:i18n("OK")});
this.buttons=[this.okButton];
}
});
{
xtype: 'button',
text: i18n("Find"),
name: 'findButton',
handler: Ext.bind(this.findNumber, this)
}
findNumber: function(){
var j = new PartKeepr.FindWindow();
j.show();
}
Edit: When I press the find button, console giving me the following error: ext-all.js:21 Uncaught TypeError: Cannot read property 'insert' of undefined
You need to call the superclass initComponent method:
Ext.define('PartKeepr.FindWindow', {
extend: 'Ext.window.Window',
constrainHeader: true,
title: i18n("Find Number"),
initComponent: function() {
this.okButton = Ext.create("Ext.button.Button", {
text: i18n("OK")
});
this.buttons = [this.okButton];
this.callParent();
}
});
I'm trying to create a dialog window in ExtJS to perform a save function, but I'm getting problems loading the page.
A (reduced) example of the code window definition is:
Ext.define('MyRequest.SaveDraftOrTemplateWindow', {
extend: 'Ext.window.Window',
alias: 'widget.saveDraftOrTemplateWindow',
requires: ['Ext.toolbar.Toolbar'],
modal: true,
initComponent: function() {
this.items = [ saveDraftOrTemplateForm ];
Ext.apply(this, {
dockedItems: [{
xtype: 'toolbar',
items: [
{
iconCls: 'saveas-draft',
text: '<b>Save</b>',
id: 'saveDraftTemplate',
handler: saveAsDraftRequest(textFieldDraftOrTemplateName.getValue(), checkBoxSaveAsTemplate.getValue()),
scope: this
}
]
}]
});
this.callParent();
}
});
function saveAsDraftRequest(draftName, isTemplate) {
Ext.getBody().mask('Saving draft request...'); // Errors actually occurs on this line
}
// This line is the start of the stack causing the problem...
var saveDraftOrTemplateWindowInstance = Ext.create('MyRequest.SaveDraftOrTemplateWindow', {
Id: 'saveDraftOrTemplateWindow',
xtype: 'saveDraftOrTemplateWindow',
width: 400,
height: 180,
bodyPadding: 0
});
The problem is that is seems to be 'calling' the saveAsDraftRequest() function when the page initially loads which gives the Javascript error "Uncaught TypeError: Cannot read property 'mask' of null", and prevents the page loading. I don't really understand why the function is getting called at this point, as the handler presumably shouldn't be called until the button is actually clicked.
I assume that if the page were already correctly loaded then Ext.getBody() would correctly return a result instead of null, but why is this getting called during the initial page load?
You are invoking saveAsDraftRequest function in initComponent in line:
handler: saveAsDraftRequest(textFieldDraftOrTemplateName.getValue(), checkBoxSaveAsTemplate.getValue())
You should change it to
handler: saveAsDraftRequest
Then you need resolve draftName and isTemplate in handler. You can for example assign them to button:
handler: saveAsDraftRequest,
draftName: textFieldDraftOrTemplateName.getValue(),
isTemplate: checkBoxSaveAsTemplate.getValue()
Then you can access them in handler like so:
function saveAsDraftRequest(sender) {
console.log(sender.draftName);
console.log(sender.isTemplate);
}
Ah, #Lolo has given me the hint I need - I see now that the initialisation code was invoking the function to get the handler to use - what I could have done is:
handler: function() {
saveAsDraftRequest(textFieldDraftOrTemplateName.getValue(), checkBoxSaveAsTemplate.getValue());
},
... if I wanted to invoke it there.
I am currently trying to add a custom button that will be able to call when ever the user wants to add a new button using EXTJS 4.
Here is the TimeButton.js file that i want to use to create the button
Ext.namespace("Ext.controls");
Ext.create('Ext.Button', {
text: 'Time',
renderTo: Ext.getBody(),
handler: function() {
alert('The current time is '+Date())
}
});
Ext.reg('timebutton', Ext.controls.TimeButton);
but when ever i try add it to any form i get the following error
types[config.xtype || defaultType] is not a constructor
Or would it be better to do something like this
Ext.controls.TimeButton = Ext.extend(Ext.Panel, {
initComponent: function(){
Ext.apply(this, {
frame: true
,height: 330
,layout: 'border'
,layout: 'column'
,split: true
,cls: 'DocumentWindow'
,items: []
});
this.documentGrid = new Ext.controls.DocumentGrid({height: 220,
agentId : this.agentId,
columnWidth: 0.5})
Ext.controls.DocumentPanel.superclass.initComponent.apply(this, arguments);
}
From what i understand this happens when trying to instantiate (create) a component that does not exist but i do not see where the error might be! is there an error in the code that I have posted?
Define your button as a class, register it for using with xtype by providing alias property and instantiate it in the parent items container. Here is an example.