function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Quddus Ololade 4Quddus Ololade 4 

Unable to use my wrapper class in Lightning component API version 42

Below Code:
public class parentclass{

    public class Model{
        @AuraEnabled public String year {get;set;}
        @AuraEnabled public Map<Integer, Decimal> dataMap {get;set;}
    }
}

Component Code:
<aura:component controller="parentclass" implements="flexipage:availableForAllPageTypes,force:hasRecordId" access="global">
   
 <aura:attribute name="listVehicles" type="parentclass.Model[]" />
Error: while saving the component: Failed to save undefined: Invalid <aura:attribute> type: Model

This is speacially on the lightning component API 42 version, I have old component which is on 40 API version works absolutely fine.
Is this is a bug or not the right way to use wrapper any more in lightning ?

Any ideas appreciated !
Thanks
Best Answer chosen by Quddus Ololade 4
Ashif KhanAshif Khan
Hi Quddus Ololade, 
I worked on your code review it

demo.app
<aura:application extends="force:slds">
    <c:ModelClass />
</aura:application>
ModelClass .cmp
<aura:component controller='ModelClass'>
    <aura:attribute name="listVehicles" type="ModelClass[]" />
    <aura:attribute name="listVehiclestoshow" type="List" />
    <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
<div align='center'>
                <b>listVehicles Data</b>
    </div> 
    <aura:iteration items="{!v.listVehiclestoshow}" var="summary">
                    <b>{!summary.year}</b><br/>

                <aura:iteration items="{!summary.dataMap}" var="value1">
                    {!value1.integerVal}--->{!value1.decimalVal}<br/>
                </aura:iteration>
                    ---------------------------------------
                    <br/>
            </aura:iteration>
</aura:component>




ModelClassController.js
 
({
    doInit : function(component, event) {
        var action = component.get("c.getModels");
        action.setCallback(this, function(a) {
        
          component.set("v.listVehicles",  a.getReturnValue());
             var listVehicles=a.getReturnValue();
            var modelList = [];
            for(var i=0; i<listVehicles.length;i++){
               var yr=listVehicles[i].year;
               var lst=listVehicles[i].dataMap;
                var modelListAsYear = [];
                 for(var key in lst){
                    modelListAsYear.push({integerVal:key,decimalVal:lst[key]});
                }
                modelList.push({year:yr,dataMap:modelListAsYear});
            }
         
         component.set("v.listVehiclestoshow",  modelList);
        });
        $A.enqueueAction(action);
    }
})




ModelClass.apxc
 
public class ModelClass{
@AuraEnabled public String year {get;set;}
@AuraEnabled public Map<Integer, Decimal> dataMap {get;set;}
    public ModelClass(String y, Map<Integer, Decimal> d){
        year = y;
        dataMap = d;
    }

    @AuraEnabled
    public static List<ModelClass> getModels(){
        List<ModelClass> ModelClassList=new List<ModelClass>();
        Map<Integer, Decimal> mp= new Map<Integer, Decimal>();
        mp.put(1, 1831);
        mp.put(2, 1571);
        mp.put(3, 1569);
        mp.put(4, 1111.54);
        mp.put(5, 1137.12);
        mp.put(6, 1135.29);
        String yr='2016';
        ModelClass mm=new ModelClass(yr,mp);
        ModelClassList.add(mm);
        
        Map<Integer, Decimal> mp2= new Map<Integer, Decimal>();
        mp2.put(7, 1160);
        mp2.put(8, 1138);
        String yr2='2017';
                ModelClass mm2=new ModelClass(yr2,mp2);
        ModelClassList.add(mm2);
        
        return ModelClassList;
    }
}

view

User-added image

working well in my dev org.

All Answers

GauravGargGauravGarg
Can you try changing the API version to 40.0. 
Ashif KhanAshif Khan
Hi Quddus Ololade,

You cannot use inherited class attribute type 
instead of this you can use 
<aura:attribute name="listVehicles" type="Object[]" />

Let me know, is it work for you.
Quddus Ololade 4Quddus Ololade 4
@gaurav: it works fine in 40, but in 42 it didn work, i read this article which says "https://trailhead.salesforce.com/modules/lex_dev_lc_vf_tips/units/lex_dev_lc_vf_tips_apex#Tdxn4tBK-heading4" which says it is not possible to have inner class.

 
GauravGargGauravGarg
I hope you can use "String" or "Object[]" instead of showing inner class. 

Pass values in JSON format and deserialize it in JS Controller 

Thanks,
Gaurav
Skype: gaurav62990
GauravGargGauravGarg

I can understand that Wrapper isn't working in your case "42.0" version, but we can still implement MAP and List in the same class. Can you check the below link and try to convert your JS controller to get the job done. 

https://salesforce.stackexchange.com/questions/140608/how-to-iterate-over-map-in-salesforce-lightning-component/140630

Thanks,

Gaurav
Skype: gaurav62990

sfdcMonkey.comsfdcMonkey.com
hi Quddus Ololade,
check out below post :
http://sfdcmonkey.com/2017/07/06/use-wrapper-class-lightning-component/
there are 2 solution for your problem :
1. create your inner/wrapper class as a new class. (cut your wrapper class code from main class and create a new parent level class with wrapper class code and then in your aura:attribute you can directly use parent level wrapper class as attribute type).

2. don't touch apex code, just update aura :attribute type as object type :
<aura:attribute name="listVehicles" type="object[]" />
i hope it helps you.
 Let me inform if it helps you and kindly mark it best answer if it helps you
thanks

sfdcmonkey.com

 
Ashif KhanAshif Khan
Hi Quddus Ololade, 
I worked on your code review it

demo.app
<aura:application extends="force:slds">
    <c:ModelClass />
</aura:application>
ModelClass .cmp
<aura:component controller='ModelClass'>
    <aura:attribute name="listVehicles" type="ModelClass[]" />
    <aura:attribute name="listVehiclestoshow" type="List" />
    <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
<div align='center'>
                <b>listVehicles Data</b>
    </div> 
    <aura:iteration items="{!v.listVehiclestoshow}" var="summary">
                    <b>{!summary.year}</b><br/>

                <aura:iteration items="{!summary.dataMap}" var="value1">
                    {!value1.integerVal}--->{!value1.decimalVal}<br/>
                </aura:iteration>
                    ---------------------------------------
                    <br/>
            </aura:iteration>
</aura:component>




ModelClassController.js
 
({
    doInit : function(component, event) {
        var action = component.get("c.getModels");
        action.setCallback(this, function(a) {
        
          component.set("v.listVehicles",  a.getReturnValue());
             var listVehicles=a.getReturnValue();
            var modelList = [];
            for(var i=0; i<listVehicles.length;i++){
               var yr=listVehicles[i].year;
               var lst=listVehicles[i].dataMap;
                var modelListAsYear = [];
                 for(var key in lst){
                    modelListAsYear.push({integerVal:key,decimalVal:lst[key]});
                }
                modelList.push({year:yr,dataMap:modelListAsYear});
            }
         
         component.set("v.listVehiclestoshow",  modelList);
        });
        $A.enqueueAction(action);
    }
})




ModelClass.apxc
 
public class ModelClass{
@AuraEnabled public String year {get;set;}
@AuraEnabled public Map<Integer, Decimal> dataMap {get;set;}
    public ModelClass(String y, Map<Integer, Decimal> d){
        year = y;
        dataMap = d;
    }

    @AuraEnabled
    public static List<ModelClass> getModels(){
        List<ModelClass> ModelClassList=new List<ModelClass>();
        Map<Integer, Decimal> mp= new Map<Integer, Decimal>();
        mp.put(1, 1831);
        mp.put(2, 1571);
        mp.put(3, 1569);
        mp.put(4, 1111.54);
        mp.put(5, 1137.12);
        mp.put(6, 1135.29);
        String yr='2016';
        ModelClass mm=new ModelClass(yr,mp);
        ModelClassList.add(mm);
        
        Map<Integer, Decimal> mp2= new Map<Integer, Decimal>();
        mp2.put(7, 1160);
        mp2.put(8, 1138);
        String yr2='2017';
                ModelClass mm2=new ModelClass(yr2,mp2);
        ModelClassList.add(mm2);
        
        return ModelClassList;
    }
}

view

User-added image

working well in my dev org.
This was selected as the best answer
Quddus Ololade 4Quddus Ololade 4
@ashif: This looks good... I already did it as per the other post of creating a child lightning component and passing the mapping values and keys to it as an attribute parameter. But I will try to re-write the code and try this logic, it looks simple and less work.
Thanks !
Quddus Ololade 4Quddus Ololade 4
No Asif, thanks I already marked your answer as best solution