2

I need to display a small number of fields, with the list being generated dynamically:

<lightning-record-view-form if:false={editMode} record-id={recordId} object-api-name={objectApiName}>
  <div class="slds-grid slds-wrap">
    <template for:each={activeCoachingConfig.fields} for:item="field">
      <div key={field.name} class="slds-col slds-size_1-of-1">
        <lightning-output-field field-name={field.name}></lightning-output-field>
      </div>
    </template>
  </div>
</lightning-record-view-form>

This is the data in activeCoachingConfig, copied from the Javascript console:

fields: Array(4)
  0: {name: "Customer_Name__c", required: false}
  1: {name: "Claim_Number__c", required: false}
  2: {name: "UPS_Tracking_Number__c", required: true}
  3: {name: "Tracking_Number_Replacement_Shipment__c", required: false}
  length: 4
  __proto__: Array(0)
guidance: "Lorem Ipsem."
__proto__: Object

Those four field names exist, are visible to the user, and even appear on the standard page layout elsewhere in the flexipage. However, when my LWC renders, only the last field in the list renders (in this example, Tracking_Number_Replacement_Shipment__c). I have re-ordered the list, and it is always the last field that renders. When I inspect the element tree in DevTools, I see all four lightning-output-fields, but the first three are empty (no label, no value, class slds-hide applied).

To try to understand what is happening, I added html to output the field name before the lightning-output-field. That displayed all four field names, but only the final output field actually rendered. Finally, I hardcoded four lightning-output-fields in the page with the same four field names. They all display, but of the dynamically rendered fields, only the final one displays. Here is my final "Diagnostic" html:

<lightning-record-view-form if:false={editMode} record-id={recordId} object-api-name={objectApiName}>
  <div class="slds-grid slds-wrap">
    <lightning-output-field field-name="Customer_Name__c"></lightning-output-field>
    <lightning-output-field field-name="Claim_Number__c"></lightning-output-field>
    <lightning-output-field field-name="UPS_Tracking_Number__c"></lightning-output-field>
    <lightning-output-field field-name="Tracking_Number_Replacement_Shipment__c"></lightning-output-field>
    <template for:each={activeCoachingConfig.fields} for:item="field">
      <div key={field.name} class="slds-col slds-size_1-of-1">
        <p>{field.name}</p>
        <lightning-output-field field-name={field.name}></lightning-output-field>
      </div>
    </template>
  </div>
</lightning-record-view-form>

and here is how it renders:

Screenshot

The three outlined sections are the hardcoded lightning-output-fields, the iterated <p> tags, an the iterated lightning-output-fields. As you can see, all four fields work when hardcoded, and field.name worked in each p tag. But only the final lightning-output-field inside the template iteration is displayed.

Finally, here is a screenshot of the DevTools inspector showing the penultimate and final lightning-output-fields.

enter image description here

Why does this not work? I have done similar components in the past without issue. Note: I have also repeated this with lightning-record-edit-form and lightning-input-fields (as I will need an edit version as well) with the same results - only the final lightning-input-field renders.

2
  • Have you tried omitting the template and rendering them directly? As in: <lightning-output-field for:each={activeCoachingConfig.fields} for:item="field" key={field.name} field-name={field.name}></lightning-output-field> ... You might get better luck with that.
    – sfdcfox
    Mar 17, 2021 at 2:31
  • 2
    Can you put the relevant parts of your controller up too? I recreated this using some standard fields from account and using your code, I get no issues. Mar 17, 2021 at 3:08

1 Answer 1

2

I was able to resolve this. It was my own bug, but I couldn't see it with the tools I was using at the time. Documenting for completeness' sake, both the SF behavior I misunderstood, and a mistake I made while debugging.

Credit to @CasparHarmer for asking me to post relevant parts of my controller code. I skipped that initially because it's a little complex, and because I could clearly see in the JS console the JSON object being generated in the controller. To make matters simple, I planned to change my controller to return that JSON value, hardcoded, to show that the issue was not my controller code. I used the Javascript Console's "Copy Object" function to copy the value from the console, and pasted it into my editor; I was very surprised to see carriage return (\r) characters in the first 3 of my the field names, which were not displayed in the JS console's nicely formatted display:

{
    "fields": [
        {
            "name": "Customer_Name__c\r",
            "required": false
        },
        {
            "name": "Claim_Number__c\r",
            "required": false
        },
        {
            "name": "UPS_Tracking_Number__c\r",
            "required": true
        },
        {
            "name": "Tracking_Number_Replacement_Shipment__c",
            "required": false
        }
    ],
    "guidance": "Lorem Ipsem."
}

This happened because my list of field names comes from a Textarea(255) field in a Custom Metadata record, and I split it with split(/;|\n/) (supporting semicolon and/or newline delimiters). Changing my regex to split(/;|(?:\r?\n)/) fixed the problem.

Takeaways:

  1. Textarea fields use Windows-style newlines (\r\n).
  2. Don't just rely on the pretty, formatted console logging- when in doubt, look at the raw text output.
  3. Always post relevant controller code.

You must log in to answer this question.

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