I am unsure how one updates a pe:sheet without directly editing a cell. Currently, when I make a modification to a cell, the data in the underlying list is not modified, and when I modify the underlying list, the front end is not updated. How should I user sync these two?
Here is the HTML:
<script type="text/javascript">
function sheetExtender() {
this.cfg.enterMoves = {row: 1, col: 0};
}
</script>
<pe:sheet id="mySheet" widgetVar="mySheet" value="#{myView.objList}"
var="obj" rowKey="#{obj.listIndex}" style="color: #757575;" height="400"
showRowHeaders="true" sortOrder="ascending" width="1000" extender="sheetExtender">
<p:ajax event="change" listener="#{myView.onChange}" update="mySheet"/>
<pe:sheetcolumn headerText="X" value="#{obj.x}" colType="checkbox"/>
<pe:sheetcolumn headerText="Y" value="#{obj.y}" />
<pe:sheetcolumn headerText="Z" value="#{obj.z}" />
</pe:sheet>
And the change handler:
public void onChange(SheetEvent event) {
Sheet sheet = event.getSheet();
List<SheetUpdate> updates = sheet.getUpdates();
SheetUpdate sheetUpdate = updates.get(0);
Integer rowId = (Integer) sheetUpdate.getRowKey();
Integer colId = (Integer) sheetUpdate.getColIndex();
String oldValue = (String) sheetUpdate.getOldValue();
String newValue = (String) sheetUpdate.getNewValue();
sheet.appendUpdateEvent(rowId, colId + 1, "DUMMY", null, "DUMMY");
sheet.commitUpdates();
}
I cannot find any particular method or widget function to keep these two in sync. If you know the correct method to do this, please let me know how you found it.
Thanks!
#Gumpf you have everything correct...you can only edit cells from the UI front end.
Changing the values in the backing bean will NOT reflect in the Sheet unless you update="sheet" to redraw the entire sheet again. The whole purpose of the Sheet is to not act like an Editable datatable where if you had a 10x10 editable DataTable it would submit 1000 values on Form Submit every time. If you had a 20x20 then it wouldn't work as Most servers stop you at 1000 Form Submit items.
So the Sheet is designed just to update a cell or cells at a time to update your backing bean WITHOUT having to redraw the sheet. What you want to do by updating your backing bean values and have it reflect in the Sheet the only way that will work is update="sheet" to force the whole Sheet to re-render after updating your backing bean values which might not be what you want. Or it might be....
Related
I have a column of checkboxes in my table that I want to have checked with parity in row.isSelected().
When using the VirtualDOM the rows in the buffer don't get checked/unchecked as part of a table.getRows() loop to un-check the box. The rows DO get unselected from the table POV via row.deselect().
The checkbox is added with a mutator to the first column:
checkboxMutator = function (value, data) {
return '<input type="checkbox" class="rowCheckBox" name="' + value + '">';
}
The select all logic:
$("#select-all").click(function () {
var rows = table.getRows(true);
rows.forEach(function(row){
row.select();
$("input[name='" + row.getData().index + "']:checkbox").prop('checked', true);
});
});
The rows that don't exist in the DOM at all yet can be checked by adding some logic into rowFormatter to check them on render the first time.
It might not be possible to fix, but I thought it was worth asking about.
Because Tabulator uses a vitrual DOM only the rows that are visible actually exists, rows are created and destroyed as you scroll.
Because of this it is not safe to try and manipulate any DOM elements inside the table from outside.
In your case you should be using a Custom Formatter that uses the isSelected function on the row component to determine if the checkbox should be selected when it is created.
//custom formatter
function checkboxFormatter(cell, formatterParams, onRendered){
//create input element
var input = document.createElement("input");
input.setAttribute("type", "checkbox");
//set checked state
input.checked = cell.getRow().isSelected();
return input;
}
//assign formatter in column definition
{title:"selected?", formatter:checkboxFormatter}
You should then be using the rowSelectionChanged option to redraw the row after selection has changed, which will then cause the formatter to run and update the checkbox.
rowSelectionChanged:function(data, rows){
//rows - array of row components for the selected rows in order of selection
//data - array of data objects for the selected rows in order of selection
//reformat all rows that have changed
rows.forEach(function(row){
row.reformat();
})
}
You can then select all rows in the table by calling the selectRow function on the table.
table.selectRow();
I have an xpage with a data view control, that has show checkbox and show header checkbox enabled. I want to be able to provide confirmation with a count of selected documents to the user when they click the submit button.
Example
"Are you sure you want to submit x number of documents?"
My confirm action returns 0 regardless of how many documents I select. What am I doing wrong?
<xp:confirm>
<xp:this.message><![CDATA[#{javascript:var dataView1:com.ibm.xsp.extlib.component.data.UIDataView = getComponent("dataView1");
var val = dataView1.getSelectedIds();
var len = val.length;
return "Are you sure you want to submit " + len + " number of documents?";
}]]></xp:this.message>
</xp:confirm>
The immediate problem that you're running into is that the confirmation message is most likely being computed as the button is rendered the first time - which is to say, when no documents are checked.
Even beyond that, though, the getSelectedIds method is tricky: the selected documents are cleared after each request, so something that would do a request to the server to get the selected ID count would also have the side effect of clearing out the selections.
What may be the way to do here is to do the check client-side with something like this:
<xp:eventHandler ...>
<!-- other action stuff here -->
<xp:this.script><![CDATA[
var count = dojo.query("tbody input[type='checkbox']:checked", dojo.byId("#{id:yourDataViewId}")).length;
return XSP.confirm("Are you sure you want to submit " + count + " document" + (count == 1 ? "" : "s") + "?");
]]></xp:this.script>
</xp:eventHandler>
The Dojo query in there will search for all checked checkboxes inside the body part of the data view (to exclude the header checkbox), restricted to within the specific data view you want to search for. The XSP.confirm client-side method is the same idea as the <xp:confirm/> simple action, and returning the value from it will cancel the submit if the user says no.
I have a datatable problem when I reject changes on the table. I've created an example below which demonstrates the problem:
DataTable table = new DataTable();
table.Columns.Add("Name", typeof(string));
table.Columns.Add("Last_Name", typeof(string));
table.Columns.Add("Male", typeof(Boolean));
foreach (DataColumn column in table.Columns)
{
if (column.ColumnName == "Name")
{
column.Unique = true;
}
}
DataRow row;
row = table.NewRow();
row["Name"] = String.Format("Steve");
row["Last_Name"] = String.Format("Smith");
row["Male"] = true;
table.Rows.Add(row);
table.AcceptChanges();
So at this stage I have a DataTable with a unique column constraint and 1 row in that table.
I now delete that row:
row.Delete();
This sets the rowstate to Deleted.
At this stage I realise that I've made a mistake and want to add the row again. So I create the new row again and add it to the DataTable:
row = table.NewRow();
row["Name"] = String.Format("Steve");
row["Last_Name"] = String.Format("Smith");
row["Male"] = true;
table.Rows.Add(row);
At this stage my DataTable contents are in the following state:
table.Rows[0].RowState is Deleted
table.Rows[1].RowState is Added
Now, I've changed my mind about the whole thing and want to get back to how I started so I call RejectChanges:
table.RejectChanges();
When I do this I receive the following error:
Column 'Name' is constrained to be unique. Value 'Steve' is already present.
I understand that there are 2 rows with the same values but I thought reject changes would have ingored this as the RowStates are different.
Any ideas how I can get round this?
In my live code I use this to move rows between to 2 grids (like allowing the user to selected what columns are visible)
I'm using C#4.0 in Visual Studio 2012
Thanks in advance
I have some issues in deleting a row on click of a button. I have a datatable, which contains 5 columns. The fifth column is a button. I have a requirement, where, when I click on the button, the row data corresponding to the button needs to be deleted. Im trying to populate the column values using a datamodel. Below is the code that I have written to acheive the row deletion. But the row is not getting deleted.
<h:commandButton id="buttonID1" image="/images/drappimages/delete.png" style="width:15px ;" actionListener="#{adminBean.delete}" >
<f:ajax render="adminTableID" ></f:ajax>
</h:commandButton>
The listener method is specified below
public void delete(ActionEvent event)
{
deleteFlag = true;
int rowIndex = adminVODataModel.getRowIndex() ;
AdminVO admminData = adminVODataModel.getRowData();
System.out.println("The rowIndex that needs to be actioned is :"+ rowIndex);
System.out.println("The adminVOList is :"+ adminVOList.size());
adminVOList.remove(rowIndex) ;
adminVOList.remove(adminData) ;
System.out.println("the VOList now is "+ adminVOList.size());
adminVODataModel = new ListDataModel<AdminVO>(adminVOList) ;
setAdminScheduleVODataModel(adminVODataModel);
}
Im using the adminVODataModel to populate the datatable. Im trying to remove the corresponding row using the above code. But the row is not getting deleted.
Please Assist. Thanks in Advance
You should update your table after deletion
just add update="#form" to your <p:ajax. In case you got some h:panelGroup wrapper, you can place its id instead of #form in the update.
b.t.w I think that in 3.4 you can place table id in the target of the update attribute too (not sure if that was possible in prior to 3.4)
since you moved to h:commandButton , try
render="#form" or render="somePanelGroudIDThatWrapsTheTable"
also
don't do both adminVOList.remove(rowIndex); and adminVOList.remove(adminData) ;
if you got the right index use it to remove the entry
I'm using cfspreadsheet to generate an excel spreadsheet. I'm adding rows one by one. Immediately after I add the row, I want to format it. Something like this:
<cfset SpreadsheetAddRow(mySpreadsheet, "hi,this,is,a,test") />
<cfset SpreadsheetFormatRow(mySpreadsheet,
{
fgcolor:red;
}) />
However, for the formatrow function, you have to provide a row number. Is there any way to format the row I just added without keeping a running counter of what row I'm up to?
The spreadsheet object itself knows how many rows are in it, similar to a query object.
<cfset CurrentRow = mySpreadsheet.RowCount />
Updating your example so that it works in ACF9:
<cfset SpreadsheetFormatRow(mySpreadsheet,
{
fgcolor = 'red'
}, mySpreadSheet.RowCount ) />