Ext.Button handler config option - javascript

someClass = Ext.extend(someClassB, {
_someFunctionC{
someButton = new Ext.button({
handler: function () {
this._onClick('click');
}
}),
_onClick(someMessage){
Ext.Msg.alert(someMessage);
}
}
}
_onClick eats one parameter; in the above code you put in the 'click' event because you want _onClick to be executed after the user clicks on the button. However, how do you specify this specific 'click' registration AND pass in a local variable as the _onClick parameter at the same time?
As an aside, why do you even have to specify 'click', when the API states that handler always pertains to a click? Is this additional information not unnecessary?

Typically you set it up like this. No real need to pass parameters since someFunction is a member of your 'class' and has access to any data you'd want.
var button = new Ext.Button({
handler: this.someFunction
scope: this
});
someFunction: function() {
// do something interesting.
}

So if i understand correctly you want to set the handler config option but set the arguments yourself in one go?
Does this do what you want?
// clicking the button alerts 'Hello World'
new Ext.Button({
text: 'Test',
handler: function(value){
alert('Hello, ' + value);
}.createCallback('World')
});
Notice the createCallback executed on the anonymous function, this creates a callback function for handler which only gets passed the arguments you pass to createCallback.

Another way that I've found to do this is to pass a custom config option along with your button. Say you wanted to have a splitbutton that could choose the amount of banners to add. (this is from a recent project)
{
xtype: 'splitbutton',
iconCls: 'icon addBanners',
ref: '../addBanner',
text: 'Add Banner',
menu: new Ext.menu.Menu({
items: [{
text: 'Add 10 Banners',
scope: this,
handler: this.addBanner,
numBanners: 10
},{
text: 'Add 20 Banners',
scope: this,
handler: this.addBanner,
numBanners: 20
}]
}),
scope: this,
handler: this.addBanner,
numBanners: 1
}
And in your function:
addBanner: function(button, event) {
if (button.numBanners) {
// do whatever
}
}

You can also create a callback function that inserts extra parameters when it is called:
var button = new Ext.Button({
handler: this.someFunction.createDelegate(button,['Some message'])
});

Related

Bind an Event via a JSON Model

I wonder if it is possible to bind an Event via a JSONModel.
If I do so, it will always throw this Exception:
Uncaught TypeError: I.fFunction.call is not a function
This is my code:
_ViewReference: undefined,
_oMenuItemsConfigModel: undefined,
createMenu: function(oItem){
if (!this._menu) {
this._menu = new sap.ui.unified.Menu(this._oMenuConfig);
this._menu.setModel(this._oMenuItemsConfigModel);
this._menu.bindAggregation("items", "/", new sap.ui.unified.MenuItem({
text: "{text}",
icon: "{icon}",
select: "{select}",
enabled: "{enabled}"
}));
this._ViewReference.addDependent(this._menu);
}
var eDock = sap.ui.core.Popup.Dock;
this._menu.open(false, oItem, eDock.BeginTop, eDock.BeginBottom, oItem);
return oItem;
}
I have a Universal ContextMenu which just needs some config in order to get created. This is how I call this function from my Controller:
var oContextMenu = new ContextMenu(this.getView(),
new sap.ui.model.json.JSONModel(
[
{
text: "Copy",
select: [this.onContextMenuItemCopySelected, this]
},
{
text: "Paste",
select: [this.onContextMenuItemPasteSelected, this]
}
]
)
);
Here is a JSBin Example.
You cannot use databinding for events.
But you can implement an universal event handler for your menuitems that will call the appropriate function.
Bind the menu items select event to a common event handler:
this._menu.bindAggregation("items", "/", new sap.ui.unified.MenuItem({
text: "{text}",
select: [this.onSelect, this]
}));
And implement the handler like this:
onSelect:function(oEvent){
var item = oEvent.getParameter("item");
var context = item.getBindingContext();
var fnConfig = context.getProperty("select");
fnConfig[0].bind(fnConfig[1])();
}
fnConfig is the Array of function an this-object from the model.
Using Function.bind() lets you call the function on the given this object.
Here it is on JSBin

ExtJS: Field change event fires before ViewController's init

I have a field that is stateful, and I also have it hooked up to the change event... when its value changes, I want to perform some operation. However, because it's a stateful field, the change event fires when I go back to this view, and unfortunately, the change event fires before the ViewController's init method, which means I will not be able to access my reference lookup.
In the following example, run it, change the date, and then re-run the application... you'll see a console.log that appears for the change, and then for the init. I realize I could set up the handler in the init method, but that just seems silly. I also realize I could create myField as a private var and access it that way, but that also seems silly. And yes, I could change to the select event, but that's not what I want to do. Anyone have any thoughts? Here's an example:
Ext.application({
name : 'Fiddle',
launch : function() {
Ext.state.Manager.setProvider(new Ext.state.CookieProvider());
Ext.define('MyViewController', {
extend: 'Ext.app.ViewController',
alias: 'controller.myView',
init: function() {
console.log('init fired', this.lookupReference('myField'))
},
onChange: function(value) {
console.log('onChange fired', this.lookupReference('myField'));
}
});
Ext.define('MyView', {
extend: 'Ext.container.Container',
controller: 'myView',
renderTo: Ext.getBody(),
items: [{
xtype: 'datefield',
value: new Date(),
stateful: true,
stateId: 'blahblah',
listeners:{
change: 'onChange'
}
}, {
xtype: 'datefield',
value: new Date(),
reference: 'myField'
}]
});
Ext.create('MyView');
}
});
This is because the state mixin is initialized before the controller, this is code taken directly from Ext.Component's constructor:
me.mixins.state.constructor.call(me);
me.addStateEvents('resize');
controller = me.getController();
if (controller) {
controller.init(me);
}
There is no config to change this behavior. Honestly, I've never seen someone make a form field's value stateful.
You can use the buffer config to delay event firing.
This has an advantage of setting up the event after the controller is initialised.
The solution:
listeners: {
change: {
buffer: 300,
fn: 'onChange'
}
}
An Alternative is to handle 'beforestaterestore` event of the stateful field and apply the state value only after controller is initialised.
listeners: {
beforestaterestore: function (field, state){
var controller = field.up().getController();
Ext.Function.interceptAfter(controller, 'init', function(){
field.setValue(state.value); // update
},this);
return false;
}
}

calling wrong method ExtJS

I have this piece of code :
listeners:
{
beforerender: function()
{
if (importButton == true)
{
this.menu.add(
{
text: 'Import',
iconCls: 'importIcon',
listeners:
{
click: new ifAuthorizing('import')
}
})
}
this.menu.add(
{
text: 'Consultation',
iconCls: 'searchIcon',
listeners:
{
click: menuConsultation
}
})
}
}
that is supposed to add items to a menu when some conditions are OK.
It's working, the button are well added if the conditions matches.
The problem is coming from the
listeners:
{
click: new ifAuthorizing('import')
}
This listener is supposed to be appended to the menu item, but it is triggered during the beforerender event of its parent.
function ifAuthorizing(arg) {
console.log('import')
}
The 'import' is displayed in the console logs during the beforerender event, and then if I click on the menu item that is supposed to have a click method, nothing happens.
I would like to know why.
new ifAuthorizing('import')
Here operator new tries to create an object and interpretes ifAuthorizing as a constructor. The constructor is called immediately, that's why it fires on beforeRender event. As a result you get some object which is not a copy of function ifAuthorizing, so it can't be called on menu item's event with the desired result.

How to get a Custom ExtJS Component to render some html based on a bound value

I'm trying to get a custom extjs component to render either a green-check or red-x image, based on a true/false value being bound to it.
There's a couple of other controls that previous developers have written for rendering custom labels/custom buttons that I'm trying to base my control off but I'm not having much luck.
I'd like to be able to use it in a view as follows where "recordIsValid" is the name of the property in my model. (If I remove the xtype: it just renders as true/false)
{
"xtype": "booldisplayfield",
"name": "recordIsValid"
}
Here's what I have so far, but ExtJS is pretty foreign to me.
Ext.define('MyApp.view.ux.form.BoolDisplayField', {
extend: 'Ext.Component',
alias : 'widget.booldisplayfield',
renderTpl : '<img src="{value}" />',
autoEl: 'img',
config: {
value: ''
},
initComponent: function () {
var me = this;
me.callParent(arguments);
this.renderData = {
value: this.getValue()
};
},
getValue: function () {
return this.value;
},
setValue: function (v) {
if(v){
this.value = "/Images/booltrue.png";
}else{
this.value = "/Images/boolfalse.png";
}
return this;
}
});
I'd taken most of the above from a previous custom linkbutton implementation. I was assuming that setValue would be called when the model-value for recordIsValid is bound to the control. Then based on whether that was true or false, it would override setting the value property of the control with the correct image.
And then in the initComponent, it would set the renderData value by calling getValue and that this would be injected into the renderTpl string.
Any help would be greatly appreciated.
You should use the tpl option instead of the renderTpl one. The later is intended for rendering the component structure, rather that its content. This way, you'll be able to use the update method to update the component.
You also need to call initConfig in your component's constructor for the initial state to be applied.
Finally, I advice to use applyValue instead of setValue for semantical reasons, and to keep the boolean value for getValue/setValue.
Ext.define('MyApp.view.ux.form.BoolDisplayField', {
extend: 'Ext.Component',
alias : 'widget.booldisplayfield',
tpl: '<img src="{src}" />',
config: {
// I think you should keep the true value in there
// (in order for setValue/getValue to yield the expected
// result)
value: false
},
constructor: function(config) {
// will trigger applyValue
this.initConfig(config);
this.callParent(arguments);
},
// You can do this in setValue, but since you're using
// a config option (for value), it is semantically more
// appropriate to use applyValue. setValue & getValue
// will be generated anyway.
applyValue: function(v) {
if (v) {
this.update({
src: "/Images/booltrue.png"
});
}else{
this.update({
src: "/Images/boolfalse.png"
});
}
return v;
}
});
With that, you can set your value either at creation time, or later, using setValue.
// Initial value
var c = Ext.create('MyApp.view.ux.form.BoolDisplayField', {
renderTo: Ext.getBody()
,value: false
});
// ... that you can change later
c.setValue(true);
However, you won't be able to drop this component as it is in an Ext form and have it acting as a full fledged field. That is, its value won't be set, retrieved, etc. For that, you'll have to use the Ext.form.field.Field mixin. See this other question for an extended discussion on the subject.

What is the difference between these two codes?

I am new to ExtJs, just stepped into some basic things and found that its very hard to get started as a beginner.
Below are the two ways of implementing Ext button:
Sample1:
var nextBtn = new Ext.Button({
text: 'Next >>',
handler: function() {
Ext.getDom('form_main').submit();
},
id: 'next',
renderTo: 'next'
});
Sample2:
Ext.widget('button', {
text: 'some long title of my cool button',
scale: 'large',
cls: 'my-button',
width: 100,
renderTo: 'output'
});
My guess is beacuse of the version, it has changed. Please let me know what is the difference between these two codes.
Regards,
There are many ways to instantiate a class in ExtJS.
Take this definition as example:
Ext.define ('Ext.button.Button', {
alias: 'widget.button' ,
// here other properties and methods ...
});
Then you can chose one of these ways to instantiate Ext.button.Button:
First: javascript style
var button = new Ext.button.Button ({
// props and methods
});
Second: ExtJS style with Ext.create method
var button = Ext.create ('Ext.button.Button', {
// props and methods
});
Third: ExtJS style with Ext.widget method (it uses alias property)
var button = Ext.widget ('button', {
// props and methods
});
I suggest you to use the second or the third way because they use ExtJS dynamic loader: here's the documentation

Categories

Resources