How call function in renderer html with Ext.js 4.2 - extjs

Code is:
Ext.define("Myapp", {
extend: '',
config: {},
initComponent: function () {},
getGrid: function () {
Ext.create("Ext.grid.Panel", {
...
columns: [
{
header: 'xx',
renderer: function (value) {
return '<a onclick=''>text</a>';
}
}
]
});
},
test: function(){
alert(1);
},
});
In the above code, I want call test function in onclick event. I tried Myapp.test(), But it didn't work.
Is there any way to do this?

You have to add a listener to the cell and check inside the listener function if the user clicked the 'a' tag.
A good example has been made by Tyr
Take a look at this fiddle
ExtJS components working like simple object literals, so you can extend them with anything you want. In this case, i added the property "active" which can be checked in the beforeEdit listener.

Related

ExtJS cannot override methods statics

I wanted to extend Ext.Action class due to add my own methods, but I've encouraged problem Cannot override method statics on Core.app.Action instance.
I know that is a problem connected to overriding constructor. But don't know how to solve it other way.
Here is code of my component
Ext.define('Core.app.Action', {
extend: 'Ext.Action',
iconCls: 'icon-add',
currentData: undefined,
constructor: function(config){
config = Ext.applyIf(config || {}, this);
this.callParent([config])
},
handler: function (widget, event) {
Ext.Msg.alert("Name:", this.currentData.data.company)
},
getActionId: function () {
return this.actionId
},
setCurrentData: function (data) {
this.currentData = data
this.disable()
if (data.data.actions) {
this.currentData.data.actions.forEach(action => {
if (action === this.actionId) this.enable()
})
}
}
})
And there is a way how I create instance of mentioned class
Ext.create('Core.app.Action', {
actionId: 'D',
text: "Action D",
})
ExtJS is not throwing errors when I remove constructor from my class, but I can't also use methods such as handler or setCurrentData.
I've also tried overriding the component, but failed.
Answers in solution below weren't helpful in this case.
Reusable Action in Ext JS MVC

Ext Js : Hide all element or items inside container

I have multiple container with field. Basically when container is hidden all field's are not visible. but I was checked "hidden" property or "isHidden()" method of field. I am getting as false.
I want make it as true when container is hidden and false when it is visible.
How to make field are hidden and show by using override
Your question is very hard to read. (Poor English) But if I understand correctly you hide a container with fields. If you then check the isHidden() of one of the fields, it returns false. That is standard Ext behavior. The container is hidden not the fields. What you can do is query down and set the fields hidden.
E.g.
Ext.define('MyCustomContainer', {
extend: 'Ext.Container',
hide: function () {
var me = this;
Ext.each(me.query('field'), function (field) {
field.hide();
});
me.callParent(arguments);
},
show: function () {
var me = this;
Ext.each(me.query('field'), function (field) {
field.show();
});
me.callParent(arguments);
}
});
You ask:
I don't want to create custom component. Can I do same thing by using override?
Yes you can!
I hope you don't have an Ext.Container as type it's kind of dirty overriding it for ALL containers, but it will work... => it would be better to replace Ext.Container with the specific type of your container...
Ext.define('YourApp.override.Container', {
override: 'Ext.Container',
hide: function () {
var me = this;
Ext.each(me.query('field'), function (field) {
field.hide();
});
me.callParent(arguments);
},
show: function () {
var me = this;
Ext.each(me.query('field'), function (field) {
field.show();
});
me.callParent(arguments);
}
});

How can I reference the backbone view from a kendo ui treeview event handler?

I'm using the Kendo UI treeview with Backbone.js along with Marionette.js The treeview is inside a view component and works well execpt for one area. To start, I initialize the treeview when I call the view render method
View.myPanel = Marionette.ItemView.extend(
render: function () {
this.treeview = this.$el.find("#treeview").kendoTreeView({
dataSource: this.hierarchicalDataSource,
dataTextField: ["item"],
dragAndDrop: true,
loadOnDemand: false,
drop: this.onDrop
}).data("kendoTreeView"),
this.treeview.expand(".k-item");
},
onDrop: function (e) {
...
code to create model goes here ......
...
this.saveItem(localModel, false);
}
}
The problem I have is that when I try and call this.saveItem, I have no reference to "this". . Normally "this" would be the view itself.
Instead "this" refers to the treeview object. I see the event object inside the drop handler but no reference to the view.
I tried to extend the treeview with BackBone.Events but that causes me to lose the drag and drop functionality. I also tried passing the view object as a parameter to the drop handler but that replaces the event parameter in the onDrop function.
Underscore's bind and bindAll methods may hep you.
View.myPanel = Marionette.ItemView.extend(
initialize: function() {
_.bindAll(this,'onDrop');
},
render: function () {
this.treeview = this.$el.find("#treeview").kendoTreeView({
dataSource: this.hierarchicalDataSource,
dataTextField: ["item"],
dragAndDrop: true,
loadOnDemand: false,
drop: this.onDrop
}).data("kendoTreeView"),
this.treeview.expand(".k-item");
},
onDrop: function (e) {
...
code to create model goes here ......
...
this.saveItem(localModel, false);
}
}
To know more see _.bind
Here is sample EXAMPLE posted it there on underscore site
var buttonView = {
label : 'underscore',
onClick: function(){ alert('clicked: ' + this.label); },
onHover: function(){ console.log('hovering: ' + this.label); }
};
_.bindAll(buttonView, 'onClick', 'onHover');
// When the button is clicked, this.label will have the correct value.
jQuery('#underscore_button').bind('click', buttonView.onClick);
Here this in callback function buttonView.onClick points correctly to buttonViewand not to the bound DOM element (which is usual).
I know very little about backbone or marionette, but it seems like you can use the ItemView variable you created:
View.myPanel.saveItem(localModel, false);
Update
Have you tried a self-executing function that passes the View object in as a local variable and returns the ItemView object:
View.myPanel = (function(view) {
return Marionette.ItemView.extend(
render: function () {
this.treeview = this.$el.find("#treeview").kendoTreeView({
dataSource: this.hierarchicalDataSource,
dataTextField: ["item"],
dragAndDrop: true,
loadOnDemand: false,
drop: this.onDrop
}).data("kendoTreeView"),
this.treeview.expand(".k-item");
},
onDrop: function (e) {
...
code to create model goes here ......
...
view.myPanel.saveItem(localModel, false);
}
);
})(View);
Kendo UI explicitly sets the context for event handlers to the widget that triggers the event; use a closure to keep access to your view:
render: function () {
var that = this;
this.treeview = this.$el.find("#treeview").kendoTreeView({
dataSource: this.hierarchicalDataSource,
dataTextField: ["item"],
dragAndDrop: true,
loadOnDemand: false,
drop: function (e) {
that.onDrop(e)
}
}).data("kendoTreeView"),
this.treeview.expand(".k-item");
}

In Extjs 4, why is my firing of custom event om image el not working?

Update 2: This confirms the cpuchartclicked event is being fired, because the alert('hello') works. What I need is to be able to respond to that event in my controller.
items: [
{
xtype: 'image',
itemId: 'graphiteChartCPU',
src: '',
listeners:{
'afterrender':function (comp) {
comp.getEl().on('click', function (el) {
this.fireEvent('cpuchartclicked');
}, this);
},
'cpuchartclicked':function () {
alert('hello');
}
}
}
]
Update: With the following, I am setting the scope for the on click handler. fireEvent() seems to be working now, but still not hearing the event in controller.
items: [
{
xtype: 'image',
itemId: 'graphiteChartCPU',
src: '',
listeners:{
'afterrender':function (comp) {
comp.getEl().on('click', function (el) {
alert('on click handler');
this.fireEvent('cpuchartclicked');
}, this);
}
}
}
]
// Listen Application Event
me.application.on({
cpuchartclicked: me.onChartClicked,
scope: me
});
I'm trying to fire a custom event on an image el so when the image is clicked the controller hears the event.
But I get an error cmp.fireEvent() is not a function?
items: [{
xtype: 'image',
itemId: 'graphiteChartCPU',
src: '',
listeners:{
'afterrender':function (comp) {
comp.getEl().on('click', function (el) {
el.fireEvent('cpuchartclicked');
});
}
}
}]
me.application.on({
cpuchartclicked: this.onChartClicked,
scope: this
});
You are confusing Components and Elements. The afterrender event listener is set on the Image Component, and receives the Component itself as the first argument (that you named el instead, incorrectly).
Then, in the afterrender listener, you retrieve the main DOM element for that Component, which happens to be an <img> tag, and set click listener on the element object, which is an instance of Ext.dom.Element.
The click event signature is not what you expect; the first argument is an Ext.util.Event object that does not have a fireEvent method. Hence the error.
I would suggest looking up event signatures in the docs before using them. Also try to add a debugger statement before the line that blows up, and see what variables are passed in and what is going on. Using Chrome or Firefox debugger can be immensely helpful here.
Solved it, though I am wondering if this is the best way to do it.
I fire the custom event via the image, and then listen for that event on the image as well in the controller.
items: [
{
xtype: 'image',
itemId: 'graphiteChartCPU',
src: '',
listeners:{
'afterrender':function (comp) {
comp.getEl().on('click', function (el) {
this.fireEvent('cpuchartclicked');
}, this);
}
}
}
]
'myContainer image':
{
'cpuchartclicked': me.onChartClicked
}
you must bind to the image element like that:
{
xtype: 'image',
itemId: 'graphiteChartCPU',
src: '',
listeners: {
el: {
click: function() {
console.log("Click");
}
}
}
}
it solve my problem in ext5

How to call an action of controller from grids action column

I have an action column in my grid which is needed to perform lots of non-trivial operations after click on it. I don't want to use the handler method only to avoid duplicity in my code. I want to handle the click event from the controller method which can be called from more sides.
Here is my definition of action column:
{
header: translator.translate('actions'),
xtype: 'actioncolumn',
width: 50,
items:[{
id : 'detailContactPerson',
icon : '/resources/images/pencil.png',
tooltip: translator.translate('show_detail')
}]
},
But now I don't know how to write the Component query definition to set up listener.
init: function() {
this.control({
'detailContactPerson': {
click: function(obj) {
var contactPerson = obj.up('container').contactPerson;
this.detail(contactPerson);
}
},
Second way I've tried is to call the method of controller directly from handler method. It looks like this:
{
header: translator.translate('actions'),
xtype: 'actioncolumn',
width: 50,
items:[{
id : 'detailContactPerson',
icon : '/resources/images/pencil.png',
handler: function(contactPerson){
Project.controller.contactPerson.detail(contactPerson);
},
tooltip: translator.translate('show_detail')
}
But unfortunately it isn't supported way to call controller method (No method exception raised).
Could someone help me to construct working Component query, or show some example how to call controller method from outside?
try actioncolumn#detailContactPerson
or you can listene to actioncolumn 's click event
see this: http://www.sencha.com/forum/showthread.php?131299-FIXED-EXTJSIV-1767-B3-ActionColumn-bug-and-issues
init: function() {
this.control({
'contact button[action=add]':{
click: this.addRecord
},
'contact button[action=delete]':{
click: function(){this.deleteRecord()}
},
'contact actioncolumn':{
click: this.onAction
}
});
},
onAction: function(view,cell,row,col,e){
//console.log(this.getActioncolumn(),arguments, e.getTarget())
var m = e.getTarget().className.match(/\bicon-(\w+)\b/)
if(m){
//选择该列
this.getGrid().getView().getSelectionModel().select(row,false)
switch(m[1]){
case 'edit':
this.getGrid().getPlugin('rowediting').startEdit({colIdx:col,rowIdx:row})
break;
case 'delete':
var record = this.getGrid().store.getAt(row)
this.deleteRecord([record])
break;
}
}
}
BTW.I prefer to use these to instead of AcionColumn
Ext.ux.grid.column.ActionButtonColumn
Ext.ux.grid.RowActions
I have a better way: add new events on your view where are presents the actioncolumns:
{
xtype:'actioncolumn',
align:'center',
items:[
{
tooltip:'info',
handler:function (grid, rowIndex, colIndex) {
var rec = grid.getStore().getAt(rowIndex);
//this is the view now
this.fireEvent('edit', this, rec);
},
scope:me
},
....
me.callParent(arguments);
me.addEvents('edit')
then on your controller:
.....
this.control({
'cmp_elenco':{
'edit':function(view,record){//your operations here}
....
I too wanted to handle logic for the actioncolumn in a controller. I am not certain if this is better or worse than simply using one of the other plugins mentioned, however this is how I was able to get it to work.
Things to note:
the id config property in the items array of the actioncolumn
does nothing at all, the icons will still receive a generated id
the items are NOT components, they are simply img elements
you can add an id to the actioncolumn itself to target a specific instance of actioncolumn
each icon (or item in the actioncolumn) is given a class of x-action-col-# where # is an index beginning with 0.
For example, in the columns definition of my grid I have:
header: 'ACTION',
xtype: 'actioncolumn',
id: 'myActionId',
width: 50,
items: [{
icon: 'resources/icons/doThisIcon.png',
tooltip: 'Do THIS'
},{
icon: 'resources/icons/doThatIcon.png',
tooltip: 'Do THAT'
}
]
and in the controller:
init: function(){
this.control({
'actioncolumn#myActionId': {
click: function(grid,cell,row,col,e){
var rec = grid.getStore().getAt(row);
var action = e.target.getAttribute('class');
if (action.indexOf("x-action-col-0") != -1) {
console.log('You chose to do THIS to ' + rec.get('id')); //where id is the name of a dataIndex
}
else if (action.indexOf("x-action-col-1") != -1) {
console.log('You chose to do THAT to ' + rec.get('id'));
}
}
}
}
Using this method, you can place all logic for any given action column in the controller.
Here is a way to avoid declaring the handler (no need to use addEvents, ExtJS 4.1.1) :
Ext.grid.column.Action override :
Ext.grid.column.Action.override({
constructor: function () {
this.callParent(arguments);
Ext.each(this.items, function () {
var handler;
if (this.action) {
handler = this.handler; // save configured handler
this.handler = function (view, rowIdx, colIdx, item, e, record) {
view.up('grid').fireEvent(item.action, record);
handler && handler.apply(this, arguments);
};
}
});
}
});
Action column config :
{
xtype: 'actioncolumn',
items: [{
icon: 'edit.png',
action: 'edit'
}]
}
Controller :
this.control({
'grid': {
edit: function (record) {}
}
});
You can also follow this example http://onephuong.wordpress.com/2011/09/15/data-grid-action-column-in-extjs-4/.

Resources