1

So I am trying to dynamically render out the fields of a Salesforce account, since this is supposed to be a package and I do not know what fields and rules the organization has on an account. However, I need to perform some logic on the individual field if some other code calls for it.

If I do it the simple way:

// editAccountForm.js
import { LightningElement, api, track, wire } from "lwc";
import { getObjectInfo } from "lightning/uiObjectInfoApi";
import ACCOUNT_OBJECT from "@salesforce/schema/Account";

export default class EditAccountForm extends LightningElement {
  @api accountId;

  @track objectInfo;
  @wire(getObjectInfo, { objectApiName: ACCOUNT_OBJECT })
  objectInfo;

  editableFields;

  get propertyNames() {
    // Return cached value
    if (this.editableFields) return this.editableFields;

    // Data not ready yet, return nothing
    if (!this.objectInfo || !this.objectInfo.data) return [];

    const t = Object.values(this.objectInfo.data.fields)
      .filter(v => v.createable)
      .map(v => v.apiName);
    this.editableFields = t;
    return this.editableFields;
  }
}

// editAccountForm.html
<template>
  <lightning-card>
    <h2 slot="title">Edit account</h2>

    <div class="slds-p-horizontal_small">
      <lightning-record-edit-form
        record-id={accountId}
        object-api-name="Account"
      >
        <template for:each={propertyNames} for:item="propertyName">
          <lightning-input-field
            field-name={propertyName}
            key={propertyName}
          ></lightning-input-field>
        </template>
      </lightning-record-edit-form>
    </div>
  </lightning-card>
</template>

This renders out perfectly, however as far as I can read, call expressions in the markup isn't supported, so I have to wrap it into my own component in order to process it in any way. I tried to do this in the following way.

// editAccountFormElement.js
import { LightningElement, api } from "lwc";

export default class EditAccountFormElement extends LightningElement {
  @api propertyName;
}
// editAccountFormElement.html
<template>
  <lightning-input-field field-name={propertyName}></lightning-input-field>
</template>

And the change in editAccountForm.html to instead use the new component.

// editAccountForm.html
<template>
  <lightning-card>
    <h2 slot="title">Edit account</h2>

    <div class="slds-p-horizontal_small">
      <lightning-record-edit-form
        record-id={accountId}
        object-api-name="Account"
      >
        <template for:each={propertyNames} for:item="propertyName">
          <c-edit-account-form-element
            property-name={propertyName}
            key={propertyName}
          ></c-edit-account-form-element>
        </template>
      </lightning-record-edit-form>
    </div>
  </lightning-card>
</template>

However now nothing is rendered at all. All the <lightning-input-field>'s are empty and nothing loads. Am I doing something wrong, or do the <lightning-input-field>'s have to be inside the same component that started the <lightning-record-edit-form>?

  • I think yes they are required to be in the same component To specify editable fields, use lightning-input-field components inside lightning-record-edit-form component.. I am not sure why would you need to use a child component. – manjit5190 Apr 29 at 13:28
  • @manjit5190 I need to conditionally render some extra information for the field if I have some other data that matches the field name. – Stefan Frederiksen Apr 29 at 13:31
0

There is some communication between your record-edit-form and your input-field. This communication is lost when you add an extra child in between. (regardless whether its standard or custom)

Things as simple as this.template.querySelector("lightning-input-field") will return null if record-edit-form tries to interact with the input located on the child. You can also have a look at the documentation and you'll find some methods that are even Reserved for internal use.

The following is an extract of the documentation of lightning-output-field, but I believe it applies here as well

Usage Considerations

lightning-output-field must be a child of lightning-record-view-form. You can't nest it in another component like lightning-layout though you can nest it in a <div> container within lightning-record-view-form.

| 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.