EXT JS - adding a listener on any element added to a container - extjs

HI,
I have a ExtJS parent 'container' type, whereas i need to add a 'contextmenu' listener to any element that is added to this parent container, via Drag/Drop.
Can someone guide me as to the best way to do this?
I have tried this below but can't get the function to fire.
myContainer.on('added', function(obj1,obj2,index){
alert('added');
});
this may not be the 'best practice' to do it this way anyway...?
thanks for the help !

You're using the wrong event... The added event gets fired when (using your example) myContainer is added to some other container. What you'll need is the add event that fires, when an item is added to myContainer:
myContainer.on('add', function(container, component, index) {
component.on('contextmenu', function() {
});
});

Related

How to pass instance of MessageBox from grid to controller?

I need to pass instance of my MessageBox so I can close it inside the success function of my Ajax request which is inside the controller. This way, i won't need to add refs for controller to look for my messagebox.
this.win = Ext.create('Ext.window.MessageBox',{
buttonAlign: 'left'
,buttons:[
{
text: "This Only"
,scope:this
,handler: function() {
this.fireEvent("eventName",{type:"all", // i presume my messagebox is simply passed in here, I just dont know HOW });
}
}
]
thank you in advance!
You'll need to pass a reference in the event being fired, e.g.
this.fireEvent("eventName",{type:"all", this.up('window') });
You pass this.up('window') as this refers to the button being clicked, you need to traverse the DOM upwards to get the parent window. Then in your event, you have access to the window instance as the second argument in the event- and can do with it what you will (.e.g window.close();)
n.b. off the top of my head I cant remember if you may be better off using this.up('messagebox')

ExtJS4 - how to get parent grid on selectionchange?

I have little experience with ExtJS3 and now starting with version 4.
In my controller, I have this:
init: function ()
{
this.control({
"userlist":
{
selectionchange: function (view, selected, opts)
{
//get to grid??
}
}
});
}
How can I access the grid that this event happened on, without using id's?
I want to enable/disable buttons on the grid toolbar (tbar) if there are items selected, but I don't want to give anything id's (not the bar, not the individual buttons)
EDIT: the solution was to use the refs property in the controller:
refs:
[
{
ref: "list",
selector: "userlist"
}
],
selectionchange: this.activateTbButtons
activateTbButtons: function (selected, opts)
{
if (selected.selected.length == 1)
{
var tb = this.getList().query("toolbar");
}
}
Just found out that you can use the attribute view, and views under Ext.selection.Model.
This can be useful in cases when you let's say open multiple instances of your objects.
So, to access the grid in your example:
selectionchange: function (view, selected, opts) {
//get to grid??
var grid = view.view.ownerCt;
}
Having the same problem and found the previous answers missing some points. In short, I recommend:
selectionchange: function (selModel, selected, eOpts) {
var grid = selModel.view.ownerCt;
}
This was already proposed by Adezj although it referred to the selectionchange event that has the view as the first argument, and is not applicable to ExtJS 4.0.7+. (Don't think that selectionchange ever had the view as an argument?)
Note that this might not be officially supported by ExtJS since the view property of the selection model is not mentioned in the API docs at all.
Another approach is to use Ext.ComponentQuery.query(...) or defining refs in the controller, as proposed by Arun V, which is basically just a handy wrapper for Ext.ComponentQuery.query(). This works fine if you only have individual instances of the grid class but you need to take care in case you have multiple instances of the same grid class. Simply doing Ext.ComponentQuery.query('xtype-of-your-grid') will return all instances of your grid and you will have lots of fun finding out in which one the user has selected something.
So, in general, I would highly recommend to always work your way up from the component or object that fired the event to be sure you are in the right branch of the component hierarchy unless you are sure you will never have more than one instance of that class you write a controller for.
EDIT
I took a look at the docs for the selectionChange event:
selectionchange( Ext.selection.Model this, Ext.data.Model[] selected, Object eOpts )
The view is not being passed in to the selectionchange handler. An easy way to handle this is to either use Ext.getCmp() or use refs as seen in the docs for Ext.app.Controller:
http://docs.sencha.com/ext-js/4-0/#!/api/Ext.app.Controller
//get grid
var grid = selectionModel.view.ownerCt.ownerCt;

Backbone per instance event bindings

I have a view that creates a sub-view per item in the list. Generically let's call them ListView and ListItemView. I have attached an event as follows on ListItemView:
events: {
"click .remove": "removeItem"
}
I have template-generated html for ListItemView that is approximately like the following (swapped lb/rb for {/} so you can see the "illegal" html):
{div class="entry" data-id="this_list_item_id"}
SOME STUFF HERE
{div class="meta"}
{a class="remove" href="javascript:;"}[x]{/a}
{/div}
{/div}
The problem is, when the click on any of the [x]'s, ALL of the ListItemViews trigger their removeItem function. If I have it go off of this model's id, then I drop all the items on the page. If I have it go off the clicked item's parent's parent element to grab the data-id, I get a delete for EACH ListItemView instance. Is there a way to create an instance-specific event that would only trigger a single removeItem?
If I have ListView hold a single instance of ListItemView and reassign the ListItem model and render for each item in the list it works. I only end up with one action (removeItem) being triggered. The problem is, I have to find the click target's parent's parent to find the data-id attr. Personally, I think the below snippet is rather ugly and want a better way.
var that = $($(el.target).parent()).parent();
Any help anyone gives will be greatly appreciated.
It seems like your events hash is on your ListView.
If it is, then you can move the events hash to ListItemView and your removeItem function can be the following
removeItem: function() {
this.model.collection.remove(this.model);
}
If this isn't the case, can you provide your ListView and ListItemView code so I can look at it.
A wild guess but possible; check that your rendered html is valid. It might be possible that the dom is getting in a tiz due to malformed html

Can you trigger action/events in Sencha Touch from html elements?

I have a Sencha tab panel, each tab loads html content via ajax. One of the components is a post/list that visitors can use to drill down once more to read the entire post.
My question is, can I somehow trigger a view switch through the html? Or should I be loading the post data via JSON, and styling a listpanel in Sencha?
Thank you!
You can add listeners to elements within your HTML which would then be able to trigger the view switch. For example,
// simple HTML snippet contained in Panel
<a class="my-link">Click Me!</a>
// on after load/after render (need to ensure that the elements exists in the page!)
// get reference to the containing panel (tab)
var panel = this.items.get(0);
panel.getEl().on({
tap: function(e){
console.log('i was clicked!');
},
delegate: 'a.my-link'
});
The delegate option allows you to pass a selector that means the event will only fire when an element matching that selector is in the event target's chain (i.e. returns something in an e.getTarget(delegate) call).
EDIT
You can access attributes of the tapped element using either the DOM node tapped or use Ext.fly to wrap an Ext.Element instance around it and use the helper methods.
console.log(e.getTarget('a.my-link')); // logs DOM node
console.log(Ext.fly(e.getTarget('a.my-link'))); // logs Ext.Element wrapping DOM node
console.log(e.getTarget('a.my-link').href); // logs href via DOM node property
console.log(Ext.fly(e.getTarget('a.my-link')).getAttribute('href')); // logs href via Ext.Element getAttribute() method
Depending on the nesting you may be able to remove the selector from the getTarget() call (i.e. if you're always tapping on the element your listening on then you can remove it, but if there are children in the element you're listening on then you will need it. In the second case the 'target' will be the child that the event bubbled from so the href etc will be wrong. If that makes sense... :) )
The solution for 2.2.1:
initialize: function() {
this.element.on({
tap: <function>,
delegate: <query_expression>
});
this.callParent(arguments);
}
<query_expression> can be anything fitting in to Ext.query() too.

Adding listener to an editor grid panel

There is an Editor grid panel.
I am trying to add a listener to the cell click event. I have tried to do it in different ways:
gridPanel.addListener('cellclick',myfunction);
inside the grid:
listeners: {
cellclick: myfunction
}
I have tried to do it in the selectionModel object.
None of them worked.
Where can be the problem?
If you can't add the listener as a config parameter, it's probably because you're having problems with the callback function not being in scope, similar to this:
> var obj = { greetMe: this.sayHi, sayHi: function(){ console.log('hi'); }};
undefined
> obj.greetMe();
TypeError: Property 'greetMe' of object #<Object> is not a function
> obj.greetMe
undefined
In the first line, this was still referring to the global (read: window) object at the time the object was defined. So this.sayHi === window.sayHi === undefined. The same thing happens when you define Ext config objects. Try defining the callback inline:
> var obj = { greetMe: function(){ console.log('hi'); }};
undefined
> obj.greetMe()
hi
Other options:
Define the function in a wider scope, outside of your class
Attach the listener within the constructor or within initComponent, by which time your class methods should be instantiated
Attach the listener sometime later
You have to use cellmousedown of grid panel or cell selectionchange of selection model.
addListener worked. I had some syntax error.
Still adding the listener as a parameter doesn't work
For row selection I put it on the selection model and for double clicks on the grid directly. This works well but I must warn you if you don't prevent the default event you will get horrible memory consumption.
Ext.onReady(function(){
requestGrid.getSelectionModel().on('rowselect', handleRowSelect);
requestGrid.on('rowdblclick', handleDoubleClick);
}
It would help if I read :) My solution is for row selection not cell selection but it might very well work.

Resources