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:
I don't think this is appropriate way to do so in lightning.
One way to do say by firing a event from inner component whenever the value changes in inner component. You can fire event with both value and index and store that information in outer component.
Another way to do so is by using double binding principle of lightning.
<aura:if isTrue="{!v.configuration.Data_Type__c=='text'}">
<div class="slds-form-element__control slds-m-top_xx-small slds-m-bottom_xx-small slds-p-bottom_small">
<ui:inputText label="{!v.configuration.Field_Label__c}" class="slds-input " value="{!v.configuration.value}" aura:id="input"/>
</div>
</aura:if>
<aura:if isTrue="{!v.configuration.Data_Type__c=='number'}">
<div class="slds-form-element__control slds-m-top_xx-small slds-m-bottom_xx-small slds-p-bottom_small">
<ui:inputNumber label="{!v.configuration.Field_Label__c}" class="slds-input " value="{!v.configuration.value}" aura:id="input"/>
</div>
</aura:if>
Now value of each inner component will get set in there configuration object.
saveData : function(component, event, helper){
var configurations = component.get("v.configurations");
//console.log(configurations);
for(var i=0; i<configurations.length; i++){
console.log(configurations[i].value);
}
}
Best Answer
Currently I do not have option to select text of
lightning:textarea
as onlyfocus
andshowHelpMessageIfInvalid
methods are available for lightning:textarea. You can use html tagtextarea
, as proxySecureElement
object supportsselect
method and proxySecureDocument
supports bothqueryCommandSupported
andexecCommand
.Component
Controller