I have been monitoring strange behaviours in my page since I put the pageBlockTables in repeat and te columns of these tables inside a repeat too. hte recors I try to create appears on my page and I can changes the values in the inputFields, but using a button that rerender affect the values in the field. In fact, the values are simply not saved when the rerender append, or when I try to save. While debuging, I found that only the last table is functionning normally, the values are keept with a rerender and the new values in the fields updates the records. So I was wondering if using a repeat only keeps a trace of the last item in the repeat, so the other before are shown and seems to function but doesn't.
here is my VF page simplified:
<apex:page standardController="ProductRequest" recordSetVar="ProductRequest" extensions="ProductRequestController2" tabstyle="ProductRequest">
<apex:form >
<apex:pageBlock title="Manufacturing Products Requests" id="repeat">
<apex:repeat value="{!fieldSetsKeys}" var="fieldSetKey">
<apex:variable var="name" value="{!fieldSetKey}"/>
<apex:outputPanel styleClass="Color">
<apex:pageBlockSection title="{!name}" columns="1">
<apex:pageBlockTable value="{!wrappers[name]}" var="wrapper" id="Table">
<apex:column headerValue="#"> <apex:outputText value="{!wrapper.ident}"/> </apex:column>
<apex:repeat value="{!fieldSets[fieldSetKey]}" var="field">
<apex:column headerValue="{!fieldLabels[field]}">
<apex:inputField value="{!wrapper.product[field]}" />
</apex:column>
</apex:repeat>
<apex:column headerValue="Action on row">
<apex:commandButton value="Clone" action="{!copyRow}" rerender="repeat">
<apex:param name="selectedRow" value="{!wrapper.ident}" assignTo="{!selectedRow}"/>
<apex:param name="productType" value="{!name}" assignTo="{!productType}"/>
</apex:commandButton>
<apex:commandButton value="Delete" action="{!deleteRow}" rerender="repeat">
<apex:param name="selectedRow" value="{!wrapper.ident}" assignTo="{!selectedRow}"/>
<apex:param name="productType" value="{!name}" assignTo="{!productType}"/>
</apex:commandButton>
</apex:column>
</apex:pageBlockTable>
<apex:outputPanel>
<apex:commandButton value="Add Row" action="{!addRows}" rerender="repeat">
<apex:param name="addCount" value="1" assignTo="{!addCount}"/>
<apex:param name="productType" value="{!name}" assignTo="{!productType}"/>
</apex:commandButton>
<apex:commandButton value="rerender" rerender="Table"/>
</apex:outputPanel>
</apex:pageBlockSection>
</apex:outputPanel>
</apex:repeat>
<apex:pageBlockButtons >
<apex:commandButton value="Save" action="{!save}"/>
<apex:commandButton value="Cancel" action="{!cancel}"/>
<apex:commandButton value="{!if(fileUpload == false, 'Save and add files', 'Go back')}" action="{!addAttachementFiles}"/>
</apex:pageBlockButtons>
</apex:pageBlock>
</apex:form>
</apex:page>
the buttons for creating new record works well, but the problem is with the facts that the values are not kept in the inputFileds. I'm pretty sure the problem comes from the repeat, since all my code was working well when I was having a single pageBlockTable and no repeat.
And the controller:
public with sharing class ProductRequestController2 {
public List<ProductRequestWrapper> deletedWrappers {get; set;}
public Map<String, List<ProductrequestWrapper>> wrappers {get; set;}
public map<String, Id> recordTypes {get; set;}
public static map<String, String> parentRecords = new map<String, String>{'Project__c' => 'Project__c', 'Opportunity' => 'Opportunity__c'};
public pageReference recordPage {get; set;}
public Id parentId {get; set;}
public String parentRecordApiName {get; set;}
public Boolean fileUpload {get; set;}
public String productType {get; set;}
public Integer selectedRow {get; set;}
public Integer addCount {get; set;}
public Map<String ,List<String>> fieldSets {get; set;}
public Set<String> fieldSetsKeys {get; set;}
public map<String, String> fieldLabels {get; set;}
public ProductRequestController2(ApexPages.StandardSetController controller) {
recordPage = controller.cancel();
fileUpload = false;
parentId = (Id) ApexPages.currentPage().getParameters().get('id');
if (parentId != null) {
parentRecordApiName = parentRecords.get(parentId.getSObjectType().getDescribe().getName());
deletedWrappers = new List<ProductRequestWrapper>();
getRecordTypes();
for (ProductRequest prod : Database.query('SELECT ' + getUsedFields() +' FROM ProductRequest WHERE ' + parentRecordApiName + ' = :parentId')) {
String productCategoryName = prod.Product_Category__c.toLowerCase();
wrappers.get(productCategoryName).add(new ProductRequestWrapper(wrappers.get(productCategoryName).size(), prod, true));
}
}
}
public void deleteRow() {
if (wrappers.get(productType)[selectedRow].alreadyExisting == true) {
deletedWrappers.add(wrappers.get(productType)[selectedRow]);
}
wrappers.get(productType).remove(selectedRow);
for (Integer i = selectedRow; i < wrappers.get(productType).size(); i++){
wrappers.get(productType)[i].ident = i;
}
}
public void addRows() {
for (Integer i = 0; i < addCount; i++) {
ProductRequest newProduct = new ProductRequest(Product_Category__c = productType, recordTypeId = recordTypes.get(productType));
newProduct.put(parentRecordApiName, parentId);
wrappers.get(productType).add(new ProductRequestWrapper(wrappers.get(productType).size(), newProduct, false));
}
}
public void copyRow() {
ProductRequest copiedProduct = wrappers.get(productType)[selectedRow].product.clone(false, true, false, false);
wrappers.get(productType).add(new ProductRequestWrapper(wrappers.get(productType).size(), copiedProduct, false));
}
public pageReference save() {
List<ProductRequest> productsRequested = new List<ProductRequest>();
List<ProductRequest> productsDeleted = new List<productRequest>();
for (List<ProductrequestWrapper> products : wrappers.values()) {
for (ProductRequestWrapper wrap : products) {
ProductsRequested.add(wrap.product);
system.debug(wrap.product);
}
}
for (ProductRequestWrapper wrap : deletedWrappers) {
productsDeleted.add(wrap.product);
}
try {
upsert ProductsRequested;
} catch(System.DMLException e) {
ApexPages.addMessages(e);
}
if (!productsDeleted.isEmpty()) {
delete productsDeleted;
}
return recordPage;
}
public pageReference cancel() {
return recordPage;
}
public void addAttachementFiles() {
quickSave();
fileUpload = !fileUpload;
}
public void getRecordTypes() {
wrappers = new Map<String, List<ProductrequestWrapper>>();
recordTypes = new Map<String, Id>();
for (Schema.PicklistEntry category : ProductRequest.Product_Category__c.getDescribe().getPicklistValues()) { //to find all picklist values
for (RecordType recordType : [select Id, Name from RecordType where sObjectType='ProductRequest']) { //to find all possible recordType
String categoryName = category.getLabel().toLowerCase();
String recordTypeName = recordType.Name.toLowerCase();
if (recordTypeName.contains(categoryName)) {
wrappers.put(categoryName, new List<ProductrequestWrapper>());
recordTypes.put(categoryName, recordType.Id);
}
}
}
}
public map<String, Schema.FieldSet> getFieldSetMap(){
return Schema.SObjectType.ProductRequest.fieldSets.getMap();
}
private String getUsedFields() {//for getting all the field used on the Vf page with the FieldSet and used that on the SOQL
Set<String> usedFields = new Set<String>{'Id', 'Product_Category__c'};
fieldLabels = new Map<String, String>();
fieldSets = new Map<String ,List<String>>();//
for (String fieldSet : getFieldSetMap().keySet()) {
String fieldSetName = fieldSet.split('_')[0].toLowerCase();//
fieldSets.put(fieldSetName, new List<String>());//
for (Schema.FieldSetMember field : getFieldSetMap().get(fieldSet).getFields()) {
String fieldAPI = field.getFieldPath();
usedFields.add(fieldAPI);
fieldLabels.put(fieldAPI, field.getLabel());
fieldSets.get(fieldSetName).add(fieldAPI);//
}
}
fieldSetsKeys = new Set<String>{'cable', 'plate', 'roadcase', 'pipe', 'custom'};//
for (String lookup : parentRecords.keySet()){
usedFields.add(parentRecords.get(lookup));
}
return String.join((Iterable<String>)usedFields, ' ,');
}
public class ProductRequestWrapper {
public ProductRequest product {get; private set;}
public Integer ident {get; private set;}
public Boolean alreadyExisting {get; private set;}
public Attachment file {
get { if (file == null)
file = new Attachment();
return file;}
set;}
public ProductRequestWrapper(Integer inIdent, ProductRequest ExistingProduct, Boolean exist) {
ident = inIdent;
alreadyExisting = exist;
product = ExistingProduct;
}
}
}
wrappers