If you really wanted to hide error messages you could do something like this:
Component:
<div>
<lightning:input label="First Name" aura:id="firstName" required="true"/>
<lightning:button onclick="{!c.hideErrors}">Hide Errors</lightning:button>
</div>
Controller:
hideErrors : function(component, event, helper) {
var el = component.find("firstName");
$A.util.removeClass(el, "slds-has-error"); // remove red border
$A.util.addClass(el, "hide-error-message"); // hide error message
}
Style:
.THIS .hide-error-message > .slds-form-element__help {
.THIS .hide-error-message > .slds-form-element > .slds-form-element__help {
display: none;
}
But the internal DOM structure and class names of base components are subject to change so this isn't a totally robust solution.
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
we had a similar requirement and the way we fixed it was to put the entire form inside an aura:if and changed the Boolean condition. this essentially meant the dom got re-created again but we were able to reset 4 to 5 fields in one condition.
Helpercode:
We also did not have the need to touch each field this way instead controlled everything through an aura:if.Not the cleanest or most-efficient solution but till we get a reset function in lightning-input in the future we will use this :)