+ Start a Discussion
Juan Pablo GarzónJuan Pablo Garzón 

I need to show a Map in VisualForce

Hi All

 

I am developing a VisualForce page and I need to pass a parameter to controller class. Why do I need to pass a parameter?, because I try to paint a table in HTML using a repeat apex component <apex:repeat>. The method called returns to VisualForce page a values map and I need to pass a key map to controller class.

 

Controller

 

public class claControlFormatoCotizacionSolicitud{ transient Map<String, Map<String, Double>> totalesAnticipos = new Map<String, Map<String, Double>>(); transient List<String> monedasAnticipos = new List<String>(); String tipoAnticipo {get;set;} public void calcularAnticiposSolicitud() { Map<String, String> monedasConsulta = new Map<String, String>(); List<Anticipo__c> consultaAnticipos = [SELECT Moneda__c, Tipo__c, Valor__c FROM Anticipo__c WHERE Solicitudes_de_viaje__c = :ApexPages.currentPage().getParameters().get('identificadorSolicitud') AND Tipo__c <> 'Tiquetes' AND IsDeleted = false ORDER BY Tipo__c ASC LIMIT 1000]; for(Anticipo__c registroAnticipo :consultaAnticipos) { monedasConsulta.put(registroAnticipo.Moneda__c, registroAnticipo.Moneda__c); } for(String monedaRegistro :monedasConsulta.values()) { monedasAnticipos.add(monedaRegistro); } monedasAnticipos.sort(); for(Anticipo__c registroAnticipo :consultaAnticipos) { if (totalesAnticipos.containsKey(registroAnticipo.Tipo__c)) { Map<String, Double> totalesTipo = totalesAnticipos.get(registroAnticipo.Tipo__c); if (totalesTipo.containsKey(registroAnticipo.Moneda__c)) { Double valorTotal = totalesTipo.get(registroAnticipo.Moneda__c); valorTotal = valorTotal + registroAnticipo.Valor__c; totalesTipo.put(registroAnticipo.Moneda__c, valorTotal); totalesAnticipos.put(registroAnticipo.Tipo__c, totalesTipo); } } else { Map<String, Double> totalesTipo = new Map<String, Double>(); for(String monedaTipo :monedasAnticipos) { if (monedaTipo == registroAnticipo.Moneda__c) { totalesTipo.put(registroAnticipo.Moneda__c, registroAnticipo.Valor__c); } else { totalesTipo.put(monedaTipo, 0); } totalesAnticipos.put(registroAnticipo.Tipo__c, totalesTipo); } } } } public List<String> getMonedasAnticipos() { return monedasAnticipos; } public List<String> getTiposAnticipos() { List<String> tiposAnticipos = new List<String>(); for(String tipoRegistro :totalesAnticipos.keySet()) { tiposAnticipos.add(tipoRegistro); } return tiposAnticipos; } public List<Double> getTotalesMonedas() { String tipoRegistro = System.currentPageReference().getParameters().get('tipoAnticipo'); List<Double> totalesTipo = totalesAnticipos.get(tipoRegistro).values(); return totalesTipo; } }

 

 VisualForce Page

 

<apex:page action="{!calcularAnticiposSolicitud}" controller="claControlFormatoCotizacionSolicitud" renderAs="pdf" showHeader="false" title="FTUG01 - Formato Solicitud Cotización de Tiquetes y Hotel"> <apex:form id="forCotizacionSolicitid"> <table border="1" width="100%"> <tr> <td></td> <apex:repeat value="{!MonedasAnticipos}" var="detalleMoneda"> <td><apex:outputText value="{!detalleMoneda}"/></td> </apex:repeat> </tr> <apex:repeat value="{!TiposAnticipos}" var="detalleTipo"> <tr> <td> <apex:outputText value="{!detalleTipo}"> <apex:param assignTo="{!tipoAnticipo}" name="tipoAnticipo" value="{!detalleTipo}"/> </apex:outputText> </td> <apex:repeat value="{!TotalesMonedas}" var="detalleTotal"> <td><apex:outputText value="{!detalleTotal}"/></td> </apex:repeat> </tr> </apex:repeat> </table> </apex:form></apex:page>

 

But when I execute the VisualForce page, the parameter "tipoAnticipo" is empty or null. 

 

 

 

Best Answer chosen by Admin (Salesforce Developers) 
Juan Pablo GarzónJuan Pablo Garzón

I found solution for my problem. Maybe you think the solution is easy but I needed 3 days for look the best way. I summarize my problem.

 

I need to show values Map in Visualforce page, but I don't know how to pass the key Map. The solution uses apex repeat component and I need to convert the map in list of lists.

 

I think about apex repeat component , if you use apex repeat on other apex repeat component like that for on other for, but it is a lie because the internal repeat apex component executes only one time. So, I created a get method for a list of lists, and I put the list in the first apex repeat component and put the variable apex repeat component how the value in the second apex repeat component. 

 

Extract  of the controller class

 

 

public List<List<String>> getFilasTabla(){ return filasTabla;}

 

 Extract of Visualforce page where I paint the table HTML

 

 

<table border="1" width="100%"> <apex:repeat value="{!FilasTabla}" var="detalleTabla"> <tr> <apex:repeat value="{!detalleTabla}" var="detalleColumna"> <td><apex:outputText value="{!detalleColumna}"/></td> </apex:repeat> </tr> </apex:repeat></table>

 Note that the var of the first apex repeat component is the value of the second apex repeat component.

 

 

 

All Answers

Juan Pablo GarzónJuan Pablo Garzón

I found solution for my problem. Maybe you think the solution is easy but I needed 3 days for look the best way. I summarize my problem.

 

I need to show values Map in Visualforce page, but I don't know how to pass the key Map. The solution uses apex repeat component and I need to convert the map in list of lists.

 

I think about apex repeat component , if you use apex repeat on other apex repeat component like that for on other for, but it is a lie because the internal repeat apex component executes only one time. So, I created a get method for a list of lists, and I put the list in the first apex repeat component and put the variable apex repeat component how the value in the second apex repeat component. 

 

Extract  of the controller class

 

 

public List<List<String>> getFilasTabla(){ return filasTabla;}

 

 Extract of Visualforce page where I paint the table HTML

 

 

<table border="1" width="100%"> <apex:repeat value="{!FilasTabla}" var="detalleTabla"> <tr> <apex:repeat value="{!detalleTabla}" var="detalleColumna"> <td><apex:outputText value="{!detalleColumna}"/></td> </apex:repeat> </tr> </apex:repeat></table>

 Note that the var of the first apex repeat component is the value of the second apex repeat component.

 

 

 

This was selected as the best answer
fred526fred526

Hello Juan,

 

Do you mind posting some more of your solution?  I'm having the same problem and I'm very interested in how you did it.

 

Thanks!

Fred

Juan Pablo GarzónJuan Pablo Garzón

I have a map of maps because I need to sum group by two variables.

 

You need to create four methods: The First method should to calculate the map object. The second method should to convert the object map in a list of lists. The third method should to get list value. The fourth method should to set list value.
 
For example:

I have a Map string values (Map<String, Map<String, Double>>) and List of Lists string values (List<List<String>>). 

The map values 

Dollar, <Transport, 1000>, <Eat, 500>

Yen,  <Transport, 7050>, <Eat, 250>

 

When you convert to map object in a list of lists, you need to put a key of the first map value in a first position of a list and next you need to put a values of the second map.

The list of lists

Firs position <Dollar, 1000, 500>

Second position <Yen, 7050, 250>

 

If you draw a table with this list values

 

------------------------

| Dollar | 1000 | 500 |

------------------------

| Yen    | 7050 | 250 |

------------------------

 

The method for calculate and convert map 

 

public void calcularAnticiposSolicitud() { Map<String, String> monedasConsulta = new Map<String, String>(); List<Anticipo__c> consultaAnticipos = [SELECT Moneda__c, Tipo__c, Valor__c FROM Anticipo__c WHERE Solicitudes_de_viaje__c = :ApexPages.currentPage().getParameters().get('identificadorSolicitud') AND IsDeleted = false ORDER BY Tipo__c ASC LIMIT 1000]; for(Anticipo__c registroAnticipo :consultaAnticipos) { monedasConsulta.put(registroAnticipo.Moneda__c, registroAnticipo.Moneda__c); } for(String monedaRegistro :monedasConsulta.values()) { monedasAnticipos.add(monedaRegistro); } monedasAnticipos.sort(); for(Anticipo__c registroAnticipo :consultaAnticipos) { if (totalesAnticipos.containsKey(registroAnticipo.Tipo__c)) { Map<String, Double> totalesTipo = totalesAnticipos.get(registroAnticipo.Tipo__c); if (totalesTipo.containsKey(registroAnticipo.Moneda__c)) { Double valorTotal = totalesTipo.get(registroAnticipo.Moneda__c); valorTotal = valorTotal + registroAnticipo.Valor__c; totalesTipo.put(registroAnticipo.Moneda__c, valorTotal); totalesAnticipos.put(registroAnticipo.Tipo__c, totalesTipo); } } else { Map<String, Double> totalesTipo = new Map<String, Double>(); for(String monedaTipo :monedasAnticipos) { if (monedaTipo == registroAnticipo.Moneda__c) { totalesTipo.put(registroAnticipo.Moneda__c, registroAnticipo.Valor__c); } else { totalesTipo.put(monedaTipo, 0); } totalesAnticipos.put(registroAnticipo.Tipo__c, totalesTipo); } } } for(String tipoAnticipo :totalesAnticipos.keySet()) { List<String> filaTipo = new List<String>(); filaTipo.add(tipoAnticipo); Map<String, Double> totalesTipo = totalesAnticipos.get(tipoAnticipo); for(String monedaAnticipo :monedasAnticipos) { Double totalAnticipo = totalesTipo.get(monedaAnticipo); filaTipo.add('$' + String.valueOf(totalAnticipo)); } filasTabla.add(filaTipo); } }

 

 The method for get list values

 

public List<List<String>> getFilasTabla() { return filasTabla; }

 

The part of visualforce page when I draw a table

 

 

<apex:repeat value="{!FilasTabla}" var="detalleTabla"> <tr> <apex:repeat value="{!detalleTabla}" var="detalleColumna"> <td><apex:outputText value="{!detalleColumna}"/></td> </apex:repeat> </tr> </apex:repeat>

 

 

 

 

 

 

dke01dke01

This is pathetic.  Yet add another cheap work around to the big list of things that should just work out of the box.

 

Please vote to fix this here http://sites.force.com/ideaexchange/ideaView?c=09a30000000D9xt&id=08730000000IIn5AAG