How do I attach an event handler to a panel in extJS? - events

All I want to do is handle a click on an extJS panel.
I've tried all the of suggestions on this question plus all I could find elsewhere but each of them fail in the ways described below.
What is the correct syntax to add a click event handler to a extJS panel?
[Edit: For the sake of others who may find this question later, I'll add some comments inline to make this easier to decipher --#bmoeskau]
doesn't execute handler:
var menuItem1 = new Ext.Panel({
id: 'panelStart',
title: 'Start',
html: 'This is the start page.',
cls:'menuItem',
listeners: {
click: function() {
alert('ok');
}
}
});
[Ed: click is not a Panel event]
doesn't execute handler:
var menuItem1 = new Ext.Panel({
id: 'panelStart',
title: 'Start',
html: 'This is the start page.',
cls:'menuItem',
listeners: {
render: function(c) {
c.body.on('click', function() {
alert('ok');
});
}
}
});
[Ed: The Panel is never being rendered -- add renderTo config. Next, you'll hit a null error telling you that c is not a valid variable. Do you mean menuItem1 instead?]
doesn't execute handler:
var menuItem1 = new Ext.Panel({
id: 'panelStart',
title: 'Start',
html: 'This is the start page.',
cls:'menuItem'
});
Ext.getCmp('panelStart').on('click', function() {
alert('ok');
});
[Ed: click is not a Panel event. Also, the Panel is not yet rendered, so if you switched the callback to be on the element rather than the Component you'd get a null error.]
gets error: Ext.get('panelStart') is null:
var menuItem1 = new Ext.Panel({
id: 'panelStart',
title: 'Start',
html: 'This is the start page.',
cls:'menuItem'
});
Ext.get('panelStart').on('click', function() {
alert('ok');
});
[Ed: It's not rendered, see above. Switching from getCmp to get means you are switching from referencing the Component (which does exist, but does not have a click event) to referencing the Element (which does have a click event, but is not yet rendered/valid).]
makes the panel disappear:
var menuItem1 = new Ext.Panel({
id: 'panelStart',
title: 'Start',
html: 'This is the start page.',
cls:'menuItem',
listeners: {
'render': {
fn: function() {
this.body.on('click', this.handleClick, this);
},
scope: content,
single: true
}
},
handleClick: function(e, t){
alert('ok');
}
});
[Ed: The scope being passed into the callback (content) is not a valid ref in this code (this was copy-pasted incorrectly from another sample). Since the Panel var is created as menuItem1 and the callback is intended to run in the panel's scope, scope var should be menuItem1. Also, this Panel is never rendered, see prev comments.]
gives the error "Ext.fly(menuItem1.id) is null":
var menuItem1 = new Ext.Panel({
id: 'panelStart',
title: 'Start',
html: 'This is the start page.',
cls:'menuItem'
});
Ext.fly(menuItem1.id).addListener('click', Ext.getCmp(menuItem1.id) , this);
[Ed: Panel is not rendered, see above]
...put outside Ext.onReady()...
gets error: Ext.getCmp('panelStart') is null
Ext.getCmp('panelStart').on('click', function() {
alert('okoutside');
});
[Ed: Panel is likely not rendered at the time this code is run. Also, click is not a Panel event.]
...put outside Ext.onReady()...
gets error: Ext.get('panelStart') is null
Ext.get('panelStart').on('click', function() {
alert('okoutside');
});
[Ed: See above]
...put outside Ext.onReady()...
gets error: Ext.fly('panelStart') is null
Ext.fly('panelStart').on('click', function() {
alert('okoutside');
});
[Ed: See above]
For the last three, I checked in Firebug and <div id="startPanel"> exists:
It works with JQuery:
So with JQuery I simply have to do this and it works:
$('body').delegate(('#panelStart'), 'click', function(){
alert('ok with jquery');
});
[Ed: This is not a good approach. It's simply delaying attaching of the handler until later, when the element actually shows up in the DOM (which could also be done via Ext btw, but would still not be the proper approach). I spelled out the correct approach, as linked in my answer below. The OP's attempts are all very close, but each is missing one or two key pieces.]
How can I attach a click handler like this with extJS?

try this:
var menuItem1 = new Ext.Panel({
id: 'panelStart',
title: 'Start',
html: 'This is the start page.',
cls:'menuItem',
listeners: {
afterrender: function (comp) {
var element = comp.getEl();
element.on('click', function() {
alert('ok')
});
}
}
});

[For anyone else reading this, I went through a fairly thorough explanation of this already here.]
You are missing a few key concepts:
click is not a valid Panel event, so adding a click handler on a Panel will do nothing (this is the issue in most of the code you posted above).
In this code:
var menuItem1 = new Ext.Panel({
...
});
content.body
You copy-pasted from another answer, but incorrectly. content in the other code referenced the Panel that was created -- it is a variable. In this code you created the Panel as menuItem1 but then are trying to reference it as content?
Please re-read my previous explanation about how rendering works in the other answer I gave you. You must either add a Panel to a container that renders it, or render it directly (via the renderTo config). If you do neither, the Panel will not show up.
Using jQuery's delegate function is not the proper approach with Ext JS components.

If you want to listen to events on Ext.Elements inside of a panel, you use the element property when calling addListener or passing in listeners config, instead of waiting for the afterrender event just to set the listeners
var menuItem1 = new Ext.Panel({
id: 'panelStart',
title: 'Start',
html: 'This is the start page.',
cls:'menuItem',
listeners: {
click: {
element: 'el', // could be 'body', or any other Ext.Elements
// that are available from the component
fn: function() {}
}
}
});

Or a more simple approach:
listeners: { 'expand': {fn: adminSelected }}

Related

Nothing found in Kendo UI Combobox

Is there any way to notify user that were nothing found by his search query? Something like in JIRA comboboxes. >
http://i.stack.imgur.com/rKsGa.png
There is nothing integrated, but you can easily build this yourself.
See this jsFiddle for a demo.
Basically, what's happening is:
Return from your server. if there wasn't something found, a dummy entry with a special id.
Register the Select-Event on the ComboBox.
In the event, check to see if the selected item has your special id, and if yes, cancel the event with e.preventDefault()
Code:
$('input').kendoComboBox({
dataTextField: 'text',
dataValueField: 'id',
dataSource: {
transport: {
read: function(options) {
//instead, specify ajax call!
options.success([{ id: -1, text: 'No Matches...' }]);
}
}
},
placeholder: "Select...",
select: function(e) {
var dataItem = this.dataItem(e.item.index());
if(dataItem.id === -1) {
e.preventDefault();
}
}
});

keyup event is not firing - backbone

I've got a problem with the JQuery events in one of my Backbone.Marionette Views. I have defined some click and keyboard events. But some of them are not working. For example I want that the fetch-function is called every time the keyup event is triggered.
So here is the code:
return Backbone.Marionette.ItemView.extend({
tagName: 'div',
template: Template,
events:{
'click .yes': 'yes',
'click .no': 'no',
'keyup #citySearch': 'fetch'
},
yes : function() {
this.close();
},
no : function() {
this.close();
},
initialize: function(){
this.collection = new AreaCollection();
this.collection.on('sync', this.onShow, this);
this.sourceArr = [];
},
onShow: function() {
var that = this;
$('#citySearch').typeahead({
source: that.sourceArr
});
},
fetch: function(ev) {
var that = this;
that.collection.fetch({
data : {
query : $(ev.currentTarget).val(),
type : 'cities'
},
success: function(response) {
for (var i = 0; i < response.length; i++) {
that.sourceArr.push(response.models[i].get('name'));
}
}
});
}
});
But the keyup-Event is never fired. I also tried it with the "change"-event, which is also not working. When i use "keydown" or "keypress" instead then everything is fine and the fetch-function is called correctly.
I also tried to bind the event to that input-field manually in the initialize-function with
$('input#citySearch').bind('keyup',function() {
console.log('keyup');
});
But this is also not working. It only works if I bind the event to the input field within my underscore-Template file. But that couldn't be the solution.
Does anybody have an idea what the problem could be?
I can think of only one reason for this. And that is:
input#citySearch is not part of your itemView. This means you are NOT binding your fetch function to keyup event inside the container element of your view.
If you want to bind to something outside your view, you can trigger an event to the View in which the element resides.

MVC 3 Client side validation on jQuery dialog

I am showing lots of form using jquery dialog and I wish to add in client side validation on it. I read through some examples, saying that mvc 3 already somehow support jquery client side validation, but I tried by including the necessary script, and my form like this:
#using (Html.BeginForm("CreateFood", "Home", FormMethod.Post, new { id = "formData" }))
{
#Html.ValidationSummary(false, "Please fix these errors.")
When i try to submit my form without fill in the required field, I still dint get any message. Can anyone give me more idea / explanation / examples on this??
Really needs help here... Thanks...
UPDATE (add in the script for my dialog)
$createdialog.dialog("option", "buttons", {
"Cancel": function () {
//alert('Cancel');
$createdialog.dialog('close');
},
"Submit": function () {
var frm = $('#formData');
$.ajax({
url: '/Food/CreateFood',
type: 'POST',
data: frm.serialize(),
success: $createdialog.dialog('close')
});
}
});
Once dropped, open dialog:
// Once drop, open dialog to create food
options.drop = function (event, ui) {
// Get the ContainerImgName which food dropped at
var cimg = $(this).attr('id');
// Pass in ContainerImgName to retrieve respective ContainerID
// Once success, set the container hidden field value in the FoodForm
$.ajax({
url: '/food/getcontainerid',
type: 'GET',
data: { cImg: cimg },
success: function (result) { $('#containerID').val(result); }
});
clear();
$.validator.unobtrusive.parse($createdialog);
$createdialog.dialog('open');
};
I've faced the same problem, solved with:
$(name).dialog({
autoOpen: true,
width: options.witdth,
heigth: options.height,
resizable: true,
draggable: true,
title: options.title,
modal: true,
open: function (event, ui) {
// Enable validation for unobtrusive stuffs
$(this).load(options.url, function () {
var $jQval = $.validator;
$jQval.unobtrusive.parse($(this));
});
}
});
of course you can add the validation on the close event of the dialog, depends on what you're doing, in my case the popup was just for displaying errors so I've performed validation on load of the content. (this pop up is displaying am Action result)
For every dynamically generated form you need to manually run the validator once you inject this content into the DOM as shown in this blog post using the $.validator.unobtrusive.parse function.

Sencha Touch fireEvent

I have a main panel that is comprised of sub panels and I would like to fire an event in the main panel and listen to it on the sub panel.
I can fire the event within the subpanel and everything works but i can't seem the fire the event from the main panel.
My namespace for the sub panel is "test.testCard" and I've tried to fire the event on it with no success.
Here is an example of how to do this:
Ext.setup({
onReady: function() {
var mainPanel = new Ext.Panel({
fullscreen: true,
layout: 'fit',
renderTo: Ext.getBody(),
listeners: {
'mycustomevent': function() {
alert('event fired!');
}
},
items: [
{
items: [
{
html: 'My inner panel'
},
{
xtype: 'button',
text: 'Click me!',
handler: function() {
mainPanel.fireEvent('mycustomevent', this);
}
}
]
}
]
});
}
});
You can see that I am creating a reference to mainPanel and then referencing it later in my code in the button handler, where I then call fireEvent with my custom event. Then in my mainPanel, I am adding a listener for mycustomevent.
And as previously noted, it is best to post on the Sencha Forums, as you will get a much faster response.

Why would javascript eval work in chrome, safari, but in firefox only when firebug on?

Thanks to this answer I was able to get javascript to execute when being loaded via an ExtJS AJAX call.
However, the following code does not work the same in all browsers (on mac):
chrome: works, alert pops up
safari: works, alert pops up
firefox: works, but only when Firebug is enabled, when Firebug is not enabled, the script is ignored
How can I get javascript to execute via AJAX call in Firefox without having Firebug installed?
Ext.onReady(function(){
var menuItemStart = new Ext.Panel({
id: 'panelStart',
title: 'Start',
html: 'This is the start menu item.',
cls:'menuItem'
});
var menuItemApplication = new Ext.Panel({
id: 'panelApplication',
title: 'Application',
html: 'this is the application page',
cls:'menuItem'
});
var regionMenu = new Ext.Panel({
region:'west',
split:true,
width: 210,
layout:'accordion',
layoutConfig:{
animate:true
},
items: [ menuItemStart, menuItemApplication ]
});
var regionContent = new Ext.Panel({
id: 'contentArea',
region: 'center',
padding:'10',
autoScroll: true,
html: 'this is the content'
});
new Ext.Viewport({
layout: 'border',
items: [ regionMenu, regionContent ]
});
menuItemStart.header.on('click', function() {
Ext.Ajax.request({
url: 'content/view_start.php',
success: function(objServerResponse) {
regionContent.update(objServerResponse.responseText);
}
});
});
menuItemApplication.header.on('click', function() {
Ext.Ajax.request({
url: 'content/view_application.php',
success: function(objServerResponse) {
var responseText = objServerResponse.responseText;
console.log(responseText);
regionContent.update(responseText);
var scripts, scriptsFinder=/<script[^>]*>([\s\S]+)<\/script>/gi;
while(scripts=scriptsFinder.exec(responseText)) {
eval(scripts[1]);
}
}
});
});
});
The base that is being loaded:
<script type="text/javascript">
alert('inside application view');
</script>
<?php
echo 'this is the application view at ' . date('Y-m-d h:i:s');
?>
console.log(responseText);
this line seems problematic to me. console exists only when Firebug is on, so you'll have to comment it, or do some checking whether it exists before using it.
console.log is your culprit.
Whenever you're logging in JavaScript, it's a good idea to check if console exists before calling it's functions:
if(window.console) console.log('whatever');
That way, it will only execute when the console is available.
Not sure if removing console.log fixed this for you, but please see my other answer regarding the loadScripts config also.

Resources