0

I have an aura component which is a combination of forceChatter:Publisher and forceChatter:feed. But here in my case forceChatter:feed is getting rendered before forceChatter:Publisher. I want forceChatter:publisher to render before forceChatter:feed.

My code is a follows:

feedcomponent.cmp

<aura:component controller="chatterController" implements="force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId,forceCommunity:availableForAllPageTypes,force:lightningQuickAction" access="global" >
    <aura:handler name="init" action="{!c.doInit}" value="{!this}" access="global" />
      <aura:attribute name="contactList" type="String" />
    <aura:handler event="force:refreshView" action="{!c.doInit}" />
    <div aura:id="publisher">     
    </div>
    <div aura:id="container">
    </div>
</aura:component>

feedcomponent.js

({
    doInit : function(component, event, helper) {
        var action = component.get("c.setViewStat");    
        var artId = component.get("v.recordId");     
        action.setParams({
            "artId":artId
        });
        action.setCallback(this, function(response){
            let state = response.getState();
            if(state === "SUCCESS"){
                component.set('v.contactList',response.getReturnValue());
                console.log(response.getReturnValue());
                console.log(component.get("v.contactList"));
                var container = component.find("container");
                var publisher = component.find("publisher");
                $A.createComponent(
                    "forceChatter:publisher", {
                        "context": "RECORD",
                        "recordId": response.getReturnValue()
                    },
                    function(recordFeed) {
                        if (component.isValid()) {
                            var body = component.get("v.body");
                            body.push(recordFeed);
                            publisher.set("v.body", body);
                        }
                    }); 
                $A.createComponent(
                    "forceChatter:feed", {
                        "type": "Record",
                        "subjectId": response.getReturnValue()
                    },
                    function(recordFeed) {
                        if (component.isValid()) {
                            var body = component.get("v.body");
                            body.push(recordFeed);
                            containers.set("v.body", body);
                        }
                    });      
            }else{
                alert('Something went wrong');
            } 
        });    
        $A.enqueueAction(action);
    }
})

How do I render forceChatter:Publisher before forceChatter:feed?

1 Answer 1

2

$A.createComponent is an asynchronous function. You cannot guarantee the order of execution when you put multiple calls in a row.

Either use $A.createComponents to create both components at once:

$A.createComponents(
    [
        [
            'forceChatter:publisher',
            {
                context: 'RECORD',
                recordId: response.getReturnValue(),
            },
        ],
        [
            'forceChatter:feed',
            {
                type: 'Record',
                subjectId: response.getReturnValue(),
            },
        ],
    ],
    function (recordFeed) {
        if (component.isValid()) {
            var body = component.get('v.body');
            body = body.concat(recordFeed);
            publisher.set('v.body', body);
        }
    }
);

Or create one after the other in order. I recommend a Promise to make things easier:

const createComponent = (elementName, elementProperties) => {
    return new Promise((resolve, reject) => {
        $A.createComponent(elementName, elementProperties, (element, status, error) => {
            if (status === 'SUCCESS') {
                resolve(element);
            } else {
                reject(error);
            }
        });
    });
};
const addToBody = (element) => {
    let body = component.get('v.body');
    body.push(element);
    component.set('v.body', body);
};
createComponent('forceChatter:publisher', {
    context: 'RECORD',
    recordId: response.getReturnValue(),
})
    .then(
        (element) => addToBody(element),
        createElement('forceChatter:feed', {
            type: 'Record',
            subjectId: response.getReturnValue(),
        })
    )
    .then((element) => {
        addToBody(element);
    });

Keep in mind that this may involve two round trips to the server, so it may delay loading of your component.

1
  • Thanks @sfdcfox. Working like a charm! Commented Feb 20, 2021 at 11:03

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .