본문 바로가기
  • 개발 삽질 블로그
세일즈포스

세일즈포스 실습 2(Lightning Component, Quick Action, Apex)

by 갹둥 2023. 10. 27.

Lightning Component Quick Action

Subject Record 페이지에서 Task 추가 버튼을 누르면 뜸

task__c는 타입이라는 필수 필드를 둠 오프라인 vs 온라인 vs 선택x 중 택 1

Quick Action은

Object Manager에서 추가할 수 있음

 

select에서 오프라인 선택시 화면
온라인 선택시 화면

 

선택x 선택시 화면

<aura:component description="NewTask" controller="TaskController" implements="force:hasRecordId,force:lightningQuickActionWithoutHeader,flexipage:availableForAllPageTypes" access="global">
    <aura:attribute name="recordId" type="String" />
    <aura:handler name="init" value="{!this}" action="{!c.fnInit}"/>
    <aura:attribute name="options" type="List"/>
    <aura:attribute name="typeValue" type="String"/>
    <article class="slds-card">
        <div class="slds-card__header-title slds-align_absolute-center slds-border_bottom slds-m-around_medium slds-p-around_medium">
            <h3 class="slds-text-heading_medium">Task 추가</h3>
        </div>
        <div class="slds-card slds-card__body_inner slds-m-around_large">
            <lightning:input aura:id="taskName" label="Task Name" required="true"/>
            <lightning:input aura:id="taskContent" label="내용" required="true"/>
            <lightning:combobox aura:id="taskType" options="{!v.options}" label="타입" value="{!v.typeValue}" required="true"/>
            <aura:if isTrue="{!v.typeValue == '온라인'}">
                <lightning:input type="url" aura:id="taskSourceLink" label="url"/>
            </aura:if>
            <aura:if isTrue="{!v.typeValue == '오프라인'}">
                <lightning:input type="text" aura:id="taskAddressCity" label="시 군/구"/>
                <lightning:input type="text" aura:id="taskAddressStreet" label="상세"/>
            </aura:if>
            <div class="slds-container_center slds-text-align_center slds-m-around_medium">
                <lightning:button type="button" label="추가" onclick="{!c.fnBtnAddClick}"/>
                <lightning:button type="button" label="취소" onclick="{!c.fnBtnCancelClick}"/>
            </div>
        </div>
    </article>
</aura:component>

typeValue가 바뀔 때 화면이 조건에 따라 같이 바뀜, select label과 option은 controller에서 지정해줌

fnInit : function(component, event){
    var options = [
        {label: '온라인', value: '온라인'},
        {label: '오프라인', value: '오프라인'},
        {label: '선택x', value: '선택x'}
    ];
    component.set("v.options", options);

}

CRUD 작업이 이루어질 때는 Apex Controller를 거쳐야하기 때문에 Controller.js나 Helper.js에서 연결해줘야함

새로운 Task를 저장하는 부분의 코드는 아래와 같음

fnBtnAddClick: function(component, event, helper){
    var objTask = {};
    objTask.Subject__c = component.get("v.recordId");
    objTask.Name = component.find("taskName").get("v.value");
    objTask.Content__c = component.find("taskContent").get("v.value");
    objTask.Type__c = component.find("taskType").get("v.value");
    if(objTask.Type__c === "오프라인"){
        objTask.TaskLocation__c = {};
        objTask.TaskLocation__City__s = component.find("taskAddressCity").get("v.value");
        objTask.TaskLocation__Street__s = component.find("taskAddressStreet").get("v.value");
    }else if(objTask.Type__c === "온라인"){
        objTask.SourceLink__c = component.find("taskSourceLink");
    }


    var action = component.get("c.insertTask");
    action.setParams({
        "objTask": objTask
    });
    action.setCallback(this, (response) => {
        var state = response.getState();
        if(state === "SUCCESS"){
            helper.showToast("New Task", "새로운 Task가 추가되었습니다!", "success");
        }else{
            helper.showToast("Fail", "에러가 발생하였습니다.", "error");
        }
         var navEvt = $A.get("e.force:navigateToSObject");
            navEvt.setParams({
              "recordId": component.get("v.recordId")
            });
            navEvt.fire();
    });
    $A.enqueueAction(action);
}

 

 

Task Record Page

맨위 패널과 지도 표시 부분만 Aura Component만 개발로 만들었음, 아래 패널들은 Tabs와 Fields Section임

Task 유형이 오프라인일 때만 아래와 같이 지도 컴포넌트가 나오도록 하였음

 


Task Detail & To do List

▶Task 제목과 detail, Task 완료 여부에 따라 완료 버튼 다르게 처리, To do List(Related List)를 보여줌, 체크박스 누를 시 해당 Todo 완료 처리, To do List 누를 시 Related List page로 이동, 각 To do 제목 누를시 해당 To do Record Detail 페이지로 이동

Component명: TodoRecordDetail.cmp

<aura:component description="TaskRecordDetail" controller="TaskController" implements="force:hasRecordId,force:lightningQuickActionWithoutHeader,flexipage:availableForAllPageTypes" access="global">
    <aura:attribute type="Object" name="objTask"/>
    <aura:attribute type="List" name="listTodo"/>
    <aura:handler name="init" value="{!this}" action="{!c.fnInit}"/>
    <aura:handler event="force:refreshView" action="{!c.fnInit}" />
    <aura:attribute name="recordError" type="String" access="private"/>
    <force:recordData aura:id="recordHandler"
                      recordId="{!v.recordId}"
                      fields="Id"
                      targetError="{!v.recordError}"
                      recordUpdated="{!c.handleRecordUpdated}" />
    <article class="slds-card">
        <div class="slds-card__header slds-grid">
            <header class="slds-media slds-media_center slds-has-flexi-truncate">
                <div class="slds-media__body">
                    <h2 class="slds-card__header-title slds-text-heading_medium">
                        <span>&#128681;{!v.objTask.Name}</span>
                    </h2>
                </div>
                <aura:if isTrue="{!v.objTask.isFinished__c}">
                    <lightning:button label="완료 취소" onclick="{!c.fnFinishTask}"/>
                    <aura:set attribute="else">
                        <lightning:button label="완료로 표시" onclick="{!c.fnFinishTask}"/>
                    </aura:set>
                </aura:if>
                <lightning:button label="Edit" onclick="{!c.fnEditRecord}"/>
                <lightning:button label="Delete" onclick="{!c.fnDeleteRecord}"/>
            </header>
        </div>
        <div class="slds-card__body slds-card__body_inner">
            <h5 class="slds-text-heading_small">{!v.objTask.Content__c}</h5>
        </div>
        <div class="slds-card__body slds-card__body_inner">
            <article class="slds-card slds-card_boundary">
                <div class="slds-card__header slds-grid">
                    <header class="slds-media slds-media_center slds-has-flexi-truncate">
                        <div class="slds-media__body">
                            <h2 class="slds-card__header-title">
                                <a href="./related/To_do_list__r/view" class="slds-card__header-link slds-truncate" title="Card Header">
                                    <span>&#128209;To do List</span>
                                </a>
                            </h2>
                        </div>
                        <lightning:button label="추가" onclick="{!c.fnAddToDo}"/>
                    </header>
                </div>
                <div class="slds-card__body slds-card__body_inner">
                    <ul class="slds-list slds-has-dividers_top slds-has-divider_bottom slds-has-block-links_space">
                        <aura:iteration items="{!v.listTodo}" var="todo">
                            <li class="slds-item">
                                <aura:if isTrue="{!todo.isFinished__c}">
                                    <div class="slds-list_inline"><input id="{!todo.Id}" type="checkbox" onchange="{!c.fnChangeState}" checked="checked"/>
                                    <a href="{!'/'+todo.Id}"><span style="text-decoration:line-through">{!todo.Name}</span></a></div>
                                    <aura:set attribute="else">
                                        <div class="slds-list_inline"> <input id="{!todo.Id}" type="checkbox" onchange="{!c.fnChangeState}"/>
                                            <a href="{!'/'+todo.Id}"><span style="text-decoration:none">{!todo.Name}</span></a></div>
                                    </aura:set>
                                </aura:if>
                            </li>
                        </aura:iteration>
                    </ul>
                </div>
            </article>
        </div>
    </article>
</aura:component>

*Record detail 페이지로 이동 url: (도메인)/lightning/r/(Object API Name)/(recordId)/view

(도메인)/(recordId) 이런식으로만 써도 알아서 위의 url로 이동됨

*Related List 페이지로 이동 url: ./related/(Lookup 등 API Name)/view

.은 record page url에서 view 제외한 부분, 이 부분을 절대경로로 다 써줘도 됨

 

TaskController(Apex Controller)

public with sharing class TaskController {

    @AuraEnabled
    public static Task__c getTask(String recordId){
        Task__c objTask = [SELECT Name, Content__c, isFinished__c, (SELECT Id, Name, isFinished__c FROM To_do_list__r) FROM Task__c WHERE Id = :recordId];
        return objTask;
    }
	//생략...
    @AuraEnabled
    public static Boolean changeFinishState(String recordId){
        Task__c[] objTask = [SELECT isFinished__c FROM Task__c WHERE Id = :recordId];
        if(!objTask.isEmpty()){
            Boolean boolIsFinished = objTask[0].isFinished__c;
            objTask[0].isFinished__c = !boolIsFinished;
            update objTask;
            return !boolIsFinished;
        }
        return false;
    }
}

완료 상태를 바꾸는 함수는 위와 같이 구현하였음

 

 

 


 

 

Task Location 지도 표시 부분

lightning:map 태그 사용, mapMarkers라는 변수를 두고 Map 세팅

Task의 Address 필드 정보를 받아와서 화면에 지도로 보여줌

Component명: TaskLocation.cmp

<aura:component controller="TaskController" description="TaskLocation" implements="force:hasRecordId,force:lightningQuickActionWithoutHeader,flexipage:availableForAllPageTypes" access="global">
    <aura:attribute name="mapMarkers" type="Object[]"/>
    <aura:handler name="init" value="{! this }" action="{! c.fnInit }"/>
    <aura:handler event="force:refreshView" action="{!c.fnInit}" />
    <lightning:map mapMarkers="{! v.mapMarkers }" zoomLevel="15"/>
</aura:component>

*lightning:map 태그 내에 속성을 세팅해줘야함

-mapMarkers: 표시할 지도 위치(location), 핀 타이틀(title), 설명(description) 등 세팅, 아래 컨트롤러에서 지정해줬음

-zoomLevel은 확대 정도 세팅

 

({
    fnInit: function(component, event){
        var action = component.get("c.getAddress"); //주소 필드 가져오는 함수
        action.setParams({
            recordId: component.get("v.recordId")
        });
        action.setCallback(this, function(response){
            var state = response.getState();
            if(state === "SUCCESS"){
                var mapAddress = response.getReturnValue();
                console.log(mapAddress);
                var mapMarkers = [{
                                 location: {
                                     Street: mapAddress.Street,
                                     City: mapAddress.City,
                                     Country: '대한민국'
                                 },
                                 title: 'Task 장소',
                                 description: 'Task 장소'
                }];
                component.set("v.mapMarkers", mapMarkers);
            }else{ //주소를 불러오는데 오류가 났을 때는 그냥 대한민국 지도 보여줌
                var mapMarkers = [{
                    location: {Country: '대한민국'},
                    title: 'Task 장소',
                    description: 'Task 장소'
                    }];
                component.set("v.mapMarkers", mapMarkers);
            }
        });
        $A.enqueueAction(action);
    }
});

Location은 Country, City, Street 등으로 구성된 위치 정보 Object가 들어감

 

 

 

 

'세일즈포스' 카테고리의 다른 글

LWC Lifecycle Hooks  (0) 2023.10.30
Salesforce 실습해보기 1(Lightning Component/Aura)  (0) 2023.10.18