It's about 2 years after I initially touched this issue and today I've found this Known Issue here https://success.salesforce.com/issues_view?id=a1p3A0000008gDzQAI
It confirms my ancient observations from 2015 and confirms also that the Peters fine-grained approach does not work.
For me the recommended workaround is not usefull, since ui:whatever can't out of the box deal with picklists values, field dependencies, translation and localization like number- and date-formats. It can be done, but needs an unjustified amout of complexity and code. My workaround is to use visualforce with it's mature apex:inputField instead.
Here is the Known Issue
<force:inputField>
is not rendering fields on UI when being used
inside <aura:iteration>
tag or inside nested components in Lightning
application
Summary
<force:inputField>
is not rendering fields on UI as expected
when being used inside <aura:iteration>
or inside inner component in
Lightning application
Repro
- Login to your org
- Try creating a sample lightning application
- Create a component with below sample code snippet & try to preview the app
- You will notice the fields doesn't render on the UI as expected.
<aura:component>
<aura:iteration aura:id="iteration" items="{!v.expenses}" var="expenses">
<force:inputField value="{!expenses.Amount__c}"/>
</aura:iteration>
</aura:component>
Workaround
Try using <ui:inputText>
or or
<ui:inputCheckbox>
instead of for rendering input
fields inside <aura:iteration>
or inside inner components
There could be several reasons other than what I am describing here . But here is one for starters. I recently faced a challenge when I was using aura:attribute
of type Map in IE11.
I was sending this map to apex controllers for a DML operation as follows.
Component
<aura:attribute name="sampleMap" type="Map" />
Controller
var myMap = new Map();
myMap['Account'] = { Name : "Test Account"};
myMap['Contact'] = { LastName : "Baron"};
component.set("v.sampleMap",myMap);
var action = component.get("c.serverEcho");
action.setParams({ jsMap : component.get("v.itemMap") });
action.setCallback(this, function(response) {});
$A.enqueueAction(action);
This is an expando method of assigning properties to type Map in javascript and is a valid one when trying to assign dynamic properties to a map/object. Also as you can see I got greedy.
But I ran into issues where I was able to see some extra key : value pairs being added to the Map thus resulting in an Internal server error when trying to perform a DML operation in the apex side.
Looks like IE/aura/closure-compiler(not sure which one) adds certain key-value pairs when using expando properties. You would see something as follows when you debug the incoming values inside apex class.
{_i={}, _s=0, _t=Map, Account={Name=Test Account}, Contact={lastName=Baron}}
If you do not sanitize the keys before performing the DML operation. Then there is a good chance you will run into errors. So I had to sanitize the inputs before I sent it to the apex as follows
sanitizeMap : function(myMap) {
for(var key in myMap){
if(this.startsWith(key,"_",0)){
delete myMap[key];
}
}
return myMap;
},
startsWith : function(haystack,needle, position) {
position = position || 0;
return haystack.indexOf(needle, position) === position;
}
As you see from the code above, this code assumes the properties are going to start with a "_" and if the properties change there is a good chance that these sanitization checks might not work.
Point being - Javascript Map as such is not a strict type and using SObject Type in lightning component and inside the apex controller could save you a ton of time doing sanitization checks for any unseen values introduced during the runtime (might not happen always). Also, it is always better using the typed attributes rather than untyped attributes as it improves the code readability and maintainability over a long run.
Best Answer
The problem is XML does not allow the use of unescaped < or > characters. In Apex (which is where Lightning Components gets its type system) arrays and lists are equivalent. We typically use array notation in attribute defs because you do not have to
< and >
encode the []. Try this instead: