12

Today I'm giving the new v41.0 <lightning:outputField> a try. I want to use it massively inside an <aura:iteration> to build a data-table and want to accomplish the following:

  • Internationalized output: correct decimal delimiter, correct date and number formats. Tried lightning:formattedNumber does not work as expected, because it takes the settings of the browser, but I need to use the the users salesforce locale not the locale defined in the browser). Basically this is done very good by <lightning:outputField>. Exactly as expected!
  • Eventually I want an editable table with picklists, transaltions, lookups all the good stuff, you name it. And high numbers of it. So I would like to switch to <lightning:inputField> in the end. But as starter Read-Only is good enough.

I would need to adjust several things of <lightning:outputField>. The mode variant="label-hidden" helps but is still messing things up in my layout. Therefore I thought about to extend and customize the component as described here:

https://developer.salesforce.com/blogs/developer-relations/2015/03/salesforce-lightning-components-by-example-component-extension.html

1. Is it possible at all?

I have tried this:

<aura:component extends="lightning:outputField">
    <!--...-->
</aura:component>

But when I want to save the markup, I get only

FIELD_INTEGRITY_EXCEPTION

cannot extend non-extensible component

2. Are Standard Components extensible at all?

Are some / all or none of the Salesforce-Standard components (those of the namespaces force:, ui: and lightning:) extensible="true" or not? Where (documentation, documentation-app, etc.) can I find if and which component is be extensible or not?

3. Even if it would be possible, is extension a good idea?

The rendering of the component is not inline. It creates several display:block; and inline-block; elements in the DOM. This is messing-up my layout (huge table, lots of lines, lots more of <lightning:outputField>). Now is extension a good approach to make something which fits only partly better fit into the requirements? The partly good fit is localization: <lightning:outputField> comes in good old Visualforce quality I was used to from <apex:outputField>! Perfect!

4. Slow and async rendering

To use lightning:outputField inside a table and inside an iteration over the <tr> I was only able to do it like this

<tbody>
    <aura:iteration items="{! v.Opportunities }" var="item">
        <tr>
            <td>
                <lightning:recordViewForm recordId="{!item.Id}" objectApiName="Opportunity">
                    <lightning:outputField fieldName="CloseDate" variant="label-hidden" />
                </lightning:recordViewForm>
            </td>
            <!-- !! lots more of outputFields to come ... !! </td>-->
        </tr>
    </aura:iteration>
</tbody>

I would have preferred to have only on single <lightning:recordViewForm> per <tr> but this is messing-up the table layout completely. That's the reason for lots of <lightning:recordViewForm> per <tr>. It works, but I need massive CSS-hacks to adjust the rendering and it becomes very slow and does not scale good.

5. Is <lightning:recordViewForm> designed to be used in high numbers?

All this looks and feels like <lightning:recordViewForm> is designed to be used only once or at least only in a very small number of occurrences per component or page. I did not see it stated in the docs, but is I my feeling correct that it should be used only a few times and not a couple of hundred times? If so, what is the best practice for such tables?

  • 1
    As an alternate solution, have you looked at lightning:datatable this looks promising with support to all types of fields if you are ready to spin up your own wrapper object and hook it to the data attribute developer.salesforce.com/docs/atlas.en-us.lightning.meta/… – Rao Oct 12 '17 at 16:50
  • @Rao super interesting! This looks really awsome and for sure I will use it - unfortunately here it probably won't work: I need fine-grain access to the cells (css, colorize, custom-content), I need lookups - AND (now it comes!) lightning:datatable is using as lightning:formattedNumber the clinentside-browser-locale and NOT the serverside-salesforce-user-locale. I dont understand, we salesforce is coming up with such inconsisten locale-behavior. Also the columsizes are adaptable, but are falling back every page-load... – Uwe Heim Oct 12 '17 at 17:16
  • @Rao, so as nice as a datatable approach will ever be - as an alternative, we will still need flexible building-blocks of whateverTheHeckNamespace:inputField and :outputField to compose all those shiny editable-tables, tree-tables, accordion-tables, nested-editors and whatever ideas the our clients will come up with. My concern now is, that lightning:inputField - again like force:inputField - is not as powerful as apex:inputField was in VF.... in my tests more issues and questions came up - and it looks like i will have to ask more of them here ;-) – Uwe Heim Oct 12 '17 at 17:24
  • totally agree we are just dealing with whatever is getting thrown at us, for some of my projects i have scratched lightning based approach and adapted third party js route( cavet being I am having to use salesforce supported version and not the latest version at times) – Rao Oct 12 '17 at 17:32
6
  1. Is it possible at all?

No.

  1. Are Standard Components extensible at all?

No.

  1. Even if it would be possible, is extension a good idea?

It'd be potentially useful, but we can't.

  1. Slow and async rendering

You shouldn't be using tables. It's a shame that they actually allow it, because tables are not used anywhere in Lightning at all. Everything is meant to be responsive, and tables are not responsive by nature. You didn't say exactly how your layout got messed up, but you should look at the lightning:layout element to create a grid that can reflow elegantly with fewer CSS hacks.

  1. Is <lightning:recordViewForm> designed to be used in high numbers?

The documentation doesn't say, but I'd have to guess "probably not." You might consider using force:outputField/force:inputField instead. I've had much better luck using combinations of lightning:layout and lightning:layoutItem. This give you better control over how things are laid out.

Also, I'd solidly recommend pagination if you're looking at more than ~25 items. Actually, using pagination or infinite scrolling might be a better idea anyways; the data could load progressively so that you can minimize the rendering time.

| improve this answer | |
  • all very good - only in terms of table I disagree: there is use of tables in lightning, e.g. on any list-view on any top-level tab. there are also SLDS classes for tables like slds-table, slds-table_bordered and there is the new lightning:datatable hot-shot mentioned by @Rao. So tables are dead - long live the tables ;-) I really need them and used properly, html-tables are powerful beasts. aah, and last but not least: force:outputField/force:inputField ==> IMHO total crap, tried today again: no chance inside aura:iteration (known bug!). – Uwe Heim Oct 12 '17 at 19:59
  • mess-up by lightning:outputField is DOM-output as display:block; and inline-block; done by Salesforce. I need display:inline because I need to decorate stuff in the same cell by red-yellow-green indicators without having the lightning:outputField taking 100% width (as a result of display:block). I hacked it away by wrapping lightning:outputField and applying CSS selectively. Works fine for now, but is unsafe. Slowness caused by lots of lightning:recordViewForm is crazy but even that I accept for now. Each field pops up after each other, slowly without blocking the UI. looks even nice somehow – Uwe Heim Oct 12 '17 at 20:12
2

What I came eventually up with it a wrapper component around lightning:recordViewForm and lightning:outputField which looks like that (look at currency and date-formats - they will adapt strictly to the locale of the salesforce-user ignoring any browser or OS locales)

enter image description here

As you see, the it can be combined with anything in any cell. Full flexibility, rendered inline.

The compo is markup-only, no controller, no helper needed:

<aura:component >
    <aura:attribute name="id"                           type="String"                   default="" />
    <aura:attribute name="object"                       type="String"                   default="" />
    <aura:attribute name="field"                        type="String"                   default="" />
    <aura:attribute name="wrap"                         type="Boolean"                  default="true" />
    <style>
        .elfLCXLightningOutputField .elfForceInline *               { display: inline !important; color: inherit; font-size:inherit; }
        .elfLCXLightningOutputField .elfForceWrap *                 { white-space: normal !important; }
    </style>
    <span class="elfLCXLightningOutputField">
        <span class="{! 'elfForceInline ' + (v.wrap?' elfForceWrap ':'') }">
            <lightning:recordViewForm recordId="{!v.id}" objectApiName="{!v.object}">
                <lightning:outputField fieldName="{!v.field}" variant="label-hidden" />
            </lightning:recordViewForm>
        </span>
    </span>
</aura:component>

Used like that

<tbody>
    <aura:iteration items="{! v.Opportunities }" var="item">
        <tr class="elfItemRow" 
        >
            <td data-label="" class="elfAlignRight">
                <c:elfLCXLightningOutputField id="{!item.Id}" object="Opportunity" field="CloseDate" />                             
                &nbsp;
                <span class="elfCloseStatusIndicator" title="{! item.___elfCloseStatus }">&nbsp;</span>
            </td>
            <td data-label="" class="elfAlignRight">
                <c:elfLCXLightningOutputField id="{!item.Id}" object="Opportunity" field="CreatedDate" />
            </td>
            <td data-label="" class="elfAlignRight">
                <c:elfLCXLightningOutputField id="{!item.Id}" object="Opportunity" field="Amount" wrap="false"/>
            </td>
        </tr>
    </aura:iteration>
</tbody>

What I notice is that due to the massive use of lightning:recordViewForm lots of async request are ongoing. lightning:recordViewForm and lightning:outputField seem to query their own data. They do not use what I have loaded already in the iterator. The effect is strange but at this stage for me acceptable: it loads the table quickly with all these fields black. Then like an animation each single field pops out asynchronously. It's not blocking the UI.

I expect that this is very inefficient and would love to get a more mass-data-capable inputField from Salesforce - but having the same features like lightning:outputField

Caution:

Another thing I have noticed is that subsequential settings of the v.Opportunities attribute is causing Javascript exceptions - but ALL the compos do update correctly. As a workaround I wrapped the cmp.set() with a try/catch to suspend the error.

| improve this answer | |

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.