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
Chris SeedChris Seed 

Visualforce page using Javascript remoteAction to pass results into slds tiles

Hi everyone.

Would really appreciate some help with this problem.     

Summary I want to develop a VisualForce page to display a list of records from a few custom objects and then allow the users to filter and sort the list of records.  This is a new implementation so nothing will be used in classic.  The results are only required in the Salesforce mobile app at present but likely they will be required on the desktop version in the future.  Reading around the subject the recomended solution seems to be a Visualforce page using the slds to display the data.  Given its for mobile then tiles rather than tables should be used.   Again as its mobile its recommended to use a remoteAction call from VF to a APEX controller.   

Issue I am not able to get the data to return back from the remoteCall back to the slds tiles.  If I use apex:remoteObjects call in VF, rather than a javacsript remoteAction call I am able to get the data to appear on the page in the tiles.   

Code Notes:  1. I have simplified the code below to try and make it easier to understand.   2. You will see there is code in there in two places (marked with ***remoteObects***) to highlight the code which I was able to use to get it to work with that technology for reference purposes.   

I have also highlighted the code in two places which is for the remoteAction bits. 

Thanks
--Visualforce page
------------

<apex:page standardController="XXCC_COA_Coaching_Contacts__c" extensions="XXCC_COA_Coaching_Contacts_VF" showHeader="false" standardStylesheets="false" sidebar="false" applyHtmlTag="false" applyBodyTag="false" docType="html-5.0">
    <html xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" lang="en">
        <head>
            <meta charset="utf-8" />
            <meta http-equiv="x-ua-compatible" content="ie=edge" />
            <title>Coaching Contacts</title>
            <meta name="viewport" content="width=device-width, initial-scale=1" />
            <!-- Import the Design System style sheet -->
            <apex:slds />
        </head>
        	<!--     ***********remoteObject code******************
            <apex:remoteObjects >
    		<apex:remoteObjectModel name="XXCC_COA_Coaching_Contacts__c" fields="Id,Name,XXCC_COA_Status__c,LastModifiedDate"/>
    		</apex:remoteObjects> -->
        <body>
            <!-- REQUIRED SLDS WRAPPER -->
            <div class="slds-scope">
                <!-- MASTHEAD -->
                <p class="slds-text-heading_label slds-m-bottom_small"> Coaching Contacts </p>
                <!-- / MASTHEAD -->
                <div class="slds-page-header">
                    <div class="slds-grid">
                        <div class="slds-col slds-has-flexi-truncate">
                        </div>
                    </div>
                </div>
                <!-- PRIMARY CONTENT WRAPPER -->
                <div class="myapp slds-p-horizontal_medium">
                    <ul id="contact-list" class="slds-has-dividers_bottom-space"></ul>
                </div>
                <!-- / PRIMARY CONTENT WRAPPER -->
            </div>
            <!-- / REQUIRED SLDS WRAPPER -->
            <!-- JAVASCRIPT -->
            <script type="text/javascript">
            (function () {
                //***********remoteObject code******************
                //var contact = new SObjectModel.XXCC_COA_Coaching_Contacts__c();
                //***********remoteAction code******************
                var contact = getRemoteContact();
                var contactList = document.getElementById('contact-list');
                /* FUNCTION createTile */
                function createTile(record) {
                    return ['<li class="slds-item">', '<div class="slds-tile slds-media">',
                            '<div class="slds-media__body">', '<h3 class="slds-truncate" title="', record.get('Name'),
                            '"><a href="javascript:void(0);">', record.get('Name'), '</a></h3>',
                            '<div class="slds-tile__detail slds-text-body_small">', '<p class="slds-truncate">', record.get(
                                'Title'), '</p>', '</div>', '</div>', '</div>', '</li>'
                           ].join('');
                }
                /* FUNCTION createTile */
                contact.retrieve({
                    orderby: [{
                        LastModifiedDate: 'DESC'
                    }],
                    limit: 810
                }, function (error, records) {
                    if (error) {
                        alert(error.message);
                    } else {
                        contactList.innerHTML = records.map(createTile).join('');
                    }
                });
            })();
            
            //***********remoteAction code******************
            Visualforce.remoting.timeout = 120000; // Set timeout at page level
            function getRemoteContact() {
                //var contactName = document.getElementById('ccSearch').value;
                var contactName = 'CSTEST';
                Visualforce.remoting.Manager.invokeAction(
                    '{!$RemoteAction.XXCC_COA_Coaching_Contacts_VF.getContactsStatus}',
                    contactName,
                    function (result, event){
                        if (event.status) {
                            // Get DOM IDs for HTML and Visualforce elements like this
                            document.getElementById("remoteCCId").innerHTML = result.Id;
                            document.getElementById('remoteCCName').innerHTML = result.Name;
                            
                        } else if (event.type === 'exception') {
                            document.getElementById("responseErrors").innerHTML =
                                event.message + "<br/>\n<pre>" + event.where + "</pre>";
                        } else {
                            document.getElementById("responseErrors").innerHTML = event.message;
                        }
                    }
                )
            };
            </script>
            <!-- JAVASCRIPT -->       
        </body>
    </html>
</apex:page>

------
--APEX Controller 
------

public with sharing class XXCC_COA_Coaching_Contacts_VF {
	public List<XXCC_COA_Coaching_Contacts__c> Records {get; set;}
	public XXCC_COA_Coaching_Contacts_VF(ApexPages.StandardController stdController){
	}
    @RemoteAction
    public static List<XXCC_COA_Coaching_Contacts__c> getContactsStatus(String contactName){
    List<XXCC_COA_Coaching_Contacts__c> coachingContactsStatus = [select Id, Name 
                                                             	  from  XXCC_COA_Coaching_Contacts__c 
                                                             	  limit 1];
    system.debug('Total contacts in the data return: '+coachingContactsStatus.size()); 
    return(coachingContactsStatus);
	}
}


Chris
Best Answer chosen by Chris Seed
Alain CabonAlain Cabon
Hi Chris,

It was a sample code and you have posted a test with only one XXCC_COA_Coaching_Contacts__c.

For a list, you can bring plenty of imagination with SLDS.
 
<!-- / MASTHEAD -->
   <div class="slds-page-header">                    
         <div id="coachIds"></div>                  
   </div>
 <!-- PRIMARY CONTENT WRAPPER -->
 
//***********remoteAction code******************
            Visualforce.remoting.timeout = 120000; // Set timeout at page level
            function getRemoteContact() {
                //var contactName = document.getElementById('ccSearch').value;
                var contactName = 'CSTEST';
                Visualforce.remoting.Manager.invokeAction(
                    '{!$RemoteAction.COA_Coaching_Contacts_VF.getContactsStatus}',
                    contactName,
                    function (result, event){
                        if(event.status && result && (result.constructor === Array)) {
                            console.log('event.status:' + event.status);
                            console.log('result:' + JSON.stringify(result));
                            console.log('result.Id:' + result[0].Id);
                            // Get DOM IDs for HTML and Visualforce elements like this
                            var coachs = '<ul class="slds-has-dividers_around-space">';                                           
                            result.forEach(function(item,index) {
                                coachs += '<li class="slds-item"><article class="slds-tile slds-tile_board">' 
                                + '<h3 class="slds-tile__title slds-truncate" title="test"><a href="/'+item.Id+'">'+ item.Name + '</a></h3>' 
                                +'</article></li>';
                            });   
                            coachs += '</ul>';
                            document.getElementById("coachIds").innerHTML = coachs; 
                        } else if (event.type === 'exception') {
                            document.getElementById("responseErrors").innerHTML =
                                event.message + "<br/>\n" + event.where + "";
                        } else {
                            document.getElementById("responseErrors").innerHTML = event.message;
                        }
                    }
                )
            };

 

All Answers

Alain CabonAlain Cabon
Hi,

Your question is clear and you have posted enought code.

Here is the most important trick:   console.log('result:' + JSON.stringify(result));

It is an array (brackets:[ ]) with an object :  console.log('result.Id:' + result[0].Id);

User-added image

Debugging with the developer tools (Chrome):

User-added image


User-added image


User-added image
 
<apex:page standardController="COA_Coaching_Contacts__c" extensions="COA_Coaching_Contacts_VF" showHeader="false" standardStylesheets="false" sidebar="false" applyHtmlTag="false" applyBodyTag="false" docType="html-5.0">
    <html xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" lang="en">
        <head>
            <meta charset="utf-8" />
            <meta http-equiv="x-ua-compatible" content="ie=edge" />
            <title>Coaching Contacts</title>
            <meta name="viewport" content="width=device-width, initial-scale=1" />
            <!-- Import the Design System style sheet -->
            <apex:slds />
        </head>
        <!--     ***********remoteObject code******************
<apex:remoteObjects >
<apex:remoteObjectModel name="COA_Coaching_Contacts__c" fields="Id,Name,COA_Status__c,LastModifiedDate"/>
</apex:remoteObjects> -->
        <body>
            <!-- REQUIRED SLDS WRAPPER -->
            <div class="slds-scope">
                <!-- MASTHEAD -->
                <p class="slds-text-heading_label slds-m-bottom_small"> Coaching Contacts </p>
                <!-- / MASTHEAD -->
                <div class="slds-page-header">
                    <div class="slds-grid">
                        <div class="slds-col slds-has-flexi-truncate">
                            <div id="remoteCCId"></div>
                            <div id="remoteCCName"></div>
                        </div>
                    </div>
                </div>
                <!-- PRIMARY CONTENT WRAPPER -->
                <div class="myapp slds-p-horizontal_medium">
                    <ul id="contact-list" class="slds-has-dividers_bottom-space"></ul>
                </div>
                <!-- / PRIMARY CONTENT WRAPPER -->
            </div>
            <!-- / REQUIRED SLDS WRAPPER -->
            <!-- JAVASCRIPT -->
            <script type="text/javascript">
            (function () {
                //***********remoteObject code******************
                //var contact = new SObjectModel.COA_Coaching_Contacts__c();
                //***********remoteAction code******************
                var contact = getRemoteContact();
                var contactList = document.getElementById('contact-list');
                /* FUNCTION createTile */
                function createTile(record) {
                    return ['<li class="slds-item">', '<div class="slds-tile slds-media">',
                            '<div class="slds-media__body">', '<h3 class="slds-truncate" title="', record.get('Name'),
                            '"><a href="javascript:void(0);">', record.get('Name'), '</a></h3>',
                            '<div class="slds-tile__detail slds-text-body_small">', '<p class="slds-truncate">', record.get(
                                'Title'), '</p>', '</div>', '</div>', '</div>', '</li>'
                           ].join('');
                }
                /* FUNCTION createTile */
                contact.retrieve({
                    orderby: [{
                        LastModifiedDate: 'DESC'
                    }],
                    limit: 810
                }, function (error, records) {
                    if (error) {
                        alert(error.message);
                    } else {
                        contactList.innerHTML = records.map(createTile).join('');
                    }
                });
            })();
            
            //***********remoteAction code******************
            Visualforce.remoting.timeout = 120000; // Set timeout at page level
            function getRemoteContact() {
                //var contactName = document.getElementById('ccSearch').value;
                var contactName = 'CSTEST';
                Visualforce.remoting.Manager.invokeAction(
                    '{!$RemoteAction.COA_Coaching_Contacts_VF.getContactsStatus}',
                    contactName,
                    function (result, event){
                        if (event.status) {
                            console.log('event.status:' + event.status);
                            console.log('result:' + JSON.stringify(result));
                            console.log('result.Id:' + result[0].Id);
                            // Get DOM IDs for HTML and Visualforce elements like this
                            document.getElementById("remoteCCId").innerHTML = result[0].Id;
                            document.getElementById('remoteCCName').innerHTML = result[0].Name;
                            
                        } else if (event.type === 'exception') {
                            document.getElementById("responseErrors").innerHTML =
                                event.message + "<br/>\n" + event.where + "";
                        } else {
                            document.getElementById("responseErrors").innerHTML = event.message;
                        }
                    }
                )
            };
            </script>
            <!-- JAVASCRIPT -->       
        </body>
    </html>
</apex:page>

public class COA_Coaching_Contacts_VF {
public List<COA_Coaching_Contacts__c> Records {get; set;}
	public COA_Coaching_Contacts_VF(ApexPages.StandardController stdController){
	}
    @RemoteAction
    public static List<COA_Coaching_Contacts__c> getContactsStatus(String contactName){
    List<COA_Coaching_Contacts__c> coachingContactsStatus = [select Id, Name 
                                                             	  from  COA_Coaching_Contacts__c 
                                                             	  limit 1];
    system.debug('Total contacts in the data return: '+coachingContactsStatus.size()); 
    return(coachingContactsStatus);
	}
}


 
Alain CabonAlain Cabon
[select Id, Name from COA_Coaching_Contacts__c limit 1];  Just one result.

Otherwise, you can iterate with  result.forEach(
result.forEach(function(item,index) {
       document.getElementById("remoteCCId").innerHTML = item.Id;
       document.getElementById('remoteCCName').innerHTML = item.Name;
});

 
Alain CabonAlain Cabon
The error detected by the developer tools (Chrome is because the Ids were missing.

<div id="remoteCCId"></div>
<div id="remoteCCName"></div>
Chris SeedChris Seed
Thanks very much Alain for all those points.  I will check it out shortly and come back and mark as the best answer.  
Alain CabonAlain Cabon
Hi,

Ok, your code was correct apart from that.
Chris SeedChris Seed
Thanks again Alain.  I had a look at your comment and the code you provided and that's now running and returning data which is fantastic.  I added in the code you provided to do the forEach loop into the javascript. 

However it's still not creating the Tile list in the output.  I can see if I add in the div id calls to the SLDS wrapper it will display the first record but no more:

                        <div class="slds-col slds-has-flexi-truncate">
                            <div id="remoteCCId"></div>
                            <div id="remoteCCName"></div>
                        </div>

If I use the call to <apex:remoteObjects > instead of the remote call it displays as per this image: User-added image

If I use the RemoteAction call I get this: 

User-added image
It looks like it's not calling the createTile function for some reason?   I haven't used the Google developer tools so I will look into that more now and see if I can get some debug to appear to see if its calling the javascripts correctly.  

I have inserted the code incase you have any more time to take a look.  Appologies if the formating of this goes all over the place.  this is the first time I have posted into the community.  
<apex:page standardController="XXCC_COA_Coaching_Contacts__c" extensions="XXCC_COA_Coaching_Contacts_VF" showHeader="false" standardStylesheets="false" sidebar="false" applyHtmlTag="false" applyBodyTag="false" docType="html-5.0">
    <html xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" lang="en">
        <head>
            <meta charset="utf-8" />
            <meta http-equiv="x-ua-compatible" content="ie=edge" />
            <title>Coaching Contacts</title>
            <meta name="viewport" content="width=device-width, initial-scale=1" />
            <!-- Import the Design System style sheet -->
            <apex:slds />
        </head>
    <!--     ***********remoteObject code****************** 
	<apex:remoteObjects >
	<apex:remoteObjectModel name="XXCC_COA_Coaching_Contacts__c" fields="Id,Name,XXCC_COA_Status__c,LastModifiedDate"/>
	</apex:remoteObjects>  -->
        <body>
            <!-- REQUIRED SLDS WRAPPER -->
            <div class="slds-scope">
                <!-- MASTHEAD -->
                <p class="slds-text-heading_label slds-m-bottom_small"> Coaching Contacts </p>
                <!-- / MASTHEAD -->
                <div class="slds-page-header">
                    <div class="slds-grid">
                        <div class="slds-col slds-has-flexi-truncate">
                            <div id="remoteCCId"></div>
                            <div id="remoteCCName"></div>
                        </div>
                    </div>
                </div>
                <!-- PRIMARY CONTENT WRAPPER -->
                <div class="myapp slds-p-horizontal_medium">
                    <ul id="contact-list" class="slds-has-dividers_bottom-space"></ul>
                </div>
                <!-- / PRIMARY CONTENT WRAPPER -->
            </div>
            <!-- / REQUIRED SLDS WRAPPER -->
            <!-- JAVASCRIPT -->
            <script type="text/javascript">
            (function () {
                //***********remoteObject call******************
                //var contact = new SObjectModel.XXCC_COA_Coaching_Contacts__c();
                //***********remoteAction code******************
                var contact = getRemoteContact();
                //***********End remoteAction call******************
                var contactList = document.getElementById('contact-list');
                /* FUNCTION createTile */
                function createTile(record) {
                    return ['<li class="slds-item">', '<div class="slds-tile slds-media">',
                            '<div class="slds-media__body">', '<h3 class="slds-truncate" title="', record.get('Name'),
                            '"><a href="javascript:void(0);">', record.get('Name'), '</a></h3>',
                            '<div class="slds-tile__detail slds-text-body_small">', '<p class="slds-truncate">', record.get(
                                'Title'), '</p>', '</div>', '</div>', '</div>', '</li>'
                           ].join('');
                }
                /* FUNCTION createTile */
                contact.retrieve({
                    orderby: [{
                        LastModifiedDate: 'DESC'
                    }],
                    limit: 810
                }, function (error, records) {
                    if (error) {
                        alert(error.message);
                    } else {
                        contactList.innerHTML = records.map(createTile).join('');
                    }
                });
            })();
            
            //***********remoteAction code******************
            Visualforce.remoting.timeout = 120000; // Set timeout at page level
            function getRemoteContact() {
                //var contactName = document.getElementById('ccSearch').value;
                var contactName;
                Visualforce.remoting.Manager.invokeAction(
                    '{!$RemoteAction.XXCC_COA_Coaching_Contacts_VF.getContactsStatus}',
                    contactName='CSTEST',
                    function (result, event){
                        if (event.status) {
                            console.log('event.status:' + event.status);
                            console.log('result:' + JSON.stringify(result));
                            console.log('result.Id:' + result[0].Id);
                            // Get DOM IDs for HTML and Visualforce elements like this
                            result.forEach(function(item,index) {
       							document.getElementById('remoteCCId').innerHTML = item.Id;
       							document.getElementById('remoteCCName').innerHTML = item.Name;
							});
                            //document.getElementById("remoteCCId").innerHTML = result[0].Id;
                            //document.getElementById('remoteCCName').innerHTML = result[0].Name;
                            
                        } else if (event.type === 'exception') {
                            document.getElementById("responseErrors").innerHTML =
                                event.message + "<br/>\n" + event.where + "";
                        } else {
                            document.getElementById("responseErrors").innerHTML = event.message;
                        }
                    }
                )
            };
            </script>
            <!-- JAVASCRIPT -->       
        </body>
    </html>
</apex:page>
 
public with sharing class XXCC_COA_Coaching_Contacts_VF {
	public List<XXCC_COA_Coaching_Contacts__c> Records {get; set;}
	public XXCC_COA_Coaching_Contacts_VF(ApexPages.StandardController stdController){
	}
    @RemoteAction
    public static List<XXCC_COA_Coaching_Contacts__c> getContactsStatus(String contactName){
    List<XXCC_COA_Coaching_Contacts__c> coachingContactsStatus = [select Id, Name 
                                                             	  from  XXCC_COA_Coaching_Contacts__c];
    system.debug('Total contacts in the data return: '+coachingContactsStatus.size()); 
    return(coachingContactsStatus);
	}
}

 
Alain CabonAlain Cabon
Hi Chris,

It was a sample code and you have posted a test with only one XXCC_COA_Coaching_Contacts__c.

For a list, you can bring plenty of imagination with SLDS.
 
<!-- / MASTHEAD -->
   <div class="slds-page-header">                    
         <div id="coachIds"></div>                  
   </div>
 <!-- PRIMARY CONTENT WRAPPER -->
 
//***********remoteAction code******************
            Visualforce.remoting.timeout = 120000; // Set timeout at page level
            function getRemoteContact() {
                //var contactName = document.getElementById('ccSearch').value;
                var contactName = 'CSTEST';
                Visualforce.remoting.Manager.invokeAction(
                    '{!$RemoteAction.COA_Coaching_Contacts_VF.getContactsStatus}',
                    contactName,
                    function (result, event){
                        if(event.status && result && (result.constructor === Array)) {
                            console.log('event.status:' + event.status);
                            console.log('result:' + JSON.stringify(result));
                            console.log('result.Id:' + result[0].Id);
                            // Get DOM IDs for HTML and Visualforce elements like this
                            var coachs = '<ul class="slds-has-dividers_around-space">';                                           
                            result.forEach(function(item,index) {
                                coachs += '<li class="slds-item"><article class="slds-tile slds-tile_board">' 
                                + '<h3 class="slds-tile__title slds-truncate" title="test"><a href="/'+item.Id+'">'+ item.Name + '</a></h3>' 
                                +'</article></li>';
                            });   
                            coachs += '</ul>';
                            document.getElementById("coachIds").innerHTML = coachs; 
                        } else if (event.type === 'exception') {
                            document.getElementById("responseErrors").innerHTML =
                                event.message + "<br/>\n" + event.where + "";
                        } else {
                            document.getElementById("responseErrors").innerHTML = event.message;
                        }
                    }
                )
            };

 
This was selected as the best answer
Chris SeedChris Seed
That's just what I need Alain, thanks very much.  
Alain CabonAlain Cabon
Good. I could work as a goood psychic. Well, I get a little carried away! 

Best regards
Alain