Telerik RadGrid OnRowSelected Events, all done event for multiple selection? - telerik

I have a RadGrid with multiple select enabled:
<telerik:RadGrid runat="server" ID="RadGrid1" AutoGenerateColumns="false" AllowMultiRowSelection="true">
<MasterTableView TableLayout="Fixed">
<Columns>
<telerik:GridBoundColumn DataField="Dialog" HeaderText="Dialog" DataType="System.String" />
</Columns>
</MasterTableView>
<ClientSettings EnableRowHoverStyle="true">
<Selecting AllowRowSelect="True" />
<ClientEvents OnRowSelected="RowSelected"/>
</ClientSettings>
</telerik:RadGrid>
And the OnRowSelected event triggers for each row selected. When selecting 10 rows, the event gets fired 10 times. Simple enough.
My question is what event can I listen to to know when all the rows that are going to be selected are selected (as a result of the multiple selection)? I need to make a post request with the ids of the selected rows and I don't think it's a good idea to let 10 post request be made. I can query the grid to get the selected rows, I just need to know when to do it; ideally something that doesn't involve timeouts. There must an event for this that I'm overlooking.

Got something working with timeouts:
var rowSelectedTimeout;
function RowSelected(rowObject) {
if (window.rowSelectedTimeout) {
// If selecting multiple rows, clear the previous row's rowSelectedTimeout
window.clearTimeout(window.rowSelectedTimeout);
}
rowSelectedTimeout = window.setTimeout(function () {
window.rowSelectedTimeout = null;
alert('rows selected');
}, 10);
}

The trick here is really how to figure out when the user has "stopped" selecting. If the multiple selection is done via a shift+click then sure, you have a lot of items to go through, but what if you have the same number of items (10) and the user ctrl+clicks each one of them? It can very easily become a bit over-complicated. There unfortunately isn't an event in the RadGrid that you can subscribe to that triggers after a multiple select action has finished selecting all rows.
Your best option here would probably be to have an external button or something similar that would trigger this post, and then use the SelectedItems collection of the RadGrid since this would then allow for a more batch approach instead of posts occurring for every row.

Related

Rich Picklist + A4j Support + onlistchange

There are a weird behavior happening when I use rich picklist component attached to an a4j support onlistchange event.
If I have "n" selected items into picklist component, the server will try to populate it "n" times (running gruposDeTributosQuery.resultListOrdered() "n" times!!!)!
This causes a hard delay, because the query used to populate is a little bit slower...
Above is my code:
<rich:pickList id="picklisttributos" value="#{criarEstudo.tributosDoAssuntoList}"
label="Tributos" >
<s:selectItems var="_tributos" value="#{gruposDeTributosQuery.resultListOrdered}"
label="#{_tributos.nome} | #{_tributos.id}" />
<s:convertEntity />
<a4j:support event="onlistchange" process="picklistOF" reRender="picklistOF" />
</rich:pickList>
Bizarre.
New discover...
The problem is gruposDeTributosQuery.resultListOrdered!
public List<Tributo> getResultListOrdered() {
this.setOrder("nome");
//ArrayList<Tributo> lista = new ArrayList<Tributo>(
// this.getResultList());
return this.getResultList();
}
If I use direclty resultList this bahavior doesn´t happen!

Consuming GWT click events

Due to performance reasons, I have a custom made table. The table consists of columns that are created as HTML DIVs, and the row is wrapped into an AbsolutePanel. The position of the column(s) and the row(s) is absolute and calculated on the render loop. The table is added into a ScrollPanel and only renders the visible portion of the rows, and adds rows when the user scrolls.
Customer requirement is to open a PopupPanel to show details about the row when the row is clicked. I've added a ClickHandler to the row panel by sinking the click event into it, which works fine.
The problem is, if I add e.g. a standard link or any clickable item into one of the cells in the table, clicking on the said item(s) results in also the row click handler firing, which I want to somehow prevent. The source of the event is the row Element, not the link/icon/whatever that was clicked.
Any help solving this (perhaps a completely different approach ?) is much appreciated.
I would use gwtquery because of its simplicity and performance.
I don't know the final dom renderized by your app, but if we suppose you have something like this:
<div id="column1">
<div id="row1_1" class="my_row" product_id="whatever"> content </div>
...
</div>
Your code could be something like this:
import static com.google.gwt.query.client.GQuery.*;
$(".my_row").click(new Function(){
public void f() {
// The gquery instance of the row clicked
GQuery thisRow = $(this);
// Use gquery methods to get some info of your row
String thisId = thisRow.id();
String productId = thisRow.attr("product_id");
Element thisElement = thisRow.get(0);
// do Something with your row
...
}
});

Exclude an id from update

Can I exclude a specific id from update=":myComponent"?
I have a larger page (with several tables, input fields and so on) which is wrapped in a <p:panel id="outerPanel">. Most of the time, I just execute update=":outerPanel", which works quite fine. But now I'm facing a problem that I have to update the page except for ONE table.
How can I exclude that table (or any component in general) from an update process?
If the ID not to refresh can be identified by some logic (i.e.:
if(myVar==1) { idToExclue = 'id1';}
else // ... etc
Then you can try building a JSF call using the jsf.util.chain: (Note this uses Mojarra JSF impl.)
function myJsfSubmit(callerElement) {
var myIdsToSubmit = 'main-form:id-to-refresh-1 main-form:id-to-refresh-2';
// put your logic to exclude the desired ID here
// ...
// then
jsf.util.chain(callerElement,null,'mojarra.ab(this,event,\'action\',
\'main-form:id_to-submit\',\'+ myIdsToSubmit +\')');
return false;
}
And use that above function on the onClick() or onSubmit() of your form or component:
<h:commandButton onclick="myJsfSubmit(this)" />
No, I think that is not possible from the facelet. On the server side you could manipulate the ajax request, but I don't think that is what you want.
Maybe your view allows to wrap some h:panelGroup around the parts to update.

Define a dataObject and pass it to the next view in Flashbuilder

I am trying to convert my java-app for Android to a Flex/Air app with Flashbuilder.
I am nearly there (thanks to sample code on Adobe) but have problems with passing data between views.
I have 3 views. The first have a list of items and an event handler that choose one of this list items and pass this to the next view:
<s:List id="list" left="0" top="0" bottom="0" width="768"
change="navigator.pushView(Intro, list.selectedItem)" dataProvide "{data}">
This works fine and I can use the values stored in {data}.
e.g.
<s:Label text="{data.title}"/>
Now I want to pass the same data on a button click to the next view, spelaView.
Something like this:
<s:Button id="backBtn" label="Spela"
click="navigator.pushView(SpelaSaga, dataObj)" />
Sorry to say, I do not know how I transform the data-object {data} (with three items: data.title, data.description, data.audio) to dataObj in a form that the next view are abel to use.
Hope someone is kind enough to give me some help on this.
I just solved it.
Defined this function and could then get the data in the next view
protected function spelaSaga():void{
var dataObj:Object=
{
titel:data.title bild:data.description, audio:data.audio
};
navigator.pushView(views.SpelaSaga, dataObj);
}

Browser Memory Usage Comparison: inline onClick vs. using JQuery .bind()

I have ~400 elements on a page that have click events tied to them (4 different types of buttons with 100 instances of each, each type's click events performing the same function but with different parameters).
I need to minimize any impacts on performance that this may have. What kind of performance hit am I taking (memory etc) by binding click events to each of these individually (using JQuery's bind())? Would it be more efficient to have an inline onclick calling the function on each button instead?
Edit for clarification :):
I actually have a table (generated using JQGrid) and each row has data columns followed by 4 icon 'button' columns- delete & three other business functions that make AJAX calls back to the server:
|id|description|__more data_|_X__|_+__|____|____|
-------------------------------------------------
| 1|___data____|____data____|icon|icon|icon|icon|
| 2|___data____|____data____|icon|icon|icon|icon|
| 3|___data____|____data____|icon|icon|icon|icon|
| 4|___data____|____data____|icon|icon|icon|icon|
I am using JQGrid's custom formatter (http://www.trirand.com/jqgridwsiki/doku.php?id=wiki:custom_formatter) to build the icon 'buttons' in each row (I cannot retrieve button HTML from server).
It is here in my custom formatter function that I can easily just build the icon HTML and code in an inline onclick calling the appropriate functions with the appropriate parameters (data from other columns in that row). I use the data in the row columns as parameters for my functions.
function removeFormatter(cellvalue, options, rowObject) {
return "<img src='img/favoritesAdd.gif' onclick='remove(\"" + options.rowId + "\")' title='Remove' style='cursor:pointer' />";
}
So, I can think of two options:
1) inline onclick as I explained above
--or--
2) delegate() (as mentioned in below answers (thank you so much!))
Build the icon image (each icon type has its own class name) using the custom formatter.Set the icon's data() to its parameters in the afterInsertRow JQGrid event. Apply the delegate() handler to buttons of specific classes (as #KenRedler said below)
> $('#container').delegate('.your_buttons','click',function(e){
> e.preventDefault();
> var your_param = $(this).data('something'); // store your params in data, perhaps
> do_something_with( your_param );
> }); //(code snippet via #KenRedler)
I'm not sure how browser-intensive option #2 is I guess...but I do like keeping the Javascript away from my DOM elements :)
Because you need not only a general solution with some container objects, but the solution for jqGrid I can suggest you one more way.
The problem is that jqGrid make already some onClick bindings. So you will not spend more resources if you just use existing in jqGrid event handler. Two event handler can be useful for you: onCellSelect and beforeSelectRow. To have mostly close behavior to what you currently have I suggest you to use beforeSelectRow event. It's advantage is that if the user will click on one from your custom buttons the row selection can stay unchanged. With the onCellSelect the row will be first selected and then the onCellSelect event handler called.
You can define the columns with buttons like following
{ name: 'add', width: 18, sortable: false, search: false,
formatter:function(){
return "<span class='ui-icon ui-icon-plus'></span>"
}}
In the code above I do use custom formatter of jqGrid, but without any event binding. The code of
beforeSelectRow: function (rowid, e) {
var iCol = $.jgrid.getCellIndex(e.target);
if (iCol >= firstButtonColumnIndex) {
alert("rowid="+rowid+"\nButton name: "+buttonNames[iCol]);
}
// prevent row selection if one click on the button
return (iCol >= firstButtonColumnIndex)? false: true;
}
where firstButtonColumnIndex = 8 and buttonNames = {8:'Add',9:'Edit',10:'Remove',11:'Details'}. In your code you can replace the alert to the corresponding function call.
If you want select the row always on the button click you can simplify the code till the following
onCellSelect: function (rowid,iCol/*,cellcontent,e*/) {
if (iCol >= firstButtonColumnIndex) {
alert("rowid="+rowid+"\nButton name: "+buttonNames[iCol]);
}
}
In the way you use one existing click event handler bound to the whole table (see the source code) and just say jqGrid which handle you want to use.
I recommend you additionally always use gridview:true which speed up the building of jqGrid, but which can not be used if you use afterInsertRow function which you considered to use as an option.
You can see the demo here.
UPDATED: One more option which you have is to use formatter:'actions' see the demo prepared for the answer. If you look at the code of the 'actions' formatter is work mostly like your current code if you look at it from the event binding side.
UPDATED 2: The updated version of the code you can see here.
You should use the .delegate() method to bind a single click handler for all elements ,through jQuery, to a parent element of all buttons.
For the different parameters you could use data- attributes to each element, and retrieve them with the .data() method.
Have you considered using delegate()? You'd have one handler on a container element rather than hundreds. Something like this:
$('#container').delegate('.your_buttons','click',function(e){
e.preventDefault();
var your_param = $(this).data('something'); // store your params in data, perhaps
do_something_with( your_param );
});
Assuming a general layout like this:
<div id="container">
<!--- stuff here --->
<a class="your_buttons" href="#" data-something="foo">Alpha</a>
<a class="your_buttons" href="#" data-something="bar">Beta</a>
<a class="your_buttons" href="#" data-something="baz">Gamma</a>
<a class="something-else" href="#" data-something="baz">Omega</a>
<!--- hundreds more --->
</div>

Resources