How to Query Related Contacts from an Account in Salesforce

Salesforce developers and tech leads often work with different object which are related to each other in different ways (many to many, one to many etc). It can be tricky for new Salesforce Developers to build subqueries using soql. In today’s article we will pickup Account and Contact to address this and learn how to query related contacts form an Account in Salesforce.

Table of Contents

  1. Introduction to Account-Contact Relationship in Salesforce
  2. Understanding SOQL for Related Records
  3. Anatomy of a subquery in SOQL
  4. Querying Related Contacts Using Apex
  5. Querying Related Contacts Using JavaScript in LWC
  6. Best Practices for Querying Related Data in Salesforce

Introduction to Account-Contact Relationship in Salesforce

In Salesforce, the relationship between Accounts and Contacts is a standard parent-child one to many relationship. An Account can have multiple Contact and each Contact is associated with an Account via the AccountId field.

Understanding relationships between objects is the first step to build an efficient SOQL.


SOQL (Salesforce Object Query Language) allows developers to query records stored in the Salesforce database. In our current scenario we are going to write a subquery to fetch related records of an account in a single query. For example:

SELECT Id, Name, (SELECT Id, FirstName, LastName FROM Contacts) FROM Account WHERE Id = :accountId

This query fetches the Account record along with its related Contacts. As you can see we have used a sub-query inside a query. You can use this in Apex or other tools to retrieve related data.

Query Related Contacts from an Account

Anatomy of a subquery in SOQL

Note: A subquery is a nested query inside a query.

salesforce

To learn more about SOQL read this official Salesforce Documentation here.


Apex is the most common approach for querying related records in Salesforce. You can write a SOQL query to fetch related Contacts and expose the data to your Lightning Web Component.

Apex Example Code

public with sharing class AccountContactController {

    @AuraEnabled(cacheable=true)
    public static List<Contact> getRelatedContacts(Id accountId) {
        return [
            SELECT Id, FirstName, LastName, Email
            FROM Contact
            WHERE AccountId = :accountId
        ];
    }
}

Explanation:

  1. The @AuraEnabled annotation makes this method available to Lightning components.
  2. The method queries all Contacts related to the given accountId.

LWC Integration with Apex

Below is an example of how to call this Apex method in LWC:

import { LightningElement, api, wire } from 'lwc';
import getRelatedContacts from '@salesforce/apex/AccountContactController.getRelatedContacts';

export default class RelatedContacts extends LightningElement {
    @api recordId; // Holds the Account Id
    contacts;
    error;

    @wire(getRelatedContacts, { accountId: '$recordId' })
    wiredContacts({ error, data }) {
        if (data) {
            this.contacts = data;
            this.error = undefined;
        } else if (error) {
            this.error = error;
            this.contacts = undefined;
        }
    }
}

Key Points:

  • Use @wire to call the Apex method and bind the results to the component.
  • Handle both data and error scenarios.

The Lightning framework also provides JavaScript-based methods for querying Salesforce data. Let’s explore two approaches: Wire Adapters and Imperative Apex Calls.

Wire Adapters for Fetching Contacts

The getRelatedListInfo adapter can be used to fetch related lists programmatically. However, for custom queries, the Apex approach is often preferred.

import { LightningElement, api, wire } from 'lwc';
import { getRecord } from 'lightning/uiRecordApi';

const FIELDS = [
    'Account.Name',
    'Account.Contacts'
];

export default class RelatedContactsWireAdapter extends LightningElement {
    @api recordId;
    account;
    error;

    @wire(getRecord, { recordId: '$recordId', fields: FIELDS })
    wiredAccount({ error, data }) {
        if (data) {
            this.account = data;
            this.error = undefined;
        } else if (error) {
            this.error = error;
            this.account = undefined;
        }
    }
}

Imperative Apex Calls in LWC

For scenarios requiring user interaction, you can use imperative Apex calls. Here is an example:

import { LightningElement, api } from 'lwc';
import getRelatedContacts from '@salesforce/apex/AccountContactController.getRelatedContacts';

export default class RelatedContactsImperative extends LightningElement {
    @api recordId;
    contacts;
    error;

    handleFetchContacts() {
        getRelatedContacts({ accountId: this.recordId })
            .then((result) => {
                this.contacts = result;
                this.error = undefined;
            })
            .catch((error) => {
                this.error = error;
                this.contacts = undefined;
            });
    }
}

Key Points:

  • Use getRelatedContacts Apex method imperatively when you need to fetch data based on user actions (e.g., button clicks).
  • Always handle promise rejections with .catch().

  1. Use SOQL Efficiently: Avoid querying unnecessary fields or records.
  2. Leverage Cacheable Methods: Use @AuraEnabled(cacheable=true) for read-only operations to improve performance.
  3. Error Handling: Always handle errors gracefully in both Apex and LWC.
  4. Optimize Data Display: Use pagination or lazy loading for large datasets.
  5. Security Considerations: Enforce sharing rules with with sharing and validate user permissions.

By combining these techniques, Salesforce developers can build powerful, efficient, and user-friendly components to query and display related Contacts for Accounts in LWC. Don’t forget to test your implementation and include error-handling mechanisms for a seamless user experience.


Have questions or need clarification? Feel free to share your thoughts in the comments below!

Add a Comment

Your email address will not be published. Required fields are marked *