How To Copy the Value From Binding Variable To Iterator in adf? - oracle-adf

i have an adf table that contain many columns + plus a column that have a button , which will open a popup to insert a value
<af:table value="#{bindings.BpmCrMilestoneUPView1.collectionModel}" var="row" rows="#{bindings.BpmCrMilestoneUPView1.rangeSize}" >
<af:column id="c49" headerText="#{bindings.BpmCrMilestoneUPView1.hints.MilestoneSeq.label}" width="50" displayIndex="-1" minimumWidth="12">
<af:inputText value="#{row.bindings.MilestoneSeq.inputValue}" readOnly="true" id="it16">
</af:inputText>
</af:column>
<af:column>
<af:inputText value="#{row.bindings.Oldmilesseq.inputValue}" id="it15">
</af:column>
<af:column label="openPopUp" >
<af:button action = "#{pageFlowScope.CRInitaitiveBean.openCommentsPopUp}" >
</af:button>
</af:column>
<af:table>
and this is the popup that contain the input text Field
<af:popup binding="#{pageFlowScope.CRInitaitiveBean.commentsPopUp}" id="p2">
<div class="form-group" id="d7">
<af:outputLabel value="#{lang.previous_comments}" />
<af:inputText autoSubmit="true" simple="true"
value="#{bindings.newCommentValue.inputValue}" />
</div>
</div>
and the newCommentValue pointing to the BpmCrOutputUPView1Iterator in the bindings tab.
if i open the popup for each row , and type values , all values are saved correctly
but when i try to loop the iterator programmatically , the typed values are null
and this is the code
RowSetIterator itr = ADFUtils.findIterator("BpmCrOutputUPView1Iterator").getRowSetIterator();
while (itr.hasNext()) {
Row row = itr.next();
if (row != null) {
System.out.println();
System.out.println("Current OUTPUT Row Is Not Null");
String newComment = (String) row.getAttribute("newCommentValue");
System.out.println();
System.out.println("new Comment is -------------------> "+newComment); // it should print the typed value for that row
but it's printed null

It will be easier for this specific use case to use the highly recommended JSFUtils open source class resolveExpression function.
JSFUtils and ADFUtils are two utilitary java class made by 3 ADF heroes Duncan Mills, Steve Muench and Ric Smith. You can easily find those using your favorite search engine.
Once added to your project you can get the value of an EL Expression inside your Java bean as follow :
String newCommentValue= (String)JSFUtils.resolveExpression("#{bindings.newCommentValue.inputValue}");
Here is the JSFUtils function for your information :
/**
* Method for taking a reference to a JSF binding expression and returning
* the matching object (or creating it).
* #param expression EL expression
* #return Managed object
*/
public static Object resolveExpression(String expression) {
FacesContext facesContext = getFacesContext();
Application app = facesContext.getApplication();
ExpressionFactory elFactory = app.getExpressionFactory();
ELContext elContext = facesContext.getELContext();
ValueExpression valueExp = elFactory.createValueExpression(elContext, expression, Object.class);
return valueExp.getValue(elContext);
}

Related

Serializing PropertyBusinessObject to XML

I'm trying to upgrade the code quality of a part of my app which can display data within dynamic Form that are configured via an XML string translated into an object. Until now, I was doing parsing and serializing with custom methods only, nearly writing each line of XML myself. That's obviously the wrong approach and I fully understand it now that I'm very familiar with Codename One.
So I rewrote my objects to use the PropertyBusinessObject interface and here are the resulting classes :
public class CForm implements PropertyBusinessObject
{
Property<String, CForm> type = new Property<>("type");
Property<String, CForm> label = new Property<>("label");
IntProperty<CForm> currentStep = new IntProperty<>("currentstep");
IntProperty<CForm> maxsteps = new IntProperty<>("maxsteps");
ListProperty<CFormField, CForm> fields = new ListProperty<>("fields", CFormField.class);
ListProperty<CFormStep, CForm> steps = new ListProperty<>("steps", CFormStep.class);
public CForm()
{
}
PropertyIndex index;
#Override
public PropertyIndex getPropertyIndex()
{
if(index == null)
index = new PropertyIndex(this, "CForm",
new PropertyBase[] {type, label, currentStep, maxsteps, fields, steps});
return index;
}
}
This class is the main one, describing the general structure of the process. Type and label are used internally to identify the model used and the job to do at the customer place. Fields are the dynamic fields that will be shown at each step, these are global fields, like remarks or so. The steps are the differents dynamic Forms that will be shown to the user. maxSteps and currentStep are used to know where the user is in the process.
public class CFormStep implements PropertyBusinessObject
{
Property<String, CFormStep> name = new Property<String, CFormStep>("name");
Property<String, CFormStep> label = new Property<String, CFormStep>("label");
IntProperty<CFormStep> value = new IntProperty<CFormStep>("value");
ListProperty<CFormField, CFormStep> fields = new ListProperty<>("fields", CFormField.class);
public CFormStep() {}
PropertyIndex index;
#Override
public PropertyIndex getPropertyIndex()
{
if(index == null)
index = new PropertyIndex(this, "CFormStep",
new PropertyBase[] { label, name, value, fields});
return index;
}
}
Each step is described with an unique name, a label used as the title of the dynamic form and a value to order the steps within the CForm. Like it's CForm parent, it has a set of fields.
public class CFormField implements PropertyBusinessObject
{
Property<String, CFormField> label = new Property<String, CFormField>("label");
Property<String, CFormField> name = new Property<String, CFormField>("name");
Property<String, CFormField> type = new Property<String, CFormField>("type");
Property<String, CFormField> value = new Property<String, CFormField>("value");
Property<String, CFormField> parent = new Property<String, CFormField>("parent");
public CFormField() {}
PropertyIndex index;
#Override
public PropertyIndex getPropertyIndex()
{
if(index == null)
index = new PropertyIndex(this, "CFormField",
new Property[] { label, name, type, value, parent });
return index;
}
}
The fields are composed of a label, an unique name, a type used to define which component will be used to render it, the value selected by the user formatted as a String and finally it's optionnal parent name.
The old implementation was fonctionnal but laggy and hard to evolve, which is why I came to write this new one.
But I'm stuck with one problem : I already rewroted the PropertyIndex.fromXML(Element e) since it was creating NPE's when calling
public void fromXml(Element e) {
Hashtable atts = e.getAttributes();
for(Object a : atts.keySet()) { <--- NPE there if no attributes
and was not supporting ListProperties.
Reading my CForm from XML works fine but when I try to serialize it back to XML I just got a <CForm><CForm/> and don't fully understand how the PropertyXMLElement works... I've already debugged the process and the PropertyBusinessObject is not empty at all. Any idea on how to fill the XML with those values ?
Here is an example of XML used :
<CForm>
<type>delivery-install</type>
<label>Intervention Test</label>
<currentstep/>
<maxsteps>3</maxsteps>
<fields>
<CFormField>
<label>Remarques</label>
<name>globalTEXTAREA6</name>
<type>TEXTAREA</type>
<value/>
</CFormField>
</fields>
<steps>
<CFormStep>
<name>step1</name>
<label>Arrivée sur place</label>
<value>1</value>
<fields>
<CFormField>
<label>Heure d'arrivée</label>
<name>step1TIME3</name>
<type>TIME</type>
<value/>
</CFormField>
</fields>
</CFormStep>
<CFormStep>
<name>step2</name>
<label>Sur place</label>
<value>2</value>
<fields>
<CFormField>
<label>Produits livrés / utilisés</label>
<name>step2PRODUCTTABLE7</name>
<type>PRODUCTTABLE</type>
<value/>
</CFormField>
</fields>
</CFormStep>
<CFormStep>
<name>step3</name>
<label>Départ</label>
<value>3</value>
<fields>
<CFormField>
<label>Heure de départ</label>
<name>step3TIME4</name>
<type>TIME</type>
<value/>
</CFormField>
<CFormField>
<label>Signature client</label>
<name>step3SIGN5</name>
<type>SIGN</type>
<value/>
</CFormField>
</fields>
</CFormStep>
</steps>
</CForm>
The XML support in property business object is still a work in progress which is why I didn't blog about it. I fixed the NPE issue and added support for list properties to fix the two issues raised. Notice I only did this for reading so there might be issues writing these objects as we didn't have time to do QA on this feature.

Default value gets stored in another column based on value selected from LOV

Table-Items
Columns-Order_Type
(Sales,
Return,
Defective)
Order_Type_Id(1,2,3)
i.e 1-Sales,
2-Return,
3-Defective
VO has Transient attribute-OrderType which has an LOV showing Order_Type.
Based on selected Order_Type, Order_Type_Id should get stored in Order_Type_Id column
public Number getOrder_Type_Id() {
String orderType = null;
Number orderNumber = null;
if (getOrderType() != null) {
orderType = getOrderType();
if (orderType.equals("Sales")) {
orderNumber = new oracle.jbo.domain.Number(2);
} else if (orderType.equals("Return")) {
orderNumber = new oracle.jbo.domain.Number(3);
} else if (orderType.equals("Defective")) {
orderNumber = new oracle.jbo.domain.Number(4);
}
this.setOrder_Type_Id(orderNumber);
}
Following code worked.
Writing following code in Order_Type_Id:
public Number Order_Type_Id()
{
String orderType=null;
Number orderNumber=null;
if(getOrder_Type()!=null){
orderType=getOrder_Type();
if(orderType.equals("Sales")){
orderNumber=new oracle.jbo.domain.Number(2);
}
else if(orderType.equals("Defective")){
orderNumber=new oracle.jbo.domain.Number(3);
return orderNumber;
}
else
{
return (Number)getAttributeInternal(Order_Type_Id);}
}
}
In Order_Type_Id attribute add dependency or Order_Type
Assuming LOV VO is also from Query not from static list :
It is developed in ADF 11g
OrderTypeLOVVO :
order_type_id - back-end stored column
order_type_desc - display column
BaseOrderVO
OrderTypeId - transient attribute - LOV - OrderTypeLOVVO
OrderTypeDesc - transient attribute - OutputText column with default value - 1
orderTypeId
- Make autoSubmit property true in both places in VO and in jsff page ( drop it as select one choice) .
- OrderTypeId value will be bindings.orderTypeId.inputValue
- Shuffle the dependent attribute Order_type_desc from left to right in dependecies component of VO.
OrderTypeDesc
Make default value as 1 and in jsff page set partial trigger dependent of orderTypeId after dropping it as output label.
Make OrderTypeDesc value attribute as bindings.orderTypeId.attributeValue
We need to make OrderTypeDesc value as orderTypeId.attributeValue because when you select OrderTypeId as sales (this is inputValue), so backend value (id) is 1. so attributeValue will get the id of the selected value in LOV.
Same works with static list VO too.
As per your requirement, In programatically,
I have created a method on value change listener of LOV,
changeValue() is the method in bean class.
public void changeValue(ValueChangeEvent valueChangeEvent) {
AppModuleImpl module = getApp(); // creating appModuleImpl class object
//definition for getApp() is given below.
item_desc = module.assignValue(valueChangeEvent.getNewValue().toString());
// This item_desc value is declared globally.
//assignValue method of AppModuleClass is given below
bind_item_desc.setValue(item_desc);
AdfFacesContext adfFacesContext = AdfFacesContext.getCurrentInstance();
adfFacesContext.addPartialTarget(bind_item_desc);
// bind_item_desc is the binding attribute of output label which needs to be refreshed.
// Add event code here...
}
public static AppModuleImpl getApp() {
return (AppModuleImpl)Configuration.
createRootApplicationModule(
"Model.AppModule", // where your module is stored
"AppModuleShared"); // chosen configuration
}
Here Model.AppModule is the location of AppModule.
assingValue() of AppModuleClass where it will assign the value according to the selected value in LOV.
public String assignValue(String value)
{
String item_desc=null;
System.out.println("Changed value " + value);
if(value.equals("Sales"))
{
item_desc="14";
}
return item_desc;
}
In assignValue, Parameter is value which will be input from bean class (a selected value from LOV) and returning the String parameter which you will be needed back again in bean class.
So when you select a value in LOV, it will trigger the value change listener method (changeValue()) and will navigate to AppModule . In AppModule , value will be assigned and come back to Bean class.
But it will not reflect untill, you will not refresh the page component.
<af:selectOneChoice value="#{bindings.item_id_lov.inputValue}"
label="item for lov"
required="#{bindings.item_id_lov.hints.mandatory}"
shortDesc="#{bindings.item_id_lov.hints.tooltip}"
id="soc4" autoSubmit="true"
valueChangeListener="#{bean1.changeValue}">
<f:selectItems value="#{bindings.item_id_lov.items}" id="si4"/>
</af:selectOneChoice>
Here value change listener is called in SelectOneChoice and autoSubmit is true.
<af:panelLabelAndMessage label="item description"
id="plam1" partialTriggers="soc4">
<af:outputFormatted value="#{bean1.item_desc}" binding="#{bean1.bind_item_desc}"
id="of1"/>
</af:panelLabelAndMessage>
Here , in value attribute item_desc is assigned (which is declared in bean). Also binding got created for the output label. PartialTrigger is assigned of LOV as outputLabel is dependent on LOV.

How can I add text to a Checkbox I create using iTextSharp?

Derived from Jeff S's methodology found here, I can add a "Checkbox" to a PDF page like so:
PdfPTable tblFirstRow = new PdfPTable(5);
tblFirstRow.SpacingBefore = 4f;
tblFirstRow.HorizontalAlignment = Element.ALIGN_LEFT;
. . . // code where textboxes are added has been elided for brevity
PdfPCell cell204Submitted = new PdfPCell()
{
CellEvent = new DynamicCheckbox("checkbox204Submitted", "204 Submitted or on file")
};
tblFirstRow.AddCell(cell204Submitted);
doc.Add(tblFirstRow);
The DynamicCheckbox class, based on Jeff S's CustomCellLayout class, is:
public class DynamicCheckbox : IPdfPCellEvent
{
private string fieldname;
private string cap;
public DynamicCheckbox(string name, String caption)
{
fieldname = name;
cap = caption;
}
public void CellLayout(PdfPCell cell, Rectangle rectangle, PdfContentByte[] canvases)
{
PdfWriter writer = canvases[0].PdfWriter;
RadioCheckField ckbx = new RadioCheckField(writer, rectangle, fieldname, "Yes");
ckbx.CheckType = RadioCheckField.TYPE_CHECK;
ckbx.Text = cap;
PdfFormField field = ckbx.CheckField;
writer.AddAnnotation(field);
}
}
My problem is that the checkbox's text (the string assigned to ckbx.Text) is not displaying. The checkbox (outsized) occupies the last cell in the table row, but there is no (visible) accompanying text.
What's missing from my code?
Note: I tried to reduce the size of the checkbox by doing this:
Rectangle tangle = new Rectangle(20, 20);
//RadioCheckField ckbx = new RadioCheckField(writer, rectangle, fieldname, "Yes");
RadioCheckField ckbx = new RadioCheckField(writer, tangle, fieldname, "Yes");
...but that attempt failed - with that code, I can't even "find" the checkbox in the generated PDF file - clicking willy-nilly in column 5 conjures up no checkbox...
Others have answered the label part. The Rectangle that you have called "tangle" needs to be calculated off of the rectangle that comes into the event handler, similar to
Rectangle tangle = new Rectangle(
rectangle.Left,
rectangle.Top - PDFStyle.boxsize - 4.5f,
rectangle.Left + PDFStyle.boxsize,
rectangle.Top - 4.5f
);
Where PDFStyle.boxsize is the width/height of the checkbox and 4.5f is the padding the edge of the cell. Basically the rectangle isn't relative to the cell, but absolute to the page.
As described in ISO-32000-1, a check box is a field of type Button. If you define text for a button, you want to define the text that is displayed on the button. However: in the case of a check box, there is no such text! Instead, you have two appearances, one for the Off value and one for the Yes value.
An educated guess made by an attentive reader would be that you don't want to add text (to the button), but that you want to add a label (for a checkbox). Again you should consult ISO-32000-1 and you'll discover that the spec doesn't say anything about labels for check boxes. The concept just doesn't exist at the level of an AcroForm.
This doesn't mean the concept doesn't exist in general. Many PDF tools allow you to define check boxes that are preceded by a label. When you look inside the PDF, you'll discover that this label is just part of the content, whereas the check box is represented by a widget orientation.
Let's take a look at the official documentation instead of frustrating ourselves searching on every place of the web except on the official web site. More specifically: let's take a look at the Buttons example from Chapter 7 of my book. You'll see that one can set text for a real button:
PushbuttonField button = new PushbuttonField(writer, rect, "Buttons");
button.setText("Push me");
This isn't possible with check boxes (for the obvious reason that the appearance of a check box is completely different). If we want to add a label, we can add it for instance like this:
checkbox = new RadioCheckField(writer, rect, LANGUAGES[i], "Yes");
field = checkbox.getCheckField();
field.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, "Off", onOff[0]);
field.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, "Yes", onOff[1]);
writer.addAnnotation(field);
ColumnText.showTextAligned(canvas, Element.ALIGN_LEFT,
new Phrase(LANGUAGES[i], font), 210, 790 - i * 40, 0);
You can find the C# version of these examples here: http://tinyurl.com/itextsharpIIA2C07
Creating a checkbox, and then accompanying text to its right, can be done like this:
PdfPCell cell204Submitted = new PdfPCell()
{
CellEvent = new DynamicCheckbox("checkbox204Submitted")
};
tblFirstRow.AddCell(cell204Submitted);
// . . . Chunks and an anchor created; that code has been elided for brevity
Paragraph parCkbxText = new Paragraph();
parCkbxText.Add(Chunk204SubmittedPreamble);
parCkbxText.Add(ChunkBoldNote);
parCkbxText.Add(Chunk204Midsection);
parCkbxText.Add(anchorPayeeSetup204);
PdfPCell cellCkbxText = new PdfPCell(parCkbxText);
cellCkbxText.BorderWidth = PdfPCell.NO_BORDER;
tblFirstRow.AddCell(cellCkbxText);
public class DynamicCheckbox : IPdfPCellEvent
{
private string fieldname;
public DynamicCheckbox(string name)
{
fieldname = name;
}
public void CellLayout(PdfPCell cell, Rectangle rectangle, PdfContentByte[] canvases)
{
PdfWriter writer = canvases[0].PdfWriter;
RadioCheckField ckbx = new RadioCheckField(writer, rectangle, fieldname, "Yes");
ckbx.CheckType = RadioCheckField.TYPE_CHECK;
ckbx.BackgroundColor = BaseColor.ORANGE;
ckbx.FontSize = 6;
ckbx.TextColor = BaseColor.WHITE;
PdfFormField field = ckbx.CheckField;
writer.AddAnnotation(field);
}
}

Soql : Need help on accessing subquery value in datatable

Am new to Salesforce.
I have used following query :
select name,(select Due_Amount__c from Dues__r where year__c=1990 and month__c=3) from contact where Accountid = '00190000012j4Xi'
which is giving the result as
Name Due__c
Rose Gonzalez Due_Amount__c
1 400.0
Sean Forbes Due_Amount__c
1 300.0
I am populating the result in the data table as contact.name :
totalDues = new List<Contact>([select name,(select Due_Amount__c from Dues__r where year__c=1990 and month__c=3) from contact where Accountid =: selectedSoc]);
totalDuesWrapperList = new List<contactWrapper>();
for(Contact c : totalDues)
totalDuesWrapperList.add(new contactWrapper(c));
/*Wrapper class*/
public Contact con{get; set;}
public Boolean selected {get;set;}
// public Due__c totalDues{get;set;}
public Due__c dueObj{get;set;}
public Decimal totalDues{get;set;}
public contactWrapper(Contact c)
{
con= c;
selected = false;
totalDues = 0;
dueObj = new Due__c();
}
}
Visual force code:
<apex:dataTable value="{!totalDuesWrapperList}" var="con" id="contactTable2" columnswidth="50px,50px" cellpadding="4" border="1" title="table2">
<apex:column headervalue="Member Name" value="{!con.con.name}" />
<apex:column headervalue="Dues Remaining" value="{!con.Due_Amount__c}" />
</apex:dataTable>
The problem is am unable to access the Due amount as con.Due_Amount__c as i have done for Name(con.name)
Could any one help me in this regard.
The sub query will manifest itself as a collection, so you will need to access individual records in the collection to get the values.
E.g. Get the first Dues Due Amount.
<apex:column headervalue="Dues Remaining" value="{!con.Dues__r[0].Due_Amount__c}" />
Alternatively, you may find it easier to modify the wrapper class to expose the required value as a property.
public Decimal DueAmount {
get {
return con.Dues__r[0].Due_Amount__c;
}
}
See also:
Referencing Apex Maps and Lists
Incidentally, the Salesforce StackExchange is a great place for Salesforce specific questions.

Flex DropDown selection not working when I search for item

so here is the problem that I have so far. I tried to simplify my code so I can attempt to figure this out, but I have had absolutely no luck. I have a viewstack that contains 1 dropdown per stack. They share the same data provider. What I want to do is to select the item contents from the first one. Once I do that, when I click a button to the next stack I have a function that searches from index 0 to the dataprovider length and if the item from the first stack matches the second one, I want to have the second dropdown pick that item up and display it. I have it matching, and I try to select it, but when I run the application it shows up like nothing is selected. Here is what I have:
edit: I got it to work for a simple example, but when I attempt to use it in my more complicated example, on that button click it for some reason resets the value of selectedIndex to -1. How do I prevent this from happening? This is working code for the simple example
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600" applicationComplete="popList()">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.controls.Alert;
[Bindable]
private var myList : ArrayCollection;
[Bindable]
private var selectedItem : String;
[Bindable]
private var index : int;
[Bindable]
private var ind : int;
private function popList() : void {
myList = new ArrayCollection();
stack.initialize();
myList.addItem("1");
myList.addItem("2");
myList.addItem("3");
myList.addItem("4");
myList.addItem("5");
myList.addItem("6");
first.initialize();
second.initialize();
}
private function goNext() : void {
selectedItem = first.selectedItem;
stack.selectedChild = stackb;
for(index = 0; index < myList.length; index++){
var itemNow : String = myList[index].toString();
if(selectedItem == myList[index].toString()){
ind = index;
}
}
}
]]>
</fx:Script>
<mx:ViewStack id="stack" width="862" height="500">
<s:NavigatorContent id="stacka">
<s:DropDownList x="317" y="174" id="first" dataProvider="{myList}"></s:DropDownList>
<s:Button id="next" x="335" y="263" label="Next" click="goNext()"/>
</s:NavigatorContent>
<s:NavigatorContent id="stackb">
<s:DropDownList x="317" y="174" id="second" dataProvider="{myList}" selectedIndex="{ind}"></s:DropDownList>
</s:NavigatorContent>
</mx:ViewStack>
</s:Application>
I didn't try to run the code, but I have a bunch of observations:
First, don't use the same dataProvider for two separate DropDownLists. It causes weird issues. It makes no sense, I have no idea why; but it does. You could dupe the dataProvider by creating a second collection using the same source. Something like this:
-
second.dataProvider = new ArrayCollection(myList.source);
Second, you shouldn't have to manually call the initialize method on either of the DropDownLists. That is highly unusual. The initialize event is fired as part of the creation process; and I assume the initialization method is part of the default event handler. But, firing that event is not the same as having the component go through it's Lifecycle process.
A ViewStack doesn't initialize it's children before the view changes. So, you are probably setting the selectedIndex on the second DropDownList before that DropDownList is initialized, possibly allowing that drop down list to get lost. You can combat this by setting the creationPolicy to all on the ViewStack.
You can probably solve this issue with binding. Something like this.
-
<s:DropDownList x="317" y="174" id="second" dataProvider="{myList}" selectedIndex="{first.selectedIndex}"></s:DropDownList>
Your code to select the next item is comparing an object to a string, so you'll hever the selectedItem.
You could change your loop to something like this:
for(index = 0; index < myList.length; index++){
if(selectedItem == myList[index]){
second.selectedIndex = index;
}
}
But, if you're using the same dataProvider, or a copy of it, why do you even need the loop? Just use the selectedIndex property:
-
second.selectedIndex = first.selectedIndex
Does that help?
Note: StackOverflow makes it real hard to do code formatting inside a list; sorry for not keeping the numbers in my list.

Resources