<apex:OutputField/>
displays label and text, <apex:inputField/>
displays the both when those are directly under <apex:pageblockSection>
, here those are under <apex:repeat>
tag. You can add <apex:outputLabel/>
before those fields when you are using isCustom logic.
You can try out something like this:
<apex:form rendered="{!isCustom}">
<apex:outputLabel value="{!field.Label}" />
<apex:inputField value=" {!Opportunity[field]}" />
</apex:form>
or
<apex:form rendered="{!isCustom}">
<apex:outputLabel value="{!$ObjectType.Opportunity.fields[field].Label}"/>
<apex:inputField value="{!Opportunity[field]}"/>
<apex:form/>
Following generic code will return the field label
<apex:outputLabel value="{!$ObjectType.CustomObject__c.Fields.Custom_Field__c.Label}" />
In order to bind to something dynamically, you need a reference. Here is a very basic, no-frills, slightly buggy implementation that demonstrates that this basically works.
Notice how I use component.getReference to dynamically link to a field. Also notice how I can bind to the same field twice, which literally lets me modify the same field more than once in real-time, just to prove that they are real references.
With a little more error checking and fact-gathering, this could indeed be a dynamic form with some basic describe data, etc. Notice how I do not use aura:id at all. I simply bound all the fields to a common object, and I could get and retrieve the values at will (in this case, demonstrated through Object.keys). I could also bind this object to, say, a force:recordData to dynamically save the data back to the server, or send it through a server action in Apex.
<aura:application extends="force:slds">
<aura:attribute name="accountRecord" type="Account" default="{ 'sobjectType': 'Account' }" />
<aura:attribute name="edits" type="Aura.Component[]" />
<aura:attribute name="fieldName" type="String" />
<aura:attribute name="output" type="String" />
<aura:handler name="init" value="{!this}" action="{!c.init}" />
{!v.output}
<hr />
{!v.edits}
<ui:inputText value="{!v.fieldName}" />
<ui:button press="{!c.addField}" label="Add" />
<br/>
<ui:button press="{!c.display}" label="Show Data" />
</aura:application>
({
init: function(component, event, helper) {
component.set("v.edits", []);
},
addField: function(component, event, helper) {
var field = component.get("v.fieldName"),
obj = component.get("v.accountRecord");
obj[field] = "";
component.set("v.accountRecord", obj);
$A.createComponent(
"lightning:input", {
value: component.getReference("v.accountRecord."+component.get("v.fieldName")),
label: component.get("v.fieldName"),
type: "Text"
},
$A.getCallback(function(newCmp, status, error) {
var edits = component.get("v.edits");
edits.push(newCmp);
component.set("v.edits", edits);
})
);
},
display: function(component, event, helper) {
var obj = component.get("v.accountRecord");
var results = [];
Object.keys(obj).forEach(function(key) { results.push(key+":"+obj[key])});
component.set("v.output", results.join('\n'));
}
})
Here's a demo of me dynamically binding stuff:
Best Answer
To get the label, you're simply going to need to find the correct label based on the value. Here's one way you can do that:
Where "reduce" is an array function that is used to reduce the values of the array to a single value, in our case, the label that we're interested in looking for. This isn't the only possible solution, but just one of several that would work.