Removing row not reflected in datatable after update - ajax

My delete button will delete an entry from the database but not from the actual datatable in primefaces. Until you refresh it with either a filter change or F5/new session.
I've looked at various other answers to this question and am coming up blank. I've tried messing with the update and using oncomplete="PF('datalistWidget').filter()" among other things.
Using primefaces 6.0 and glassfish 4.1. Any help appreciated.
I roughly followed the tutorial at http://www.oracle.com/technetwork/articles/java/java-primefaces-2191907.html and then added on my own customization. The managed beans and facade etc... are all similar to that tutorial with the database created classes. I have not seen any errors in the glassfish log.
DataTable
<p:dataTable id="datalist" value="#{chemicalChemicalController.items}" var="item"
selectionMode="single" selection="#{chemicalChemicalController.selected}"
paginator="true"
editable ="true"
rowKey="#{item.chemKey}"
rows="10"
widgetVar="datalistWidget"
rowsPerPageTemplate="10,20,30,40,50"
filteredValue="#{chemicalChemicalController.itemsFiltered}"
>
Delete Command Button
<p:commandButton id="deleteButton" icon="ui-icon-trash"
value="#{bundle.Delete}" actionListener="#{chemicalChemicalController.destroy}"
update=":growl, datalist" disabled="#{empty chemicalChemicalController.selected}"/>
Controller Delete Command
public void destroy() {
persist(PersistAction.DELETE, ResourceBundle.getBundle("/Bundle").getString("ChemicalChemicalDeleted"));
if (!JsfUtil.isValidationFailed()) {
selected = null; // Remove selection
items = null; // Invalidate list of items to trigger re-query.
}
}

destroy method with deleting from items object.
public void destroy(SelectEvent event) {
persist(PersistAction.DELETE, ResourceBundle.getBundle("/Bundle").getString("ChemicalChemicalDeleted"));
if (!JsfUtil.isValidationFailed()) {
selected = null; // Remove selection
items = null; // Invalidate list of items to trigger re-query.
}
RowObj rowObj = (RowObj) event.getObject();// here Row Object is your selected row item.
if(items != null)
{
//iterate items and delete matched with selected row object
}
}

Related

p:datatable selectAllRows api calls don't trigger rowSelect Event

I have a p:dataTable with selectionMode=multiple which binds the rowSelect and rowUnselect event:
<p:dataTable
widgetVar="myDatatable"
selectionMode="multiple"
selection="#{myBean.selection}">
<p:ajax event="rowSelect" listener="#{myBean.onSelect}" />
<p:ajax event="rowUnselect" listener="#{myBean.onUnselect}" />
... (columns)
</p:dataTable>
Selecting rows works fine, myBean.selection is updated and myBean.onSelect() is invoked.
Now I wanted to add buttons to (un)select all items to my Toolbar. I created two <p:commandLink>s:
<p:commandLink onclick="PF('myDatatable').selectAllRows();"
update="actionbarForm">select all</p:commandLink>
<p:commandLink onclick="PF('myDatatable').unselectAllRows();"
update="actionbarForm">unselect all</p:commandLink>
The selection seems to work, I can see that either all items are (un)selected. However, neither myBean.selection nor myBean.onSelect() are updated/invoked. What do I have to do that to enable this?
These two PrimeFaces javascript api calls do in no way interact with any of the ajax events. This can be seen in the datatable.js in selectAllRows() and unselectAllRows() If you do not use ajax but a normal 'submit' via a button, you'll see that PrimeFaces expands the selection to 'all' on the server side. For this it passes the #all value of the selection to the server.
You'll also see in the source that there already is some code to send a 'toggleSelect` ajax event, so I put it in a function extending the PrimeFaces datatable:
PrimeFaces.widget.DataTable.prototype.fireToggleSelectEvent = function(checked) {
//fire toggleSelect event
if(this.cfg.behaviors) {
var toggleSelectBehavior = this.cfg.behaviors['toggleSelect'];
if(toggleSelectBehavior) {
var ext = {
params: [{name: this.id + '_checked', value: checked}
]
};
toggleSelectBehavior.call(this, ext);
}
}
}
After calling the (un)selectAllRows() via the widget, you can call this function too, with either a true (select) or false (unselect) value as the parameter.
If you then add the toggleSelect ajax to your datatable
<p:ajax event="toggleSelect" listener="#{dtSelectionView.onToggleSelect}" update=":form:msgs" />
and in your bean add a handler:
public void onToggleSelect(ToggleSelectEvent event) {
FacesMessage msg = new FacesMessage(event.isSelected() ? "All Selected" : "All Unselected");
FacesContext.getCurrentInstance().addMessage(null, msg);
}
It all works. (PrimeFaces 6.0, code tested against showcase)
You could also override both the (un)selectAllRows in the PrimeFaces datatable.js and at the end call the fireToggleSelectEvent, so all is in one functioncall (or combine both separate calls in one custom function).

How to get edited row index - OnBatchEditOpening

In my RadGrid (early 2014 version) I have this:
<ClientSettings>
<ClientEvents OnBatchEditOpening="batchEdit" />
</ClientSettings>
Then I have this js function:
function batchEditInitialInvestments(sender, args) {
...
}
This is working great mostly, I can grab (inside the js) the column uniquename that was clicked and other useful properties. I can also get the total number of rows in the grid. What I just can't find is which row was clicked (edited in batch mode), by index. For example, say there are 3 rows in my radgrid and the middle/2nd row is clicked/edited. How can I discover that "index 1" was clicked?
I have scoured the API docs at the following locations:
http://www.telerik.com/help/aspnet-ajax/grid-getting-familiar-with-client-side-api.html
http://www.telerik.com/help/aspnet-ajax/grid-onbatcheditopening.html
You can retrieve the cell of the selected row from the master table view as shown below.
function batchEditInitialInvestments(sender, args) {
var grid = $find('<%=RadGridName.ClientID%>');//can also use the sender parameter
var master = grid.get_masterTableView();
var selected = master.get_selectedItems();
var row = selected[0];
var cell = master.getCellByColumnUniqueName(row, "ColumnUniqueName");
//cell is the cell of the selected row
}

Radgrid Open/Expand child DetailGridView in insert mode from parent row command button

I am using the Telerik RadGrid to display and edit Hierarchical data. As strange as this may sound - one of the requirements is to have a child detail grid open in insert mode when a link in the parent row is clicked. This requires two things. The expansion of the child grid, and getting this grid loaded in insert mode.
This is what I've tried so far using the recommendations from Telerik documentation; However this doesn't work and throws an exception when rebind is called saying that the child detail grid can't find its linqDataSourceControl; however this control does exist while this code below is executing (I checked).
What is the solution to open a child DetailGridView in insert mode from parent row command button?
Markup:
...
<DetailTables>
<telerik:GridTableView>
...
<Columns>
<ItemTemplate>
<asp:LinkButton ID="addChildVendorRating" runat="server" CommandName="AddNewChildRating" CausesValidation="false" CssClass="normal-link" CommandArgument='<%# Eval("VendorM2MEntityToQualID")%>'>[Add Rating]</asp:LinkButton>
</ItemTemplate>
</Columns>
<DetailTables>
<!-- I Need this to be be expanded and in insert mode when addChildVendorRating command link is clicked -->
<telerik:GridTableView>
</<DetailTables>
Code:
protected void gridRatings_ItemCommand(object sender, Telerik.Web.UI.GridCommandEventArgs e)
{
if (e.CommandName == "AddNewChildRating") {
GridDataItem parentRow = e.Item as GridDataItem;
GridTableView parentGridView = parentRow.GetClosestParentControlByType<GridTableView>();
RadGrid parentGrid = parentGridView.GetClosestParentControlByType<RadGrid>();
parentRow.Expanded = true;
//parentGridView.HierarchyDefaultExpanded = true;
//parentGridView.DetailTables[0].InsertItem();
parentGridView.DetailTables[0].IsItemInserted = true;
parentGridView.DetailTables[0].Rebind();
}
}
I figured this out, hopefully this will help someone else. The solution is to cast the command handler e.Item to a GridDataItem; which gives you access to the NestedTableViews - the key to the puzzle. This is the detail view that is actually connected with data unlike DetailTables. Once you set the IsItemInserted on that and rebind it all works like charm.
This allows you to expand a section and put the child section in insert mode all in one shot. Here is the completed code below.
protected void gridRatings_ItemCommand(object sender, Telerik.Web.UI.GridCommandEventArgs e)
{
if (e.CommandName == "AddNewChildRating") {
GridDataItem parentRow = e.Item as GridDataItem;
GridTableView parentGridView = parentRow.GetClosestParentControlByType<GridTableView>();
if (parentGridView != null)
{
var targetGridView = ((GridDataItem)e.Item).ChildItem.NestedTableViews[0];
if (targetGridView != null)
{
parentRow.Expanded = true;
targetGridView.IsItemInserted = true;
targetGridView.Rebind();
}
}
}

Why does event listener not get called?

I'm using ice:menuPopup to dynamically create menus on tree nodes. In jsf page I've something like this
<f:facet name="content">
<ice:panelGroup id="faccont" style="display: inline" menuPopup="qtaPupMenu"><ice:menuPopup imageDir="/images">
<ice:menuItems id="qtaPupMenu" value="#{item.userObject.menuModel}"/>
. . .
Menu items are dynamically created by this code:
public List<MenuItem> getMenuModel() {
List<MenuItem> items = new LinkedList<MenuItem>();
MenuItem mi = new MenuItem();
mi.setValue("menu text");
ExpressionFactory expf = FacesContext.getCurrentInstance().getApplication().getExpressionFactory();
MethodExpression mthd = expf
.createMethodExpression(FacesContext.getCurrentInstance().getELContext(), "#{beanmodel.clickMenuContx}", void.class, new Class[] { ActionEvent.class });
mi.setActionExpression(mex);
items.add(mi);
return items;
}
The problem is that the event listener "#{beanmodel.clickMenuContx}" never gets called.
I've tried also with methodBinding and setActionListener method of MenuItem, but doesn't work.
Where am I going wrong?
Found it!
It was missing the MenuItem id attribute.
I added
mi.setId("myUniqueId");
and it works as expected.

How to set the SelectedValue attribute of Telerik RadComboBox inside the FormTemplate of a RadGrid

I have what I think should be a straightforward question. I have a RadGrid with FormTemplate editing and AJAX enabled. One of the fields in the FormTemplate is a RadComboBox filled with U.S. State selections. I can bind the RadComboBox to the data source to populate all the items, but I'm not able to set the SelectedValue attribute.
This RadComboBox is loaded when the Edit button is clicked for a row on the RadGrid. A custom FormTemplate is used and the contents of the row being edited are loaded via AJAX.
If you are DataBinding, its literally as easy as adding
SelectedValue='<%# Bind("FieldName")%>'
Inside the FormTemplate declaration of the RadComboBox.
If you however want to programmatically determine what value to select, then you need to implement ItemDataBound in the RadGrid, like the following example:
protected void RadGrid1_ItemDataBound(object sender, GridItemEventArgs e)
{
if (e.Item is GridEditFormItem && e.Item.IsInEditMode)
{
GridEditFormItem editFormItem = (GridEditFormItem)e.Item;
RadComboBox combo = (RadComboBox)editFormItem.FindControl("yourControlName");
combo.SelectedValue= Somevalue;
}
}
clear all items of radcombobox initially and then add a new item manually
this is what i do to set new item when i use web service
ddl.ClearSelection()
ddl.Items.Clear()
'below i'm getting the actual value and the text to display
Using reader As IDataReader = GetClientByClientID(CInt(value))
If reader.Read Then
'adding the item will show in the dropdown
Dim item As New RadComboBoxItem(reader("DisplayName").ToString, reader("ID").ToString)
item.Selected = True
ddl.Items.Add(item)
'this line will make the combobox text to be displayed correctly
ddl.Text = reader("DisplayName").ToString
ddl.DataBind()
Else
ddl.Text = ""
ddl.ErrorMessage = "Selected Client Not Found !"
End If
reader.Close()
End Using

Resources