Skip to content

rodrigoaraujo7/learning-apex

Repository files navigation

Logo
A repository to learning Apex

Apex Reference Guide | Aura Components Reference Guide


Hello World

// Remember to put ";"
System.debug('Hello World!');

Variables

// Text
string name = 'Rodrigo';

// Number
integer age = 19;

// Decimal Number
decimal money = 200.90;

// True or False
boolean female = false;

// Date
date birthDate = 17072003;

Math methods

integer firstNumber = 20, secondNumber = 50;
integer math = firstNumber + secondNumber; // addition
integer math = firstNumber - secondNumber; // subtraction
integer math = firstNumber * secondNumber; // multiplication
integer math = firstNumber / secondNumber; // division

system.debug(--firstNumber); // Decreasing a value first and read the variable last
system.debug(firstNumber--); // Read the variable first and decreasing a value last

system.debug(++firstNumber); // Increasing  a value

Conditional in variables

integer firstNumber = 8, secondNumber = 10, thirdyNumber = 15;

boolean condition = firstNumber > secondNumber; // 8 > 10?
system.debug(condition); // This result is false

boolean otherCondition = firstNumber < secondNumber; // 8 < 10?
system.debug(otherCondition); // This result is true

Conditional

integer price = 0;

if ( price >= 30 && price <= 50 ) { // if price is between 30 and 50
    System.debug('I bought a t-shirts');
} else if ( price > 50 && price <= 80 ) { // if else price is between 51 and 80
    System.debug('I bought two t-shirts');
} else if ( price > 90) { if else price is more than 90
    System.debug('I ended up leaving');
} else { if price is less 30
    System.debug('I havent money');
}

Loops

// loop with a fixed amount of repetitions
// syntax for loop
for (init_stmt; exit_condition; increment_stmt) {
    code_block
}

for (integer i = 0; i < 10; i++) { // one in one
    system.debug(i);
}

for (integer i = 2; i <= 44; i += 2) { // two in two
    system.debug(i);
}

// for a infinity repetitions
// syntax while loop
while (condition) {
    code_block
}

integer z = 0; // declaring variable out of loop
while (z <= 10) { // one in one
    system.debug(z);
    z++;
}

while (z <= 40) { // four in four
    system.debug(z);
    z += 4;
}

//syntax do while loop
do {
   code_block
} while (condition);

integer x = 0;
do { // one in one
    System.debug(x);
    x++;
} while (x <= 5);

do { // two in two
    System.debug(x);
    x += 2;
} while (x <= 12);

List

List<string> persons = new List<string>();
persons.add('Rodrigo');
persons.add('Nicolas');
system.debug(persons)

List<integer> listNumber = new List<integer> {
    8, 12, 27, 34, 41, 49
};
system.debug(listNumber)

List<string> persons = new string[5]; // Set 5 values at default
persons.add(0, 'Rodrigo'); // Adding a new index with string value
persons.set(1, 'Nicolas'); // Seting a string value at second index
persons[2] = 'Robert'; // Another method to set a new value

System.debug(persons); // Will be return (Rodrigo, Nicolas, Robert, null, null, null)

Set

// Will be sort by smallest (1 - 10) (A - Z)
Set<Integer> listNumber = new Set<Integer> {
    12, 12, 32, 312, 3627189, 2
};

system.debug(listNumber); // Will be return 2, 12, 32, 312, 3627189

Map

Map<string, string> colorCodes = new Map<string, string>(); // Declares variable

colorCodes.put('Light Blue', '#6FA4F2'); // Seting two values
colorCodes.put('Light Purple', '#884FBD'); // Seting others two values

System.debug(colorCodes); // Will be return {Light Blue=#6FA4F2, Light Purple=#884FBD}

String code = colorCodes.get('Light Blue');
System.debug(code); // Will be return #6FA4F2

Object

// Creating a new object
public class Person {
  public string name;
  public string lastName;
  public integer age;
}

// Creating a new Person
Person firstPerson = new Person();

firstPerson.name = 'Rodrigo';
firstPerson.lastName = 'Araujo';
firstPerson.age = 19;

system.debug(firstPerson); // Will be return |DEBUG|Person:[age=19, lastName=Araujo, name=Rodrigo]

// Functions inside the object
public class Person {
  // code block
  
  // At now Let's create it as null as we don't need it to return anything!
  public void speak() {
    system.debug(name);
    system.debug(lastName);
    system.debug(age);
  }
}

firstPerson.speak();

// Simple calc
public class Calculator {
    // Notice that now I didn't put void, but integer, that's because now I need it to return something!
    // And in this case, we need pass the params.
    public Integer addition(Integer firstValue, Integer secondValue) {
        Integer result = firstValue + secondValue;
        
        // Return me the result
        return result;
    
        // IMPORTANT!!!!!!!
        // Note: Under the result, nothing else will be executed
    }
}

// Object with conditional
public Integer division(Integer firstValue, Integer secondValue) {
    if (secondValue == 0) {
        system.debug('Cant divide by zero!');
        return 0;
    } else {
        return firstValue / secondValue;
    }
}

Calculator newCalc = new Calculator();
Integer firstResult = newCalc.division(122, 0); // Will be return |DEBUG|Can't divide by zero!

Static

// Because good practice to your system
// from now on we create methods using the *static*
// this will make your system much faster.

public class newCalc {
  public static void add(Integer n1, Integer n2) {
    integer result = n1 + n2;
    system.debug(result);
  }
}

newCalc.add(5, 10);

Batch Apex

// Batch Apex is used to run large jobs 
// (think thousands or millions of records!) 
// that would exceed normal processing limits.

public class MyBatchClass implements Database.Batchable<sObject> {
    public (Database.QueryLocator | Iterable<sObject>) start(Database.BatchableContext bc) {
        // collect the batches of records or objects to be passed to execute
    }
    public void execute(Database.BatchableContext bc, List<P> records){
        // process each batch of records
    }
    public void finish(Database.BatchableContext bc){
        // execute any post-processing operations
    }
}


SOQL

Select & From

// SOQL is used to search, change, delete, insert your org records.
// Now we will do a simple data search

// Select for me, the records from the Id, Name and Phone fields.
// From the Account object

// Will be return all the records I requested above

SELECT Id, Name, Phone
FROM Account

SELECT Id, Name, Account.Name, Account.Id
  FROM Contact

Where

// Now we will use where
// It is very simple, it adds a filtering system for us

SELECT Id, Name, Phone
  FROM Account
  WHERE AnnualRevenue > 1000

Where And

// Use the AND when you need use more than one WHERE

SELECT Id, Name, Vip__c, AnnualRevenue
  FROM Account
  WHERE Vip__c = true
    AND AnnualRevenue > 500

Like

// Here, I will search for an Account that has Rodrigo using the like
// %Rodrigo  - Ends with Rodrigo
// Rodrigo%  - Starts with Rodrigo
// %Rodrigo%  - Have Rodrigo

SELECT Id, Name
  FROM Account
  WHERE Name LIKE '%Rodrigo'

Order by

// Order by is used to literally Order by Asc or Desc
// Asc - lowest => highest

SELECT Name, ValorDespesa__c
  FROM Despesa__c
  ORDER BY ValorDespesa__c Desc

Group by

// Group duplicate records
// HAVING - Groups filter

SELECT Name, COUNT(Id)
  FROM Opportunity
  GROUP BY Name
  HAVING COUNT(Id) > 1

Limit

// Limits my query to 10 records

SELECT Id, Name
  FROM Account
  LIMIT 10

Count Sum Min Max Avg

SELECT Account.Name, COUNT(Id), SUM(Amount), MAX(Amount), MIN(Amount), AVG(Amount)
    FROM Opportunity
    GROUP BY Account.Name

Subquery

// Selecting a new query, inside a query

SELECT Id, Name, 
(SELECT Id, Amount 
FROM Opportunities)
    FROM Account


APEX WITH SOQL

Read

List<Account> lstAccount = [SELECT Id, Name FROM Account];

system.debug(lstAccount);

Insert

// With query (To filter the list )
List<Account> lstAccount = [SELECT Id, Name FROM Account WHERE AnnualRevenue < 100];
// Whitout query
List<Account> lstAccount = new List<Account>();

for(Account item : lstAccount) {
	Account acc = new Account();
	acc.Name = 'Nome Xpto';
	lstAccount.add(acc);
}

insert lstAccount;

Update

// With query (To filter the list )
List<Account> lstAccount = [SELECT Id, Name FROM Account WHERE AnnualRevenue < 100];
// Whitout query
List<Account> lstAccount = new List<Account>();

for(Account item : lstAccount) {
	Account acc = new Account();
	acc.Name = 'Nome Xpto';
	lstAccount.add(acc);
}

update lstAccount;

Delete

// With query to filter the list
List<Account> lstAccount = [SELECT Id, Name FROM Account WHERE AnnualRevenue < 100];

// When account have AnnualRevenue < 100, delete the record
delete lstAccount;

Try Catch 👉 Exception Class

try {
    // Code block
  } catch(Exception type) { // Error case
    // Code block
}

try {
    integer calc = 10/0;
    system.debug('🟣 Calc done successfully: ' + calc);
} catch(MathException CalcError) {
    system.debug('🔴 Error in calc!');
}

Main order of executions


Trigger

// Trigger structure
trigger TriggerName on ObjectName(time) {
    // Code block
}

// Now we will create a real trigger
// After save, active the trigger
trigger OpportunityTrigger on Opportunity(before insert) {
    System.debug('actived trigger');
}

Class with Trigger

// Class File (LeadHandler.cls)
public class LeadHandler {
    // Methods to before triggers
    public static void leadBefore(List<Lead> listLead) {
        // Phone and Cellphone fields validation
        for(Lead itemLead : listLead) {
            if(itemLead.Phone == null && itemLead.MobilePhone == null) {
                itemLead.addError('Preencha o campo Telefone'); 
            }
        }

        // CPF field validation
        for(Lead itemLead : listLead) {
            if(itemLead.CPF__c == null) {
                itemLead.addError('Preencha o campo CPF');
            }
        }

        // Sets "small company" when entering condition
        for(Lead itemLead: listLead) {
            if(itemLead.NumberOfEmployees < 1000) {
                itemLead.TamanhoEmpresa__c = 'Empresa pequena';
            }
        }
    }
    
    // Methods to after triggers
    public static void leadAfter(List<Lead> listLead) {
        // When Annual Revenue > 50000 Create new Task
        List<Task> lstTaskInsert = new List<Task>();
        for(Lead itemLead: listLead) {
            if(itemLead.AnnualRevenue > 50000) {
                Task newTask = new Task();
                newTask.subject = 'Create new task';
                lstTaskInsert.add(newTask);
            }
        } // insert lstTaskInsert; 
        // Will be inserted outside the For for good practices
        
        // If lstTaskInsert isn't empty insert the task
        if(!lstTaskInsert.isEmpty()) {
            insert lstTaskInsert;
        }
    }
}
// Creating a trigger and put the times
trigger LeadTrigger on Lead(before insert, before update, after insert, after update) {
    if(Trigger.isBefore) { // Time when this method will be function
        if(Trigger.isInsert) {
            LeadHandler.leadBefore(Trigger.new); // Executing the method
        } else if(Trigger.isUpdate) {
            LeadHandler.leadBefore(Trigger.new);
        }
    } else if(Trigger.isAfter) {
        if(Trigger.isInsert) {
            LeadHandler.leadAfter(Trigger.new);
        } else if(Trigger.isUpdate) {}
    }
}

Test

// Calculator.cls
public class Calculator {
    public static Integer addition(Integer firstValue, Integer secondValue) {
        Integer result = firstValue + secondValue;        
        return result;
    }

    public static Integer subtract(Integer firstValue, Integer secondValue) {
        Integer result = firstValue - secondValue;
        return result;
    }

    public static Integer multiplication(Integer firstValue, Integer secondValue) {
        Integer result = firstValue * secondValue;
        return result;
    }

    public static Integer division(Integer firstValue, Integer secondValue) {
        if (secondValue == 0) {
            system.debug('Não pode dividir por 0');
            return 0;
        } else {
            return firstValue / secondValue;
        }
    }
}
// CalculatorTest.cls

// Now, we will test the code.
// In the other file, let's create another class 
// To see if the code is working
@isTest
public class CalculatorTest {
    @isTest public static void testAddMethod() {
        Integer result = Calculator.addition(1, 1);
        system.assert(result == 2, '🔴 Unexpected result');
    }

    @isTest public static void testSubtractMethod() {
        Integer result = Calculator.subtract(12, 2);
        system.assertEquals(10, result, '🔴 Unexpected result');
    }

    @isTest public static void testMultiplicationMethod() {
        Integer result = Calculator.multiplication(2, 2);
        system.assert(result == 4, '🔴 Unexpected result');
    }

    // IF ELSE Division
    @isTest public static void testDivisionMethod() {        
        Integer result = Calculator.division(10, 2);
        system.assert(result == 5, '🔴 Unexpected result');
    }
    
    @isTest public static void testDivisionByZeroMethod() {
        Integer result = Calculator.division(10, 0);
        system.assert(result == 0, '🔴 Unexpected result');
    }
}

Apex with Aura

🦄 Callback Documentation

// Yet the return doesn't "return" anything
// but now using the aura we will go change that

// Apex Class
public class OpportunityC {
    @AuraEnabled // This is placed here to we can use on Aura and on LWC
    public static List<Opportunity> getOpportunitiesNV() {
        return [SELECT Name, Amount, StageName, CloseDate 
                FROM Opportunity 
                WHERE StageName = 'Closed Won'
		Order By createdDate DESC LIMIT 5];
    }
}
// In the aura:component we used the controller to
// We can use the class we created above
<aura:component controller="OpportunityC" implements="force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId" access="global" >
    // And here is a attribute 
    <aura:attribute name="opps" type="Opportunity[]" />
    
    // Now we'll joke with lifecycle
    // Name => When the component start
    // Value => On this aura component
    // Action => Execute my function doInit()
    <aura:handler name="init" value="{!this}" action="{!c.doInit}" />
    
    // This is a simple card with a default configurations, nothing special
    <lightning:card iconName="standard:opportunity" title="Oportunidades fechadas">
    	<div class="slds-p-arround_medium">
        </div>
    </lightning:card>
</aura:component>
// Controller.js
({
    // Component => Allows access the aura component
    // Event => Allows access the javascript
    // Helper => Allows access the helper functions
    doInit : function(component, event, helper) {
        helper.getOpportunities(component);
    }
})
// Helper.js
({
    // Is important the helper also can manipulate the component
    getOpportunities : function(component) {
    console.log('Estou sendo no helper - Invocação do Yrra =D');
        
    // Using the Apex OpportunityC class's method
    // like a attribute's component
    let action = component.get('c.getOpportunitiesNV');
        
    // After execute the apex method (Call the data)
    // Verify the answer of the server (SUCCESS - ERROR - INCOMPLETE) 
    action.setCallback(this, (response) => {
    	// Receive a answer
        let state = response.getState();            
            
         if(state == "SUCCESS") { // Verify if the answer is SUCCESS
	      // Assign the value to opps
              component.set("v.opps", response.getReturnValue());
              console.log(response.getReturnValue());
        }
     });
        
     // Execute the function
     // Without it we'll never get an answer
     $A.enqueueAction(action);
    }
})
<!-- Aura Component -->
<lightning:card iconName="standard:opportunity" title="Oportunidades fechadas">
    	<div class="slds-p-arround_medium">
            <!-- aura:interaion receives the list of opportunities -->
            <!-- this var is for to refs the files -->
            <aura:iteration items="{!v.opps}" var="opp">
                <!-- Here we're executing all the -->
                <!-- opportunities inside the list -->
                <!-- but only their name -->
            	<p>{!opp.Name}</p>
            </aura:iteration>
        </div>
 </lightning:card>

LWC

🤖 documentation

First Step

<!-- app.html -->

<!-- 
LWC is literally html css and javascript 
but with some small differences

NOTE: The file name is equal at the component, 
only change the extension file - EX: app.html app.css app.html
-->

<template>
     <!-- template is your tag main, all your html is placed here -->
     <!-- code block -->
</template>
// app.js

// Here your js, hi's like a React

import { LightningElement } from "lwc"; // You need import that to use lwc, else he will be return error

// Here we creating a class with a some props
// Export is used to we can literally export the class
// Default Class is a default configurations that the LWC available to us 
// App is our class name => NOTE: Important his name is equal our file name
// extends LightningElement we're using the import on the first line
export default class App extends LightningElement {
     // code block
}

Variables

// app.js

// Here we'll learn a "new" method to declare variable
name = 'Rodrigo';
age = 19

// Yes, only this! Now we'll run that in the html
<!-- app.html -->

<template>
   {name}
   {age}
   
   <!-- No comments -->
</template>

Object

// app.js

// Here we'll work with a object
person = {
    name: 'Rodrigo',
    age: 19
} // And let's run that in the html
<!-- app.html --> 

<template>
   <!-- {objectName.variableName} -->
   {person.name}
   {person.age}   
</template>

LWC if

<!-- app.html -->

<template>
   <!-- We're speaking => If the variable "visible" is true, run that -->
   <template if:true={visible}>
        <h1>Hello World</h1>
   </template>   
	
   <!-- But where's the variable "visible" -->
   <!-- We're go create she now in the javascript -->
</template>
// app.js

// Creating the variable
visible = true

Onclick

// app.js

visible = true
// Here we'll create a function to use in a button
click() { // This is a simples javascript code, but is a good example
     this.visible = !this.visible
}
<!-- app.html -->

<template>
   <!-- We're speaking => If the variable "visible" is true, run that -->
   <template if:true={visible}>
        <h1>Hello World</h1>
   </template>   
   
   <!-- Now I create this button upon receiving that the function we created -->
   <lightning-button label="Magic Destruction" onclick={click} class="slds-p-around_medium"></lightning-button>
</template>

@api

// person.js

// Ok, now I created a new file, and I named product.html product.js

// Important to import  the api in this case
import { LightningElement, api } from "lwc";

export default class Person extends LightningElement {
  // @api Is used to we can change this data in html
  @api name = 'Rodrigo Araujo'
  @api age = 19
}
<!-- person.html -->

<!-- After that, we execute those variables with @api -->
<template>
  <h1>Name: {name}</h1>
  <h3>Age: {age}</h3>
</template>
<!-- app.html -->

<template>
  <lightning-card>
    <div class="slds-p-around_x-large">
      <!-- c-person is a tag to we can import our data in the -->
      <!-- person component -->
      <c-person></c-person>
    
      <!-- Notice here I can change the data! -->
      <c-person name="Yrra Doe" age="22"></c-person>
    </div>
  </lightning-card>
</template>