8

Background

We are developing an app where we use lightning components.

Issue

When are trying to package the components, package manager returns an error referencing to some custom fields that are not found in the package. This is because when we created the namespace, it added a prefix in every custom metadata.

Workarounds

  1. Put the prefix in every custom fields and object in the component, controller and helper code.
  2. Get the prefix from a custom metadata type and build dynamically the metadata names. It works fine for the Component Controller and Helper. But we cannot set the prefix dynamically in the component page.

Expected workaround

We want to get the prefix from a custom metadata type because we have several environments and it change between them. So we can discard the 1st workaround.

Then, if we want to use custom fields dynamically in the component, we think that the only way is to use a DTO class in the controller.

What is the best practice to use the prefix namespace in Lightning Components?

Code Samples

<!-- parentComponet.cmp -->
<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes,force:hasRecordId" controller="ExampleHelper" access="global">
<aura:handler name="init" action="{!c.doInit}" value="{!this}" />
...
<aura:attribute name="prefix" type="String" access="private" default="prefix__" />
...
<c:child_1 aura:id="child_1" prefix="{!v.prefix}" settingExample="..." />
<c:child_2 aura:id="child_2" prefix="{!v.prefix}" objectExample="..." />
...
</aura:component>

<!-- parentComponentController.js -->
({
   doInit: function(cmp, event, helper){
    helper.getPrefix();
   ...
   },
   ...
})
<!-- parentComponentHelper.js -->
({
 getPrefix: function(){
   ...
   action.getCall...
   ...
   cmp.set('v.prefix', e.getReturnValue());
 });
})

-- COMPONENT CHILD --
<!-- child_1.cmp -->
<aura:component>
    <aura:attribute name="prefix" type="String" access="global" />
    <aura:attribute name="settingExample" type="Object" access="global" />
    {!v.settingExample.nameExample__c} //NOT VALID WITH PREFIX
    {!v.settingExample.[prefix]+'.'+nameExample__c} //NOT WORKING
</aura:component>
  • Each object can have many fields or just single field, that you wan to display? – Manjot Singh Nov 29 '17 at 12:05
  • Each object can have many fields. – Robertinho Sedinho Nov 29 '17 at 14:47
  • 2
    Having DTO class(Wrapper class) is the best way you could make the code work in the different namespace based on environment. – Praveen Nov 29 '17 at 15:57
  • Thank you @Praveen, I think also this is the best way. – Robertinho Sedinho Nov 30 '17 at 11:03
1

One way to achieve this is to have a Utility/Base component which can be extended by any component.

Utility.cmp

<aura:component extensible="true">
        <aura:attribute 
            name="packagePrefix" 
            type="String" 
            default="" 
            description="Package prefix is calculated by the init method."/>
        <aura:attribute 
            name="labelPrefix" 
            type="String" 
            default="c" 
            description="The label prefix, calculated from the package prefix."/>

        <aura:handler name="init" value="{!this}" action="{!c.myInit}"/>
</aura:component>

UtilityController.js

({
    myInit:function(component, event, helper) {
        // make server side call to get package prefix
        component.set("v.packagePrefix", "packagePrefixName");
        component.set("v.labelPrefix", "packagePrefixLabel");
    }
})

With extending any of your component with Utility, you get access to the package prefix.

ExampleComponent.cmp

<aura:component extends="c:Utility">
    packagePrefix : {v.packagePrefix} <br/>
    labelPrefix : {v.labelPrefix}
</aura:component>
  • Thanks Rahul. This is awesome way to have the prefix in the component but how can we use the prefix in each sobject field dynamically?{!v.settingExample.nameExample__c} //NOT VALID WITH PREFIX {!v.settingExample.[prefix]+'.'+nameExample__c} //NOT WORKING – Robertinho Sedinho Nov 29 '17 at 14:48
  • Prefix would be namespace__, to access a field value from object's instance is {!Account['namespace__customField__c']}. Based on this hypothesis, try: {!v.settingExample[prefix + 'customField__c']} – Raul Nov 29 '17 at 15:37
  • @RahulSharma dynamically field expression as suggested above will not work in Lightning Components. – Praveen Nov 29 '17 at 15:58
  • @RahulSharma as Praveen is saying, it not works in LC. Compiler returns an error because expect an integer instead of a string: {!v.settingExample[0]} – Robertinho Sedinho Nov 29 '17 at 16:05
  • I think you need to follow specific pattern in code and maybe generate a object or list in client side? – Raul Nov 29 '17 at 18:58
0

I think of the following.

You can create a new component that accepts the prefix and the fields to be displayed.

The following code may contain some bug, it is more an idea than something functional.

<!-- componentParent -->
<c:prefixComponent prefix="{!v.prefix}" item="nameExample__c" value="{!v.settingExample}" />

<!--prefixComponent.cmp -->
 <aura:component>
  <aura:handler name="init" action="{!c.doInit}" value="{!this}" />
  <aura:attribute name="prefix" type="text" />
  <aura:attribute name="item" type="text" />
  <aura:attribute name="value" type="text" />

  {!v.value}
 </aura:component>

<!-- Controller.js -->
({
doInit:function(cmp, evt, helper){
var prefix = cmp.get('v.prefix');
var item = cmp.get('v.item');
let result = '';
let elements = item.split('.');


element.forEach(item, i){
  if(i != 0){
    result += '.';
  }
  result += prefix+item;
}
let resultPrefix = value+'.'+result;
cmp.set('v.value', cmp.get(resultPrefix));

}
})

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.