function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Frank N.Frank N. 

Complex: Inputfields in repeater not updating fields after pressing save.

Hi everyone,

 

I have a sort-of complex situation as follows. I have a custom Wrapper object, this wrapper contains a custom header object, and its corresponding header_items. The items are linked to the header in a master-child relationship (1 to many).

 

The items are stored in a map, and I have an exposed property that returns the items in this map:

private Map<Id, Item__c> mItems;

public List<Item__c> items {get { return mItems.values(); } set;}

 

We can have multiple Wrapper objects therefore I have a seperate Wrapper_Basket class that contains multiple Wrapper objects. Similar to the Wrapper item I use a map to get a quick reference using an ID.

private Map<String, Wrapper> mSOWrapper;

public List<Wrapper> wrappers{ get { return mSOWrapper.values(); } set;}

 In my Visualforce page I have the following:

 

<apex:form>
   <apex:outputPanel id="panelBasket">
       <apex:repeat value="{!basket.wrappers}" var="wrapper" >
            {!wrapper.header.ID}
	     
              <apex:repeat value="{!wrapper.items}" var="item" id="theRepeat">  
				      		 	
	               <apex:inputfield value="{!wrapper.Quantity__c}"/>
						        		
	      </apex:repeat>
       </apex:repeat>

   <apex:CommandButton value="Save" action="{!updateQuantities}"  immediate="true" />
  </apex:outputPanel>
</apex:form>

 

When I press the save button the following function gets called, which calls the update function within the wrapper objects (it works, I check debug and I see the function gets called):

 

//In controller:
public void updateQuantities(){
    basket.update();
}


//In basket class, update items and header:
public void updateBasket(){
	for(Wrapper wrapper : this.wrappers){
			update wrapper.items;
			update wrapper.header;
		} 
	}

However. This does not update the new values I enter in the quantities inputfield. I always figured Salesforce would bind the quantity__c field in my repeater and updates takes care of the rest. I believe it may be my setup thats not working.

 

Can anyone shed any light on this?

 

Best,

Frank

Best Answer chosen by Admin (Salesforce Developers) 
bob_buzzardbob_buzzard

You have the immediate attribute set to true for your save button - this discards any changes entered by the user.  If you remove that, your changes will be updated in the wrapper class as you expect.

All Answers

bob_buzzardbob_buzzard

You have the immediate attribute set to true for your save button - this discards any changes entered by the user.  If you remove that, your changes will be updated in the wrapper class as you expect.

This was selected as the best answer
Frank N.Frank N.

Thanks!!! I've been looking for a while to find this solution but never looked at my command button! :smileyvery-happy:

Prash2Prash2

Bob - I am trying to do similar to what you answered here. Although I do not have immediate set to TRUE in my commandbutton, yet I do not get the updated values back in my controller method. I am relatively new to Visual Force(VF) and used wrappers successfully in the past to display data in grid. However this is the first time, I am trying to update some data from it. Any help or pointers would be greatly appreciated.

 

Description - For weekly time entry project, what are we trying to do is to allow user to select a week they are trying to enter the time against. I display the list of projects in a grid based on project resource assignment and the projects that are marked as "Administration" project. If they already have time entered against some day of the week for these projects, display that, else '0'. I am using wrapper to flatten the records. I am using dataTable in VF and have the columns as InputText. For some reason when I updates the data in the grid and press "Post", the controller method doesn't have the updated data. Please review saveChanges() method in my controller and VF page to see what I might be doing wrong. The debug statements in my saveChanges() loop retains the old values that were derived in getWeeklyTimeEntries() method. What I am doing wrong?

 

P.S. In other examples that I found, users seem to declare the variable to use in dataTable as PRIVATE FINAL in order to retrieve and update. But as I derive this wrapper grid, I can't do that.

 

Wrapper Class -

public withsharingclass WeeklyTimeEntry_Wrapper {

public Id projectId {get;set;}

public String projectName {get;set;}

public Decimal sunday {get;set;}

public Decimal monday {get;set;}

public Decimal tuesday {get;set;}

public Decimal wednesday {get;set;}

public Decimal thursday {get;set;}

public Decimal friday {get;set;}

public Decimal saturday {get;set;}

}

 

 

The message seem to be longer than allowed. Let me post the Controller and Visualforce code in second message.

Prash2Prash2

part - 2

 

Controller Class -

public class WeeklyTimeEntry_Controller {
private final User loggedInUser;
public String selectedWeek{get; set;}
public Date weekStartDate{get; set;}
public Date weekEndDate{get; set;} //WeekStartDate will be Sunday; and weekEndDate will be Saturday
public List<WeeklyTimeEntry_Wrapper> userWeeklyTime{get; set;} // The variable gets derived in getWeeklyTimeEntries() to display as Grid. Also, it is used to update changes in saveChanges().
//private final List<WeeklyTimeEntry_Wrapper> userWeeklyTime{get;set;}
public Map<String, Time_Record__c> postedProjectTimesMap; //The variable stores the time record that were retrieved for the user. It is used to compare with userWeeklyTime and determine Insert Vs. Updates.
public Id UserId, ContactId;
public String weekChanged{get; // *** setter is NOT being called ***
set {
weekChanged = value;
}
}

public WeeklyTimeEntry_Controller(ApexPages.StandardController stdController) {
this.loggedInUser= (User)stdController.getRecord();
UserId = loggedInUser.Id;
ContactId = [Select contactId From user WHERE Id = :UserId].ContactId;
weekChanged = 'TRUE';
}

public void saveChanges() {
system.debug('In saveChanges');
Decimal sunday = 0, monday = 0, tuesday = 0, wednesday = 0, thursday = 0, friday = 0, saturday = 0;
List<Time_Record__c> updateTimeRecordList = new List<Time_Record__c> ();
List<Time_Record__c> insertTimeRecordList = new List<Time_Record__c> ();
Time_Record__c updateTimeRecord;
Time_Record__c insertTimeRecord;


//Cycle through the list of updated TimeEntries
for(WeeklyTimeEntry_Wrapper updatedWeeklyTime2 : userWeeklyTime) {
system.debug('In updatedWeeklyTime2.projectName:'+ updatedWeeklyTime2.projectName);
system.debug('In updatedWeeklyTime2.projectId:'+ updatedWeeklyTime2.projectId);
system.debug('In updatedWeeklyTime2.sunday:'+ updatedWeeklyTime2.sunday);
system.debug('In updatedWeeklyTime2.monday:'+ updatedWeeklyTime2.monday);
}

} // End of saveChanges() method


public List<SelectOption> getWeeks() {
List<SelectOption> options = new List<SelectOption>();
// if (weekChanged == 'TRUE') {
// Get the weeks from the beginning of last year till this week and add it to SelectOption
Date startDate = date.newInstance(date.today().year()-1, 1, 1).toStartOfWeek();
Date endDate = startDate.addDays(6);
Date nextWeekStartDate = date.today().toStartOfWeek();
String pickListValue = string.valueOf(startDate) + ':' + string.valueOf(endDate);
String pickListLabel = 'Sunday, ' + string.valueOf(startDate);
options.add(new SelectOption(pickListValue, pickListLabel ));
selectedWeek = pickListValue;
Do {
startDate = endDate.addDays(1);
endDate = startDate.addDays(6);
pickListValue = string.valueOf(startDate) + ':' + string.valueOf(endDate);
pickListLabel = 'Sunday, ' + string.valueOf(startDate);
options.add(new SelectOption(pickListValue, pickListLabel ));
} While (nextWeekStartDate > startDate);
weekChanged = 'FALSE';
setWeek();
// }
return options;
}

public void setWeek() {
Integer li_splitDate;
this.selectedWeek = selectedWeek;
li_splitDate = selectedWeek.indexOf(':',0);
weekStartDate = Date.valueOf(selectedWeek.substring(0, li_splitDate));
weekEndDate = Date.valueOf(selectedWeek.substring(li_splitDate+1, selectedWeek.length()));
getWeeklyTimeEntries();
}

public List<WeeklyTimeEntry_Wrapper> getWeeklyTimeEntries() {
List<Team_Member__c> assignedProjects = [Select t.team_member__c, t.Contractor__c, t.Project__c, t.Project__r.Name, t.Project__r.Project_Status__c from Team_Member__c t Where t.Project__r.Project_Status__c IN ('Active','Complete') AND ((t.Contractor__c = :ContactId AND t.Contractor__c != null) OR (t.team_member__c = :UserId AND t.team_member__c != NULL))];
postedProjectTimesMap = new Map<String, Time_Record__c> ([Select t.Project__r.Name, t.name, t.Team_Member__c, t.Contractor__c, t.Hours__c, t.Id, t.Project__c, t.Start_Date__c from Time_Record__c t WHERE ((t.Contractor__c = :ContactId AND t.Contractor__c != null) OR (t.Team_Member__c = :UserId AND t.Team_Member__c != null))AND t.Start_Date__c >= :weekStartDate AND t.Start_Date__c <= :weekEndDate ORDER BY t.Project__r.Name, t.Start_Date__c]); //AND t.Start_Date__c >= 2011-11-17 AND t.Start_Date__c <= 2012-02-17];
String lastProjectInLoop = '';
Id lastProjectIdInLoop;
Decimal sunday = 0, monday = 0, tuesday = 0, wednesday = 0, thursday = 0, friday = 0, saturday = 0;
WeeklyTimeEntry_Wrapper weeklyTimeEntry = new WeeklyTimeEntry_Wrapper();
Map<String, WeeklyTimeEntry_Wrapper> weeklyTimeEntriesMap = new Map<String, WeeklyTimeEntry_Wrapper> ();
List<Time_Record__c> postedProjectTimes = postedProjectTimesMap.Values();

//Loop through posted Project Time to see if there's already entered time against it.
for (Time_Record__c postedProjectTime : postedProjectTimes) {
Date dateToCompareWithPostedTime = postedProjectTime.Start_Date__c.toStartOfWeek();
// If processing project is different than in previous iteration, add the values to the wrapper and reset the wrapper.
if (lastProjectInLoop != postedProjectTime.Project__r.Name && lastProjectInLoop != '') {
weeklyTimeEntry.projectId = lastProjectIdInLoop;
weeklyTimeEntry.projectName = lastProjectInLoop;
weeklyTimeEntry.sunday = sunday;
weeklyTimeEntry.monday = monday;
weeklyTimeEntry.tuesday = tuesday;
weeklyTimeEntry.wednesday = wednesday;
weeklyTimeEntry.thursday = thursday;
weeklyTimeEntry.friday = friday;
weeklyTimeEntry.saturday = saturday;
weeklyTimeEntriesMap.put(weeklyTimeEntry.projectId, weeklyTimeEntry);
//Reset the variables
weeklyTimeEntry = new WeeklyTimeEntry_Wrapper();
sunday = 0;
monday = 0;
tuesday = 0;
wednesday = 0;
thursday = 0;
friday = 0;
saturday = 0;
}

// Loop throgh 7 days, see which one matches "postedProjectTime.Start_Date__c" and update the weeklyTimeEntry.Day time accordingly.
for (Integer dayNumber = 1; dayNumber < 8; dayNumber++) {
if (dateToCompareWithPostedTime == postedProjectTime.Start_Date__c) {
if (dayNumber == 1) { //Sunday
sunday = postedProjectTime.hours__c;
} else if (dayNumber == 2) { //Monday
monday= postedProjectTime.hours__c;
} else if (dayNumber == 3) { //Tuesday
tuesday = postedProjectTime.hours__c;
} else if (dayNumber == 4) { //Wednesday
wednesday = postedProjectTime.hours__c;
} else if (dayNumber == 5) { //Thursday
thursday = postedProjectTime.hours__c;
} else if (dayNumber == 6) { //Friday
friday = postedProjectTime.hours__c;
} else if (dayNumber == 7) { //Saturday
saturday = postedProjectTime.hours__c;
}
}
dateToCompareWithPostedTime = dateToCompareWithPostedTime.addDays(1);
}
lastProjectInLoop = postedProjectTime.Project__r.Name;
lastProjectIdInLoop = postedProjectTime.Project__c;
}

// Get all the projects where this contact is assigned as team-member and instantiate weekly time entry for it.
for (Team_Member__c teamMemberProject : assignedProjects) {
//Check if the processing project has entry in TimeEntry map. If it does NOT, add it.
if (!weeklyTimeEntriesMap.containsKey(teamMemberProject.Project__r.Name)) {
weeklyTimeEntry = new WeeklyTimeEntry_Wrapper();
weeklyTimeEntry.projectId = teamMemberProject.Project__c;
weeklyTimeEntry.projectName = teamMemberProject.Project__r.Name;
weeklyTimeEntry.sunday = 0;
weeklyTimeEntry.monday = 0;
weeklyTimeEntry.tuesday = 0;
weeklyTimeEntry.wednesday = 0;
weeklyTimeEntry.thursday = 0;
weeklyTimeEntry.friday = 0;
weeklyTimeEntry.saturday = 0;

weeklyTimeEntriesMap.put(weeklyTimeEntry.projectId, weeklyTimeEntry);
}
}

//The list of TimeEntry is now ready, assign it to list so it can be used to retrieve the grid
userWeeklyTime = weeklyTimeEntriesMap.Values();
RETURN userWeeklyTime;

}


}

 

Visual Force -

<apex:page standardController="user" extensions="WeeklyTimeEntry_Controller" >

<apex:form id="tLineEntryForm">
<apex:pageBlock id="tEntryWeekSelectionPageBlock">
<apex:actionRegion >
<apex:pageBlockSection id="selectedWeek" title="Project List for {!$User.FirstName} {!$User.LastName}" columns="2" collapsible="false">
<apex:pageBlockSectionItem id="selectedWeek">
<apex:outputLabel for="selectedWeek">Week Beginning</apex:outputLabel>
<apex:panelGroup >
<apex:selectList value="{!selectedWeek}" multiselect="false" size="1" onchange="weekSelectedJS">
<apex:selectOptions value="{!Weeks}"/>
</apex:selectList>
</apex:panelGroup>
</apex:pageBlockSectionItem>
<apex:commandButton value="Go" action="{!setWeek}" rerender="timeEntrySection" >
<apex:param name="weekChanged" value="TRUE" assignTo="{!weekChanged}"/>
</apex:commandButton>
</apex:pageBlockSection>
</apex:actionRegion>

<apex:pageBlockSection id="timeEntrySection" title="Time Entry for {!$User.FirstName} {!$User.LastName} Dates Between {!weekStartDate} and {!weekEndDate}" columns="8" collapsible="false">
<apex:dataTable value="{!userWeeklyTime}" var="dtWeeklyTime" id="theTable" rowClasses="odd,even" styleClass="tableClass">

<apex:column >
<apex:facet name="header">Project</apex:facet>
<apex:facet name="footer">Total</apex:facet>
<apex:outputText value="{!dtWeeklyTime.projectName}" />
</apex:column>
<apex:column >
<apex:facet name="header">Sunday</apex:facet>
<apex:inputText value="{!dtWeeklyTime.sunday}" disabled="FALSE"/>
</apex:column>
<apex:column >
<apex:facet name="header">Monday</apex:facet>
<apex:inputText value="{!dtWeeklyTime.monday}"/>
</apex:column>
<apex:column >
<apex:facet name="header">Tuesday</apex:facet>
<apex:inputText value="{!dtWeeklyTime.tuesday}"/>
</apex:column>
<apex:column >
<apex:facet name="header">Wenesday</apex:facet>
<apex:inputText value="{!dtWeeklyTime.wednesday}"/>
</apex:column>
<apex:column >
<apex:facet name="header">Thursday</apex:facet>
<apex:inputText value="{!dtWeeklyTime.thursday}" />
</apex:column>
<apex:column >
<apex:facet name="header">Friday</apex:facet>
<apex:inputText value="{!dtWeeklyTime.friday}"/>
</apex:column>
<apex:column >
<apex:facet name="header">Saturday</apex:facet>
<apex:inputText value="{!dtWeeklyTime.saturday}"/>
</apex:column>
</apex:dataTable>
</apex:pageBlockSection>
<apex:actionRegion >
<apex:commandButton value="Post" action="{!saveChanges}" rerender="timeEntrySection" immediate="false"/>
</apex:actionRegion>
</apex:pageBlock>
</apex:form>
</apex:page>

Prash2Prash2

Just wanted to tell that the issue was with actionRegion tag. Encapsulating the dataTable into the actionRegion tag solved the issue.

WillysWillys

 

Thank you very much prakash.......

When dynamically adding value to a repeater controller both commandLink as well as the rerender control should come under one apex:actionRegion.