• Moshe Baitelman
  • NEWBIE
  • 0 Points
  • Member since 2018

  • Chatter
    Feed
  • 0
    Best Answers
  • 0
    Likes Received
  • 0
    Likes Given
  • 3
    Questions
  • 2
    Replies
I have a custom lightning component. It works fine in almost all instances I choose to use it. The functionality is fine. It works in apps, on record page, etc.

When I add the component to the layout of a communities page in the Community Builder, the builder breaks.

This happens before the Init handler is called and everything works when I use lightning app builder so it is unrelated to the controller but I have included that code as well.

To Replicate:
Go to Communities > Choose a community builder > Create a new page (any layout) > Add in the Custom Component (code shown below).

The moment you do so, the container where you placed the component disappears and cannot be reached again. This means I am unable to make changes to the design resources, delete the component, move the component, etc.

Can't figure out for the life of me why. Salesforce error on reload is highly uninformative.

Before adding component:
Before adding componentAfter adding component:
User-added imageAfter page reload:
After reload
Component Code:
<aura:component
        description="PriorityOrdersList"
        implements="force:appHostable,flexipage:availableForAllPageTypes,forceCommunity:availableForAllPageTypes,lightning:availableForFlowScreens"
        access="global"
        controller="priorityOrdersListController"
>

    <!-- handlers-->
    <aura:handler name="init" value="{! this }" action="{! c.init }"/>
    <aura:handler name="modalClosed" event="c:rsModalClosed" action="{!c.onModalClosed}"/>

    <!-- attributes -->
    <aura:attribute
            name="listStatus"
            type="String"
            access="public"
            default="Waiting"
    />
    <aura:attribute
            name="orderData"
            access="private"
            type="Object"
    />
    <aura:attribute
            name="columns"
            type="List"
            access="private"
    />
    <aura:attribute
            name="sortOrder"
            type="String"
            required="true"
            default="rw_Priority__c"
    />
    <aura:attribute
            name="urlSeed"
            type="String"
            required="true"
            default="https://rlscn.force.com/WMS/s/packing"
    />
    <aura:attribute
            name="isLoading"
            type="Boolean"
            access="private"
            default="true"
    />
    <aura:attribute
            name="isModalOpen"
            type="boolean"
            access="private"
            required="false"
    />
    <aura:attribute
            name="modalMessage"
            type="string"
            access="private"
            required="false"
    />

    <lightning:card class="slds-card__body slds-card__body_inner">

        <div style="height: 200px;">
            This is here just to give height to the component and create visibility.
        </div>

        <aura:if isTrue="{! not(v.isLoading) }">
            <aura:if isTrue="{!v.orderData}">
                <!-- the container element determines height of the datatable -->
                <h1 class="slds-m-vertical_small">Orders to fulfill (temporary interface)</h1>

                <lightning:button label="Refresh List" onclick="{! c.refreshOrders}" iconName="utility:refresh"
                                  iconPosition="right"/>

                <div style="height: auto">
                    <lightning:datatable
                            columns="{! v.columns }"
                            data="{! v.orderData }"
                            keyField="Id"
                            hideCheckboxColumn="true"
                            onrowaction="{! c.handleRowAction }"/>
                </div>

                <aura:set attribute="else">
                    <div class="slds-box slds-p-around_small slds-m-vertical_medium">
                        <i>Hooray! You've fulfilled all the orders!</i>
                    </div>
                </aura:set>

            </aura:if>
            <aura:set attribute="else">
                <lightning:spinner variant="brand" size="medium" alternativeText="Loading..."/>
            </aura:set>


        </aura:if>


    </lightning:card>

    <!-- Only display Modal if there is not a blocking operation taking place. -->
    <c:rsModal aura:id="modal" isOpen="{!v.isModalOpen}">
        <aura:unescapedHtml value="{!v.modalMessage}"/>
    </c:rsModal>

</aura:component>
({
    init: function (cmp, event, helper) {

        cmp.set('v.columns', [
            {label: 'Order', fieldName: 'Name'},
            {label: 'Customer', fieldName: 'Account_Owner_for_Sharing_2__c'},
            {label: 'Brand ', fieldName: 'Brand_RL__c'},
            {label: 'Order Number', fieldName: 'rw_Customer_Order__c'},
            {label: 'Priority', fieldName: 'rw_Priority__c'},
            {label: 'Order Date', fieldName: 'Order_Date__c'},
            {
                label: 'Fulfill', type: 'button',
                typeAttributes: {
                    label: 'Fulfill',
                    name: 'fulfill',
                    title: 'Click to fulfill this order',
                    disabled: {fieldName: 'unfillable'}
                }
            }
        ]);

        if (cmp.get("v.listStatus") == 'Waiting') {
            helper.getOrders(cmp);
        } else {
            let message = 'Unknown error';
            console.log(message + ': Did not call for orders.');
        }
    },
    refreshOrders: function (cmp, event, helper) {
        cmp.set("v.isLoading", true);
        helper.getOrders(cmp);
    },

    handleRowAction: function (cmp, event, helper) {
        var action = event.getParam('action');
        var row = event.getParam('row');

        switch (action.name) {
            case 'fulfill':
                helper.launchScanner(cmp, row.Id);
                helper.disableRow(cmp, row);
                break;
        }

    },


    // To Close Modal
    onModalClosed: function (cmp, event, helper) {
        cmp.set('v.modalMessage', null);
        cmp.set('v.isModalOpen', false);
    }
});

Component Helper
{
    getOrders: function (cmp) {
        var helper = this;
        var action = cmp.get('c.getOrderPriorityList');
        var sortOrder = cmp.get('v.sortOrder');

        action.setParams({sortOrder: sortOrder});
        action.setCallback(helper, function (response) {
            var state = response.getState();
            if (state === "SUCCESS") {

                var orderList = response.getReturnValue();

                if(orderList.length > 0) {

                    var rows = response.getReturnValue();     //storing the response in a temporary variable
                    //looping through each row of the result
                    for (var i = 0; i < rows.length; i++) {
                        var row = rows[i];
                        // data columns with relationship __r can not be displayed directly in data table, so generating dynamic columns
                        row.unfillable = false;
                    }

                    orderList = response.getReturnValue();
                    cmp.set("v.orderData", orderList);
                }

            } else if (state === "ERROR") {
                let errors = response.getError();
                let message = 'Unknown error'; // Default error message
                // Retrieve the error message sent by the server
                if (errors && Array.isArray(errors) && errors.length > 0) {
                    message = errors[0].message;
                }
                // Display the message
                this.alert(
                    cmp,
                    'Error Fetching Data',
                    message,
                    'error',
                    false
                );
            } else {
                console.log("Failed with state: " + state);
            }
            cmp.set("v.isLoading", false);
            cmp.set("v.listStatus", 'DataReady')
        });

        // Send actions to be executed
        $A.enqueueAction(action);

    },
    
    launchScanner: function (cmp, orderId) {
        var pageUrl = cmp.get("v.urlSeed");
        window.open(pageUrl + "?recordId=" + orderId);
    },
    disableRow: function(cmp, row) {
        var data = cmp.get('v.orderData');
        var rowIndex = data.indexOf(row);
        data[rowIndex].unfillable = true;
        cmp.set('v.orderData', data);
    },


    getModalCmp: function(cmp, isRequired) {
        return this.getCmp(cmp, 'modal', isRequired);
    },
    getCmp: function(cmp, auraId, isRequired) {
        if(isRequired === undefined) { isRequired = true; }
        var output = cmp.find(auraId);

        if(isRequired && !output) {
            throw new Error('Could not find component with Aura ID: '+auraId);
        }

        return output;
    },


    alert: function(cmp, title, message, theme, hideCloseButton) {
        var modalCmp = this.getModalCmp(cmp);

        if(hideCloseButton === undefined) {
            hideCloseButton = false;
        }

        if(modalCmp) {
            var messageEscaped = this.escapeHtml(message);
            var messageHtml = messageEscaped.replace(/\n/g, '<br />');

            cmp.set('v.isModalOpen', false);
            cmp.set('v.modalMessage', messageHtml);
            modalCmp.set('v.hideDefaultCloseControls', hideCloseButton);
            modalCmp.set('v.variant', 'alert');
            modalCmp.set('v.title', title);
            modalCmp.set('v.theme', theme || 'default');
            cmp.set('v.isModalOpen', true);
        } else {
            cmp.set('v.modalMessage', message);
            alert(message);
        }

    },

    escapeHtml: function(text) {

        // Copied from://stackoverflow.com/a/4835406

        var map = {
            '&': '&amp;',
            '<': '&lt;',
            '>': '&gt;',
            '"': '&quot;',
            "'": '&#039;'
        };

        return text.replace(
            /[&<>\x22\x27]/g,
            function(m) { return map[m]; }
        );
    }
})

Design
<design:component>
    <design:attribute name="sortOrder" description="Fields by which to sort the orders"
                      default="Order_Date__c, rw_Priority__c" required="true" label="Sort ORDER BY" />
    <design:attribute name="urlSeed" description="URL to append the RecordID to when initiating the packing interface"
                      default="https://rlscn.force.com/WMS/s/packing" required="true" label="Base URL" />
</design:component>


Apex Controller
public with sharing class priorityOrdersListController {

    @AuraEnabled
    public static List<rw_Shipment__c> getOrderPriorityList(String sortOrder) {

        try {
            String queryString = 'SELECT Id, Name, rw_Status__c, Warehouse_Status__c, CreatedDate, ' +
                    'Account_Owner_for_Sharing_2__c, Brand_RL__c, Brand_RL__r.Name, rw_Customer_Order__c, rw_Priority__c, Order_Date__c ' +
                    'FROM rw_Shipment__c ' +
                    'WHERE rw_Status__c = \'SAVED\' AND ' +
                    '(Warehouse_Status__c = \'Allocated\' ' +
                    'OR Warehouse_Status__c = \'Picking Slip Generated\' ' +
                    'OR Warehouse_Status__c = \'Packing Slip Generated\') ' +
                    'ORDER BY '+ sortorder + ' LIMIT 50';
            List<rw_Shipment__c> orderPriorityList = database.query(queryString);

            return orderPriorityList;
        } catch (Exception ex) {
            throw new AuraHandledException('No orders found found matching ' + ex.getMessage());
        }
  }
}

 
Hey all!

We have a process builder that is supposed to execute when a picklist field equals a specific option. When a user manually updates this picklist field or if I update it with Anonymous Apex, the process builder runs appropriately.

We also have a hourly batch job that often sets the picklist value. When the field is updated by the batch apex, the process builder does not run.

I have reviewed the execution order documentation (https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_triggers_order_of_execution.htm) and process builder documentation. 

I am not reopening the debate/conversation of PB vs Trigger. Question is: is there a way to use apex to prevent process builder from running? Is there a difference because this is batch apex? Has anyone ever come across something like this? Why would my process not trigger when the update happens via batch apex vs manual change?
 
Building my first Lightning component to go on a record details page in Communities.

I have to calculate 3 values. 2 are calculated in the doInit function in the controller with callback functions. The third is the sum of the first two.

I tried writing another function to calculate the 3rd value, calling that function in the callback response but I get an error that the function is not defined. 
Please see controller code provided
({
	doInit : function(component, event, helper) {
        // define recordid
        var recordId = component.get("v.recordId"); 

        // Create actions
        var action1 = component.get("c.getShipmentCost");
        action1.setParams({ wamshipment : recordId });
        var action2 = component.get("c.getFulfillmentCost")
        action2.setParams({ wamshipment : recordId });
        
        // Add callback behavior
        action1.setCallback(this, function(response) {
            var state = response.getState();
            if (state === "SUCCESS") {
                component.set("v.shipmentcost", response.getReturnValue());
            } else {
                console.log("Failed with state: " + state);
            }
        });
        
        action2.setCallback(this, function(response) {
            var state = response.getState();
            if (state === "SUCCESS") {
                component.set("v.fulfillmentCost", response.getReturnValue());
                // Call function to calculate third variable
                calculateTotal();
            } else {
                console.log("Failed with state: " + state);
            }
        })
        // Send actions to be executed
        $A.enqueueAction(action1);
        $A.enqueueAction(action2);
        
    },
    calculateTotal: function(component, event, helper) {
    	var scost = component.get("v.shipmentcost");
        var fcost = component.get("v.fulfillmentcost");
        var total = fcost + scost;
        component.set("v.totalcost", total);
    }
    
})
(I wouldn't be opposed to moving the functions in the init function to the helper, I just want to get this to work first).
Any help is greatly appreciated!

Thanks!
I have a custom lightning component. It works fine in almost all instances I choose to use it. The functionality is fine. It works in apps, on record page, etc.

When I add the component to the layout of a communities page in the Community Builder, the builder breaks.

This happens before the Init handler is called and everything works when I use lightning app builder so it is unrelated to the controller but I have included that code as well.

To Replicate:
Go to Communities > Choose a community builder > Create a new page (any layout) > Add in the Custom Component (code shown below).

The moment you do so, the container where you placed the component disappears and cannot be reached again. This means I am unable to make changes to the design resources, delete the component, move the component, etc.

Can't figure out for the life of me why. Salesforce error on reload is highly uninformative.

Before adding component:
Before adding componentAfter adding component:
User-added imageAfter page reload:
After reload
Component Code:
<aura:component
        description="PriorityOrdersList"
        implements="force:appHostable,flexipage:availableForAllPageTypes,forceCommunity:availableForAllPageTypes,lightning:availableForFlowScreens"
        access="global"
        controller="priorityOrdersListController"
>

    <!-- handlers-->
    <aura:handler name="init" value="{! this }" action="{! c.init }"/>
    <aura:handler name="modalClosed" event="c:rsModalClosed" action="{!c.onModalClosed}"/>

    <!-- attributes -->
    <aura:attribute
            name="listStatus"
            type="String"
            access="public"
            default="Waiting"
    />
    <aura:attribute
            name="orderData"
            access="private"
            type="Object"
    />
    <aura:attribute
            name="columns"
            type="List"
            access="private"
    />
    <aura:attribute
            name="sortOrder"
            type="String"
            required="true"
            default="rw_Priority__c"
    />
    <aura:attribute
            name="urlSeed"
            type="String"
            required="true"
            default="https://rlscn.force.com/WMS/s/packing"
    />
    <aura:attribute
            name="isLoading"
            type="Boolean"
            access="private"
            default="true"
    />
    <aura:attribute
            name="isModalOpen"
            type="boolean"
            access="private"
            required="false"
    />
    <aura:attribute
            name="modalMessage"
            type="string"
            access="private"
            required="false"
    />

    <lightning:card class="slds-card__body slds-card__body_inner">

        <div style="height: 200px;">
            This is here just to give height to the component and create visibility.
        </div>

        <aura:if isTrue="{! not(v.isLoading) }">
            <aura:if isTrue="{!v.orderData}">
                <!-- the container element determines height of the datatable -->
                <h1 class="slds-m-vertical_small">Orders to fulfill (temporary interface)</h1>

                <lightning:button label="Refresh List" onclick="{! c.refreshOrders}" iconName="utility:refresh"
                                  iconPosition="right"/>

                <div style="height: auto">
                    <lightning:datatable
                            columns="{! v.columns }"
                            data="{! v.orderData }"
                            keyField="Id"
                            hideCheckboxColumn="true"
                            onrowaction="{! c.handleRowAction }"/>
                </div>

                <aura:set attribute="else">
                    <div class="slds-box slds-p-around_small slds-m-vertical_medium">
                        <i>Hooray! You've fulfilled all the orders!</i>
                    </div>
                </aura:set>

            </aura:if>
            <aura:set attribute="else">
                <lightning:spinner variant="brand" size="medium" alternativeText="Loading..."/>
            </aura:set>


        </aura:if>


    </lightning:card>

    <!-- Only display Modal if there is not a blocking operation taking place. -->
    <c:rsModal aura:id="modal" isOpen="{!v.isModalOpen}">
        <aura:unescapedHtml value="{!v.modalMessage}"/>
    </c:rsModal>

</aura:component>
({
    init: function (cmp, event, helper) {

        cmp.set('v.columns', [
            {label: 'Order', fieldName: 'Name'},
            {label: 'Customer', fieldName: 'Account_Owner_for_Sharing_2__c'},
            {label: 'Brand ', fieldName: 'Brand_RL__c'},
            {label: 'Order Number', fieldName: 'rw_Customer_Order__c'},
            {label: 'Priority', fieldName: 'rw_Priority__c'},
            {label: 'Order Date', fieldName: 'Order_Date__c'},
            {
                label: 'Fulfill', type: 'button',
                typeAttributes: {
                    label: 'Fulfill',
                    name: 'fulfill',
                    title: 'Click to fulfill this order',
                    disabled: {fieldName: 'unfillable'}
                }
            }
        ]);

        if (cmp.get("v.listStatus") == 'Waiting') {
            helper.getOrders(cmp);
        } else {
            let message = 'Unknown error';
            console.log(message + ': Did not call for orders.');
        }
    },
    refreshOrders: function (cmp, event, helper) {
        cmp.set("v.isLoading", true);
        helper.getOrders(cmp);
    },

    handleRowAction: function (cmp, event, helper) {
        var action = event.getParam('action');
        var row = event.getParam('row');

        switch (action.name) {
            case 'fulfill':
                helper.launchScanner(cmp, row.Id);
                helper.disableRow(cmp, row);
                break;
        }

    },


    // To Close Modal
    onModalClosed: function (cmp, event, helper) {
        cmp.set('v.modalMessage', null);
        cmp.set('v.isModalOpen', false);
    }
});

Component Helper
{
    getOrders: function (cmp) {
        var helper = this;
        var action = cmp.get('c.getOrderPriorityList');
        var sortOrder = cmp.get('v.sortOrder');

        action.setParams({sortOrder: sortOrder});
        action.setCallback(helper, function (response) {
            var state = response.getState();
            if (state === "SUCCESS") {

                var orderList = response.getReturnValue();

                if(orderList.length > 0) {

                    var rows = response.getReturnValue();     //storing the response in a temporary variable
                    //looping through each row of the result
                    for (var i = 0; i < rows.length; i++) {
                        var row = rows[i];
                        // data columns with relationship __r can not be displayed directly in data table, so generating dynamic columns
                        row.unfillable = false;
                    }

                    orderList = response.getReturnValue();
                    cmp.set("v.orderData", orderList);
                }

            } else if (state === "ERROR") {
                let errors = response.getError();
                let message = 'Unknown error'; // Default error message
                // Retrieve the error message sent by the server
                if (errors && Array.isArray(errors) && errors.length > 0) {
                    message = errors[0].message;
                }
                // Display the message
                this.alert(
                    cmp,
                    'Error Fetching Data',
                    message,
                    'error',
                    false
                );
            } else {
                console.log("Failed with state: " + state);
            }
            cmp.set("v.isLoading", false);
            cmp.set("v.listStatus", 'DataReady')
        });

        // Send actions to be executed
        $A.enqueueAction(action);

    },
    
    launchScanner: function (cmp, orderId) {
        var pageUrl = cmp.get("v.urlSeed");
        window.open(pageUrl + "?recordId=" + orderId);
    },
    disableRow: function(cmp, row) {
        var data = cmp.get('v.orderData');
        var rowIndex = data.indexOf(row);
        data[rowIndex].unfillable = true;
        cmp.set('v.orderData', data);
    },


    getModalCmp: function(cmp, isRequired) {
        return this.getCmp(cmp, 'modal', isRequired);
    },
    getCmp: function(cmp, auraId, isRequired) {
        if(isRequired === undefined) { isRequired = true; }
        var output = cmp.find(auraId);

        if(isRequired && !output) {
            throw new Error('Could not find component with Aura ID: '+auraId);
        }

        return output;
    },


    alert: function(cmp, title, message, theme, hideCloseButton) {
        var modalCmp = this.getModalCmp(cmp);

        if(hideCloseButton === undefined) {
            hideCloseButton = false;
        }

        if(modalCmp) {
            var messageEscaped = this.escapeHtml(message);
            var messageHtml = messageEscaped.replace(/\n/g, '<br />');

            cmp.set('v.isModalOpen', false);
            cmp.set('v.modalMessage', messageHtml);
            modalCmp.set('v.hideDefaultCloseControls', hideCloseButton);
            modalCmp.set('v.variant', 'alert');
            modalCmp.set('v.title', title);
            modalCmp.set('v.theme', theme || 'default');
            cmp.set('v.isModalOpen', true);
        } else {
            cmp.set('v.modalMessage', message);
            alert(message);
        }

    },

    escapeHtml: function(text) {

        // Copied from://stackoverflow.com/a/4835406

        var map = {
            '&': '&amp;',
            '<': '&lt;',
            '>': '&gt;',
            '"': '&quot;',
            "'": '&#039;'
        };

        return text.replace(
            /[&<>\x22\x27]/g,
            function(m) { return map[m]; }
        );
    }
})

Design
<design:component>
    <design:attribute name="sortOrder" description="Fields by which to sort the orders"
                      default="Order_Date__c, rw_Priority__c" required="true" label="Sort ORDER BY" />
    <design:attribute name="urlSeed" description="URL to append the RecordID to when initiating the packing interface"
                      default="https://rlscn.force.com/WMS/s/packing" required="true" label="Base URL" />
</design:component>


Apex Controller
public with sharing class priorityOrdersListController {

    @AuraEnabled
    public static List<rw_Shipment__c> getOrderPriorityList(String sortOrder) {

        try {
            String queryString = 'SELECT Id, Name, rw_Status__c, Warehouse_Status__c, CreatedDate, ' +
                    'Account_Owner_for_Sharing_2__c, Brand_RL__c, Brand_RL__r.Name, rw_Customer_Order__c, rw_Priority__c, Order_Date__c ' +
                    'FROM rw_Shipment__c ' +
                    'WHERE rw_Status__c = \'SAVED\' AND ' +
                    '(Warehouse_Status__c = \'Allocated\' ' +
                    'OR Warehouse_Status__c = \'Picking Slip Generated\' ' +
                    'OR Warehouse_Status__c = \'Packing Slip Generated\') ' +
                    'ORDER BY '+ sortorder + ' LIMIT 50';
            List<rw_Shipment__c> orderPriorityList = database.query(queryString);

            return orderPriorityList;
        } catch (Exception ex) {
            throw new AuraHandledException('No orders found found matching ' + ex.getMessage());
        }
  }
}

 
Hey all!

We have a process builder that is supposed to execute when a picklist field equals a specific option. When a user manually updates this picklist field or if I update it with Anonymous Apex, the process builder runs appropriately.

We also have a hourly batch job that often sets the picklist value. When the field is updated by the batch apex, the process builder does not run.

I have reviewed the execution order documentation (https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_triggers_order_of_execution.htm) and process builder documentation. 

I am not reopening the debate/conversation of PB vs Trigger. Question is: is there a way to use apex to prevent process builder from running? Is there a difference because this is batch apex? Has anyone ever come across something like this? Why would my process not trigger when the update happens via batch apex vs manual change?