2

I have a simple wrapper class with an sobject and a flag that indicates if it was updated. If I have two or more wrapper class elements, the action support always updates the last one, even when the first one is the one being updated.

Here is the controller:

public class StudentClassPage {

/* Variables & Constants */

public static final String ID_PARAM = 'id';
public static final Integer NUM_OF_BLANK_COURSES = 1;

public List<CourseData> courses { get; set; } { courses = new List<CourseData>(); }
public Contact student { get; set; }

private ApexPages.StandardController controller;

/* Constructor */

public StudentClassPage(ApexPages.StandardController control) {
    controller = control;
    student = queryStudent(controller.getId());
    courses = queryCourses(controller.getId());
    addCourses();
}

/* Actions Methods */

public void addCourses() {
    for (Integer i = 0; i < NUM_OF_BLANK_COURSES; i++) {
        courses.add(new CourseData(new Student_Course__c(), student.Id));
    }
}

public PageReference save() {
    List<Student_Course__c> updateList = new List<Student_Course__c>();
    for (CourseData cr : courses) {
        if (cr.isChanged) {
            updateList.add(cr.course);
        }
    }
    upsert updateList;

    return controller.view();
}

/* Static Support Methods */

private static List<CourseData> queryCourses(Id studentId) {
    List<CourseData> crs = new List<CourseData>();
    for (Student_Course__c sc : [select Contact__c, School_Year__c
                                 from Student_Course__c
                                 where Contact__c = :studentId
                                 ]) {
        crs.add(new CourseData(sc, sc.contact__c));
    }

    return crs;
}

private static Contact queryStudent(Id studentId) {
    Contact studnt = new Contact();
    for (Contact st : [select
                            Name
                          , firstName
                          , lastName
                       from Contact
                       where Id = :studentId
                       ]) {
        studnt = st;
    }

    return studnt;
}

/* Inner Class */

public class CourseData {

    public Student_Course__c course { get; set; } //{ course = new Student_Course__c(); }
    public Boolean isChanged { get; set; }

    public CourseData(Student_Course__c sc, Id studentId) {
        course = sc;
        course.contact__c = studentId;
        isChanged = false;
    }

    public void changedRecord() {
        isChanged = true;
    }
}

}

Here is the VF page:

<apex:page standardController="Contact" extensions="StudentClassPage" tabStyle="Student_Course__c">

<apex:form id="theForm" >

<apex:sectionHeader title="Student Classes" subTitle="{!student.name}" id="title" />

<apex:messages />
    <apex:pageBlock >
    <apex:commandButton value="Save" action="{!save}" />
        <apex:pageBlockTable value="{!courses}" var="cr" id="table" >
            <apex:column headerValue="First Name" >
                <apex:outputField value="{!student.FirstName}" />
            </apex:column>
            <apex:column headerValue="Last Name" >
                <apex:outputField value="{!student.LastName}" />
            </apex:column>
            <apex:column headerValue="School Year" >
                <apex:inputField value="{!cr.course.School_Year__c}" >
                    <apex:actionSupport event="onchange" action="{!cr.changedRecord}" />
                </apex:inputField>
            </apex:column>
        </apex:pageBlockTable>
    </apex:pageBlock>

</apex:form>

</apex:page>

The actionsupport calls the changedRecord method, but it is always for the last CourseData element, even if the change is being made on the first one.

Can anyone help me correct this behavior.

Thanks!

1 Answer 1

2

Just create a new method to set the isChanged parameter for the current entry. You will need the array number of the entry, for that we will use apex:variable:

Visualforce:

<!-- Here we will use an extra variable to define a row number -->
<apex:outputPanel id="panelWithVar">
    <apex:variable value="{!0}" var="rowNumber" />
</apex:outputPanel>

<apex:messages />
<apex:pageBlock >
<apex:commandButton value="Save" action="{!save}" />
    <apex:pageBlockTable value="{!courses}" var="cr" id="table" >
        <apex:column headerValue="First Name" >
            <apex:outputField value="{!student.FirstName}" />
        </apex:column>
        <apex:column headerValue="Last Name" >
            <apex:outputField value="{!student.LastName}" />
        </apex:column>
        <apex:column headerValue="School Year" >
            <apex:inputField value="{!cr.course.School_Year__c}" >
                <apex:actionSupport event="onchange" action="{!setNewValue}" reRender="table, panelWithVar">
                    <apex:param name="p1" value="{!rowNumber}" assignTo="{!rowNumber}"/>
                </apex:actionSupport>
            </apex:inputField>
            <apex:variable var="rowNumber" value="{!rowNumber + 1}" />
        </apex:column>
    </apex:pageBlockTable>
</apex:pageBlock>

Apex:

public PageReference setNewValue(){
    courses.get(rowNumber).isChanged = true;  
    return null;
}
2
  • Thanks for your solution. Can you explain why my idea would not work? Thanks.
    – JimH
    Commented Aug 7, 2013 at 16:15
  • I think because you iterate a list and each of action support tryes to call the same method. Commented Aug 7, 2013 at 18:22

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .