How do I add a radio group to a table cell using iTextSharp 4.1.6? - itext

I'm trying to generate a dynamic survey as a PDF. The question text appears in the first cell, and the field appears in the 2nd cell. I have no problems when adding a text field or drop down field, but I cannot get a radio group to display. I am able to get a single radio button, but would like the entire group to display in the cell. Is this possible? And if so, how?
Here is a code sample of what I've tried thus far.
Table.AddCell(Question.TEXT + ":");
PdfFormField RadioGroup = PdfFormField.CreateRadioButton(ExportWriter, true);
RadioGroup.FieldName = "field" + Question.QUESTION_ID;
using (Entities _context = new Entities())
{
QuestionOptions = SURVEY.GetQuestionOptions(Question.QUESTION_ID, _context).ToList();
}
RadioCheckField Radio;
PdfFormField RadioField = null;
foreach (OPTIONS Option in QuestionOptions)
{
Radio = new RadioCheckField(ExportWriter, new Rectangle(40, 806 - count * 40, 60, 788 - count * 40), Option.OPTION_NAME, "option" + Option.OPTION_ID.ToString());
Radio.BackgroundColor = new GrayColor(0.8f);
Radio.CheckType = RadioCheckField.TYPE_CIRCLE;
RadioField = Radio.RadioField;
RadioField.SetWidget(new Rectangle(10, 20), PdfAnnotation.HIGHLIGHT_INVERT);
RadioGroup.AddKid(RadioField);
}
ExportWriter.AddAnnotation(RadioGroup);
Cell = new PdfPCell();
Events = new iTextSharp.text.pdf.events.FieldPositioningEvents(ExportWriter, RadioGroup);
Cell.CellEvent = Events;
Table.AddCell(Cell);
The issue is that when the radio buttons appear, they appear on the bottom left of the page, and not within the cell.
Thanks in advance!

Related

Strange display of a table of radio buttons

I am creating a form, in which there is a table of buttons. The following shows the idea:
Good OK Bad
Item1 [button] [button] [button]
Item2 [button] [button] [button]
Each row is a button group.
My program is able to work for a small table like the above. However, when rows or columns are more than one page to hold, the display is weird. This is my program:
PdfPTable table = new PdfPTable(colHeaders.size() + 1 );
table.setWidthPercentage(100);
PdfPCell cell;
table.setSpacingBefore(10);
table.setSpacingAfter(0);
table.setKeepTogether(false); //tested "true" different display error
//upper-left corner empty cell
cell = new CustomPdfPCell();
cell.setBackgroundColor(BaseColor.LIGHT_GRAY);
table.addCell(cell);
//header row
for (TableOfChoicesHeader c: colHeaders) {
String text = c.getText();
cell = new PdfPCell(new Phrase(text));
cell.setBackgroundColor(BaseColor.LIGHT_GRAY);
table.addCell(cell);
}
List<PdfFormField> radioGroups= new ArrayList<PdfFormField>();
//for each row
for (TableOfChoicesHeader r: rowHeaders) {
//row header
String rowText = r.getText();
cell = new PdfPCell(new Phrase(rowText));
cell.setBackgroundColor(BaseColor.LIGHT_GRAY);
table.addCell(cell);
//for the current row row
String fieldName = "question" + q.getId() +"_" + r.getId().toString();
PdfFormField radiogroup = PdfFormField.createRadioButton(writer, true);
radiogroup.setFieldName(fieldName);
radioGroups.add(radiogroup);
for (TableOfChoicesHeader c: colHeaders) {
cell = new PdfPCell();
cell.setHorizontalAlignment(Element.ALIGN_CENTER);
cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
cell.setPadding(5);
cell.setCellEvent(new CheckboxCellEvent(fieldName, r.getId() + "_" + c.getId()));
table.addCell(cell);
}
}
document.add(table);
for (PdfFormField g: radioGroups) {
writer.addAnnotation(g);
}
Here are the screenshots when table.setKeepTogether(false). The display is a little different but still strange if the value is true.
Page 1
Page 2
Update
By following Samuel's approach, I am able to see radio buttons displayed on the first page. However, the buttons on the first page got displayed on the second page. See the screenshots.
Update 2
I got it working by adding the following in MyCellField :
writer.addAnnotation(radiogroup);
instead of
PdfFormField field = radio.getRadioField();
writer.addAnnotation(field);
I cannot explain why. Thank Samuel and Bruno for their help!
Looking at your code again, is there any reason why you add the annotations for the radiobuttons all in one go at the end?.
Have you tried adding the annotation whenever you've added your row of cells? Something like this:
for (TableOfChoicesHeader r: rowHeaders) {
//row header
String rowText = r.getText();
cell = new PdfPCell(new Phrase(rowText));
cell.setBackgroundColor(BaseColor.LIGHT_GRAY);
table.addCell(cell);
//for the current row row
String fieldName = "question" + q.getId() +"_" + r.getId().toString();
PdfFormField radiogroup = PdfFormField.createRadioButton(writer, true);
radiogroup.setFieldName(fieldName);
radioGroups.add(radiogroup);
for (TableOfChoicesHeader c: colHeaders) {
cell = new PdfPCell();
cell.setHorizontalAlignment(Element.ALIGN_CENTER);
cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
cell.setPadding(5);
cell.setCellEvent(new CheckboxCellEvent(fieldName, r.getId() + "_" + c.getId()));
table.addCell(cell);
}
writer.addAnnotation(radiogroup)
}
EDIT:
As Bruno said, the examples for distributing a radio-group over multiple pages are RadioGroupMultiPage1 and RadioGroupMultiPage2. The examples for distributing a radio group across a table is found here: Distributing radio buttons of a radio field across multiple PdfCells.
EDIT 2, Electric Bogaloo:
Wipped up a quick example based on your code and the examples Bruno pointed out:
I basicly took your code frm the question above(with some stub-implementations for your custom data-classes), and used the MyCellField PdfCellEvent extension found in RadioGroupMultiPage2:
public MyCellField(PdfWriter writer, PdfFormField radiogroup, String value) {
this.writer = writer;
this.radiogroup = radiogroup;
this.value = value;
}
public void cellLayout(PdfPCell cell, Rectangle position, PdfContentByte[] canvases) {
try {
RadioCheckField radio = new RadioCheckField(writer, position, null, value);
PdfFormField field = radio.getRadioField();
writer.addAnnotation(field);
radiogroup.addKid(field);
} catch (IOException ex) {
// do nothing
} catch (DocumentException ex) {
// do nothing
}
}

How to enable tab navigation to the next editable cell in a different row group?

I'm building an application using ag-grid enterprise 4.0.7, which uses row groups and has editable fields, keyboard navigation between editable cells is essential.
Built-in tab navigation works well, but only within a row group. Once the last editable cell in a group is reached, pressing tab does NOT jump to the next editable cell in the next group but rather to some unrelated element on the page.
Here's an example based on an ag-grid documentation sample, the athletes' names are editable, tab navigates to the next athlete, but only within one country: https://jsfiddle.net/pfhkf3bm/
field: "athlete",
editable: true
Is this the intended behavior? What's the cleanest way to extend the tab navigation to jump to the next editable item in another group?
Thanks!
This method has worked for me:
myTabToNextCell(params) {
const previousCell = params.previousCellDef;
const lastRowIndex = previousCell.rowIndex;
let nextRowIndex = lastRowIndex + 1;
// TODO renderedRowCount must contain the row count.
const renderedRowCount = this.state.rowCount;
// if (nextRowIndex >= renderedRowCount) { nextRowIndex = 0; }
if (nextRowIndex < renderedRowCount) { nextRowIndex = lastRowIndex + 1; } else {
nextRowIndex = 0;
}
const result = {
rowIndex: nextRowIndex,
column: previousCell.column,
floating: previousCell.floating
};
return result;
}

Hide dropdown button

I'm creating a TextField as so:
iTextSharp.text.pdf.TextField fieldCombo = new iTextSharp.text.pdf.TextField(stamp.Writer, realArea, placeHolder);
fieldCombo.Choices = (new string[1] { "" }).Concat(attribute.Values.Select(x => x.Value.Code)).ToArray();
iTextSharp.text.Font bold = iTextSharp.text.FontFactory.GetFont(iTextSharp.text.FontFactory.HELVETICA, 9f, iTextSharp.text.Font.BOLD);
fieldCombo.Font = bold.BaseFont;
fieldCombo.FieldName = Guid.NewGuid().ToSafeString();
fieldCombo.FontSize = 10f;
fieldCombo.TextColor = new iTextSharp.text.BaseColor(System.Drawing.Color.FromArgb(255, 6, 97, 50));
fieldCombo.Options = iTextSharp.text.pdf.BaseField.EDIT | iTextSharp.text.pdf.BaseField.VISIBLE_BUT_DOES_NOT_PRINT;
stamp.AddAnnotation(fieldCombo.GetComboField(), page + 1);
From the first time the field is focussed, a very generic grayish down arrow appears on the document, positioned next to my value. Even if the field is unfocussed, this arrow stay visible.
Can I get rid of this combo box button when printing the document?

Slick grid set value on autocomplete cell

I'm trying to set values in a slick grid from jQuery thru val and text e.g. .find('div.slick-cell.l2.r2').text('xyz'). There is a jquery autocomplete on the cell in question but it only gets activated on click. So when I click the cell in question it get overwritten by the initial defaultValue in the editor:
function ComboBoxEditor(args) {
...
this.loadValue = function (item) {
defaultValue = item[args.column.field] || "";
$input.val(defaultValue);
$input[0].defaultValue = defaultValue;
$input.select();
};
...
Can I get the jQuery text value from within the world of the slick grid.
Think of slickgrid as a rendering engine and dataView as the data interface (You are using dataView right?) Jquery or javascript editing of dom elements isn't gong to work so think about how jquery/javascript can use the dataView methods to do the updating.
I ran into this same issue when adding drag and drop of files into SlickGrid
I detect the elementID of the drop and map it back to the dataView row and column.
Here is the function I used for text pasting:
function insertText(textString, location) {
grid.resetActiveCell();
$(location).click();
var startCell = grid.getActiveCell();
if (startCell) {
// only paste text into active cells for now
var columnDef = grid.getColumns();
var colField = columnDef[startCell.cell].field;
if (!dataView.getItem(startCell.row)) {
// new row
var tobj = {'id': "new_" + (Math.random() + 1).toString(36).substring(7)};
tobj[colField] = textString;
dataView.addItem(tobj);
} else {
// modify existing cell
var item = dataView.getItem(startCell.row);
item[colField] = textString;
dataView.updateItem(item.id, item);
}
grid.resetActiveCell();
grid.render();
dataView.refresh();
}
}

Dynamically Generated Telerik MVC3 Grid - Add Checkboxes

I have a grid that is dynamically generated based on search criteria. I render the grid in a partial view using Ajax. That all works fine.
I now need to add a checkbox column as the first column.
Also, how do I get filtering, sorting paging etc. to work now since it is in a partial view.
When i click on a header to sort I get a Page not found error and the filter Icon doesnt do anything.
And one more thing. When I try to add a GridCommandColumnSettings to the grid I get the error
"Invalid initializer member declarator"
Code is below for the gridcolumnsettings
public GridColumnSettings[] NewColumns(DataTable fullDT)
{
GridColumnSettings[] newColumns = new GridColumnSettings[fullDT.Columns.Count];
for (int i = 0; i < fullDT.Columns.Count; i++)
{
// set the visibility property for the DeliveryID
bool boolDeliveryID;
if (fullDT.Columns[i].ColumnName == "DeliveryID")
boolDeliveryID = false;
else
boolDeliveryID = true;
newColumns[i] = new GridColumnSettings
{
new GridCommandColumnSettings
{
Commands =
{
new GridEditActionCommand(),
new GridDeleteActionCommand()
},
Width = "200px",
Title = "Commands"
},
Member = fullDT.Columns[i].ColumnName,
Title = fullDT.Columns[i].ColumnName,
Visible = boolDeliveryID,
Filterable = true,
Sortable = true
};
}
return newColumns;
}
Any suggestions would be appreciated.
Thanks
I edited my post to add my partial for the Grid
Here is my partial for the grid
#(Html.Telerik().Grid<System.Data.DataRow>(Model.Data.Rows.Cast<System.Data.DataRow>())
.Name("Grid")
.Columns(columns =>
{
columns.LoadSettings(Model.Columns as IEnumerable<GridColumnSettings>);
})
.DataBinding(dataBinding => dataBinding.Ajax().Select("_DeliveryManagerCustomBinding", "Deliveries"))
.EnableCustomBinding(true)
.Resizable(resize => resize.Columns(true))
)
I don't add columns this way when I use the Telerik Grid control, but looking at what you're doing I would hazard a guess to say you will need to do something like the following:
increase the size of the newColumns array by 1 (because we're going to add in the checkbox column):
GridColumnSettings[] newColumns = new GridColumnSettings[fullDT.Columns.Count + 1];
if you want it at the beginning you will need to do the following before your for-loop:
GridColumnSettings s = new GridColumnSettings() {
ClientTemplate("<input type=\"checkbox\" name=\"checkeditems\" value=\"some value\" />")
Title("title goes in here")
};
Then you will add it into your array:
newColumns[0] = s;
and then increase the start index for your for-loop to 1:
for (int i = 1; i < fullDT.Columns.Count; i++)
the checkbox column will go at the beginning