1

I'm creating a set of components to override the standard view and edit actions on an object. I've explored using <lighting-record-form> and <lightning-record-view-form>/<lightning-record-edit-form> and while these provide great UI they do not have the level of customization I will need for my components and they have the limitation of not being able to grab spanning fields from related objects.

This leaves me with either creating custom apex methods to grab my data or use the getRecord method in the lightning/uiRecordApi module.

The problem I am having with the above is that the layout has to be custom made using slds-grid or <lightning-layout>.

This is fine but there isn't much documentation on how to make these mimic the standard layout style you get using <lighting-record-form> or <lightning-record-view-form> and it doesn't adhere to the user's cozy/compact setting

Has anyone successfully used lightning data service and mimicked the UI or am I missing something in the documentation with getRecord?

  • 1
    There a lot stuff under the hood of standard lightning-records components you should replicate, like: supporting record types and dependent picklists etc. I mean, it's possible, but it is really time-consuming process to develop such component from scratch. And UI probably would be the least of the problem. – BlackCat Aug 6 '19 at 22:15
  • 1
    Maybe it would be easier to find some workaround. By the way, what do you mean 'not being able to grab spanning fields from related objects'? – BlackCat Aug 6 '19 at 22:16
  • @BlackCat spanning fields are fields from a related object. For example this component will be used for assets and I would like to display account fields related to the asset. This isn't possible with those record form components – TemporaryFix Aug 7 '19 at 14:09
1

Below just proof of concept how you can use standard <lightning-record-view-form>&<lightning-record-edit-form> to fit your requirements.

Demo of Contact Detail Screen with related Account Information

HTML

<template>
    <lightning-record-edit-form record-id={recordId}
                                object-api-name="Contact">
        <div class="slds-grid">
            <div class="slds-col slds-size_1-of-2">
                <lightning-card title="Contact Information">
                    <lightning-input-field field-name="FirstName"></lightning-input-field>
                    <lightning-input-field field-name="LastName"></lightning-input-field>
                    <lightning-input-field field-name="Email"></lightning-input-field>
                </lightning-card>
            </div>
            <div class="slds-col slds-size_1-of-2">
                <lightning-card title="Related Account Information">
                    <lightning-record-view-form
                            record-id={accountId}
                            object-api-name="Account">
                        <lightning-output-field field-name="Name"></lightning-output-field>
                        <lightning-output-field field-name="Phone"></lightning-output-field>
                        <lightning-output-field field-name="Website"></lightning-output-field>
                    </lightning-record-view-form>
                </lightning-card>
            </div>
        </div>
    </lightning-record-edit-form>
</template>

JS

import { LightningElement, track, api, wire } from 'lwc';
import { getRecord } from 'lightning/uiRecordApi';

const FIELDS = [
    'Contact.AccountId'
];

export default class Tst2 extends LightningElement {
    @api recordId;
    @track record;

    @wire(getRecord, { recordId: '$recordId', fields: FIELDS })
    wiredContact({error, data}) {
        if(data) {
            this.record = data;
        } else if (error) {
            alert(error);
        }
    }

    get accountId() {
        return this.record ? this.record.fields.AccountId.value : null;
    }
}

Metadata

<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>46.0</apiVersion>
    <description>Tst 2</description>
    <isExposed>true</isExposed>
    <masterLabel>Tst 2</masterLabel>
    <targets>
        <target>lightning__RecordPage</target>
    </targets>
    <targetConfigs>
        <targetConfig targets="lightning__RecordPage">
            <objects>
                <object>Contact</object>
            </objects>
        </targetConfig>
    </targetConfigs>
</LightningComponentBundle>

Result LWC custom component result


How to deal with custom UI?

Here I see two option:

Option 1: Use only SLDS CSS classes for standard components. Because, custom wouldn't apply due to LWC Shadow Dom.

Option 2: Use workaround for overriding standard components styling, which I described here.

| improve this answer | |
  • 1
    This is awesome work you've put together here. But it still falls short of the customization level needed. You can't interlace Contact and Account fields on the same lightning-record-view-form. This will be helpful for people in the future with less strict requirements. – TemporaryFix Aug 7 '19 at 17:50
  • @Programmatic, I've added new answer. There you can edit both records at the same time. – BlackCat Aug 7 '19 at 19:14
0

Looks like you'll have to roll your own layout using Lightning Design System

| improve this answer | |
0

Just, another proof of concept. Here you can edit Contact and Account on the same page.

HTML

<template>
    <div class="slds-grid">
        <div class="slds-col slds-size_1-of-2">
            <lightning-card title="Contact Information">
                <lightning-record-edit-form record-id={recordId}
                                            class="con-edit-form"
                                            object-api-name="Contact">
                    <lightning-input-field field-name="FirstName"></lightning-input-field>
                    <lightning-input-field field-name="LastName"></lightning-input-field>
                    <lightning-input-field field-name="Email"></lightning-input-field>
                    <lightning-input-field field-name="AccountId" onchange={handleAccountChange}></lightning-input-field>
                </lightning-record-edit-form>
            </lightning-card>
        </div>
        <div class="slds-col slds-size_1-of-2">
            <lightning-card title="Related Account Information">
                <div if:true={renderAccForm}>
                    <lightning-record-edit-form record-id={accountId}
                                                class="acc-edit-form"
                                                object-api-name="Account">
                        <lightning-input-field field-name="Name"></lightning-input-field>
                        <lightning-input-field field-name="Phone"></lightning-input-field>
                        <lightning-input-field field-name="Website"></lightning-input-field>
                    </lightning-record-edit-form>
                </div>
            </lightning-card>
        </div>
    </div>
    <lightning-button label="Save" class="slds-align_absolute-center" onclick={handleSave} variant="brand"></lightning-button>
</template>

JS

import { LightningElement, track, api, wire } from 'lwc';
import { getRecord } from 'lightning/uiRecordApi';

const FIELDS = [
    'Contact.AccountId'
];

export default class Tst2 extends LightningElement {
    @api recordId;
    @track accId;
    @track renderAccForm = true;

    @wire(getRecord, { recordId: '$recordId', fields: FIELDS })
    wiredContact({error, data}) {
        if(data) {
            this.accId = data.fields.AccountId.value;
        } else if (error) {
            alert(error);
        }
    }

    get accountId() {
        return this.accId ? this.accId : null;
    }

    set accountId(value) {
        this.accId = value;
    }

    handleAccountChange(event) {
        this.renderAccForm = event.detail.value.length ? true : false;
        this.accountId = event.detail.value.length ? event.detail.value[0] : null;
    }

    handleSave() {
        Promise.all([
            this.template.querySelector('.con-edit-form').submit(),
            this.template.querySelector('.acc-edit-form').submit()
        ]).then(() => {
            //handle success
            alert('Success!');
        }).catch(error => {
            //handle error
            alert(error);
        });
    }
}

Result Working example

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