[SalesForce] Dynamic Visualforce Input Field

I am trying to make a dynamic visualforce input field. Actually, I have already made it before, however I am trying to clean up code so that I only need one input field per page.

I have a table on the page where I also have an apex:repeat tag, rendering information from various records of an object. Inside that I have components that include the following code:

<a style="font-weight: bold;" href="#" onClick="updateCurrent('{!pricing.Id}'); updateInput(); showInput();">Supply ID</a>

Note the following relevant page code:

<script>
    function showInput() {
        document.getElementById('input-screen').style.display = "block";
    }
</script>

<apex:actionFunction name="updateCurrent" action="{!updateCurrent}" rerender="input-box">
    <apex:param name="Current" value="" />
</apex:actionFunction>

<apex:actionFunction name="updateInput" action="{!dead}" reRender="input-field"/>

<div id="input-screen" class="input-box">
    <div class="input-content">
        <p style="font-size: 18px; font-family: 'Arial Black', Gadget;">Insert new ID</p>
        <apex:actionRegion>
            <apex:inputField id="input-field" value="{!current_record[current_id_field]}" html-placeholder="Product: {!current_record.Name}"/>
        </apex:actionRegion>
        <button onClick="hideInput();">Close</button>
    </div>
</div>

And the relevant controller code:

public Pricing_Info__c current_record {get;set;}
public String current_id_field {get;set;}

// The constructor 
public PricingInfo () {
   // ... code here to populate a list of Pricing_Info__c ... 
   this.current_record = pricing_objects.get(0);
   this.current_id_field = 'Name';
}

public PageReference updateCurrent() {
    System.debug('Updating Current.  Note that the \'Current\' parameter is: ' + Apexpages.currentPage().getParameters().get('Current'));
    for (Pricing_Info__c o : pricing_objects) {
        System.debug('Checking if ' + o.Id + ' = \'Current\' parameter');
        if (o.Id == (id) Apexpages.currentPage().getParameters().get('Current')) {
            System.debug(o.Id + ' does equal ' + (id) Apexpages.currentPage().getParameters().get('Current'));
            this.current_record = o;
        }
    }
    System.debug('Current record is: ' + current_record);
    return null;
}

Debug log example:

11:09:10:030 USER_DEBUG [183]|DEBUG|Updating Current. Note that the 'Current' parameter is: a2e36000000yS1YAAU

11:09:10:031 USER_DEBUG [185]|DEBUG|Checking if a2e36000000yS1YAAU = 'Current' parameter

11:09:10:031 USER_DEBUG [187]|DEBUG|a2e36000000yS1YAAU does equal a2e36000000yS1YAAU

11:09:10:031 USER_DEBUG [185]|DEBUG|Checking if a2e36000000yS1gAAE = 'Current' parameter

11:09:10:032 USER_DEBUG [191]|DEBUG|Current record is: Pricing_Info__c:{Id=a… (NOT THE SAME AS DEFAULT IN CONSTRUCTOR)

But here is the problem:
The input field does work for the sObject and field defined in the constructor, but never changes. Even if the debug log says that the 'current_record' has changed, the input field does not change. I am rerendering the input field, and I've tried the whole div, every time I am changing the div's display style, but the input field does not change.

I am very lost. If you need any more code or any elaboration I am glad to deliver.

tl;dr:
How do you make a dynamic input field such that you change a controller sObject, via clicking something on the visualforce page, to be relevant to whatever you clicked, and the input field changes as well? reRendering did not work, even though the sObject was changed. (sorry for the run-on sentence)

Best Answer

Any Rerender attribute you use in vf page, should point to an id of an apex component like <apex:outputPanel />,<apex:form />,<apex:pageBlock />,...so on.

<apex:actionFunction ... rerender="inputScreenPanel"></apex:actionFunction>

<apex:outputPanel id="inputScreenPanel">
    //apex components to be rerendered
    <div id="input-screen" class="input-box">
       ...
    </div>
</apex:outputPanel> 

NOTE : <button /> tag inside <apex:form /> behaves like form submitter button(<button type="submit"/>), so you should explicitly set the type="button" as shown in the example.

Here is an simple example to rerender dynamic input field:

VF:

<apex:page controller="AccountController">
    <apex:form>
        <button type="button" onclick="update()">update</button>

        <apex:outputPanel id="inputScreenPanel">
            <apex:inputField id="input-field" value="{!currAcc[apiName]}"/>
        </apex:outputPanel>

        <apex:actionFunction name="update" action="{!updateAcc}" reRender="inputScreenPanel">
        </apex:actionFunction>
    </apex:form>
</apex:page>

Controller :

public with sharing class AccountController {
    public List<Account> acclist{get;set;}
    public Account currAcc {get;set;}
    public String apiName {get;set;}

    public AccountController(){
        acclist = [SELECT Id,Phone,Name FROM Account WHERE Id IN ('00128000002kbKS','00128000002kbKT')];
        currAcc = accList[0];
        apiName = 'Name';
    }

    public PageReference updateAcc(){
        currAcc = acclist[1];
        return null;
    }
}
Related Topic