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
After toying with force:inputField a bit, I found the following code to clear it's value.