Регистрация  |  Вход

Как добавить данные из apex controllera на html страницу lwc

есть апекс контроллер в котором я достаю данные с junction object opportunity contact role по id opportunity

public with sharing class OpportunityDataHandler {
@AuraEnabled(cacheable = true)
public static List<OpportunityContactRole> getOpportunityContactRoles(String oppId){
return [
SELECT
ContactId,
CreatedById,
LastModifiedById,
OpportunityId,
isPrimary,
Role
FROM OpportunityContactRole
WHERE OpportunityId =: oppId
];
}
}


Есть js файл в который я импортирую метод с контроллера и пару полей для junction object, помечаю api айдишник opportunity, при помощи wire достаю данные из организации и геттерами их получаю

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

import INVOICE_NUMBER from '@salesforce/schema/Opportunity.Invoice_Number__c';
import getOpportunityContactRoles from '@salesforce/apex/OpportunityDataHandler.getOpportunityContactRoles';
import FNAME_FIELD from '@salesforce/schema/OpportunityContactRole.Contact.FirstName';
import EMAIL_FIELD from '@salesforce/schema/OpportunityContactRole.Contact.Email';



const fields = [INVOICE_NUMBER];

const fie = [FNAME_FIELD, EMAIL_FIELD];


export default class SendInvoice extends LightningElement {
@api recordId;

@wire(getRecord, {recordId: '$recordId', fields}) opportunity;
@wire(getOpportunityContactRoles, {oppId: '$recordId', fie}) opportunityContactRoles;

get invoice(){
return getFieldValue(this.opportunity.data, INVOICE_NUMBER);
}

get name(){
return getFieldValue(this.opportunityContactRoles.data, FNAME_FIELD);
}

get email(){
return getFieldValue(this.opportunityContactRoles.data, EMAIL_FIELD);
}

}


и есть html страница, которая представляет собой форму из 4 инпутов, где 3 из них идут сразу заполненными (Email - значение invoice, Recipient Name - значение name и Recipient Email значение email), а 1 нет.

<!-- sldsValidatorIgnore -->
<template>
<lightning-quick-action-panel header="Send Invoice" record-id={recordId}>
<div class="slds-p-around_large">
<lightning-input readonly type="text" variant="standard" label="Email " value={invoice}></lightning-input>
<lightning-input readonly type="text" variant="standard" label="Recipient Name" value={name} ></lightning-input>
<lightning-input readonly type="text" variant="standard" label="Recipient Email" value={email}></lightning-input>
<lightning-input type="text" variant="standard" label="Email Body" ></lightning-input>
</div>
<div slot="footer">
<lightning-button variant="destructive" label="Cancel" onclick={closeAction} ></lightning-button>
&nbsp; &nbsp;
<lightning-button variant="brand" label="Send" onclick={handleSend} ></lightning-button>
</div>
</lightning-quick-action-panel>
</template>

Вопрос заключается в том, что в этих трех инпутах отображается корректно только первый (invoice), который мы получили в js файле при помощи импорта с объекта Opportunity, а остальные 2 (name и email), которые мы получаем с контроллера не отображаются, я не понимаю что я сделал не так - почему не отображаются данные с apex контроллера. Возможна проблема заключается со вторым wire (в который я передал этот самый метод контроллера)?
есть апекс контроллер в котором я достаю данные с junction object opportunity contact role по id opportunity

public with sharing class OpportunityDataHandler {
    @AuraEnabled(cacheable = true)
        public static List<OpportunityContactRole> getOpportunityContactRoles(String oppId){
            return [
                SELECT
                    ContactId,
                    CreatedById,
                    LastModifiedById,
                    OpportunityId,
                    isPrimary,
                    Role
                FROM OpportunityContactRole
                WHERE OpportunityId =: oppId
            ];
	}
}


Есть js файл в который я импортирую метод с контроллера и пару полей для junction object, помечаю api айдишник opportunity, при помощи wire достаю данные из организации и геттерами их получаю 

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

import INVOICE_NUMBER from '@salesforce/schema/Opportunity.Invoice_Number__c';
import getOpportunityContactRoles from '@salesforce/apex/OpportunityDataHandler.getOpportunityContactRoles';
import FNAME_FIELD from '@salesforce/schema/OpportunityContactRole.Contact.FirstName';
import EMAIL_FIELD from '@salesforce/schema/OpportunityContactRole.Contact.Email';



const fields = [INVOICE_NUMBER];

const fie = [FNAME_FIELD, EMAIL_FIELD];


export default class SendInvoice extends LightningElement {
    @api recordId;

    @wire(getRecord, {recordId: '$recordId', fields}) opportunity;
    @wire(getOpportunityContactRoles, {oppId: '$recordId', fie}) opportunityContactRoles;

    get invoice(){
        return getFieldValue(this.opportunity.data, INVOICE_NUMBER);
    }

    get name(){
        return getFieldValue(this.opportunityContactRoles.data, FNAME_FIELD);
    }

    get email(){
        return getFieldValue(this.opportunityContactRoles.data, EMAIL_FIELD);
    }
 
}


и есть html страница, которая представляет собой форму из 4 инпутов, где 3 из них идут сразу заполненными (Email - значение invoice, Recipient Name - значение name и Recipient Email значение email), а 1 нет.

<!-- sldsValidatorIgnore -->
<template>
    <lightning-quick-action-panel header="Send Invoice" record-id={recordId}>
        <div class="slds-p-around_large">
            <lightning-input readonly type="text" variant="standard" label="Email " value={invoice}></lightning-input>
                <lightning-input readonly type="text" variant="standard" label="Recipient Name" value={name} ></lightning-input>
                <lightning-input readonly type="text" variant="standard" label="Recipient Email" value={email}></lightning-input>
            <lightning-input type="text" variant="standard" label="Email Body" ></lightning-input>
        </div>
        <div slot="footer">
            <lightning-button variant="destructive" label="Cancel" onclick={closeAction} ></lightning-button>
            &nbsp; &nbsp;
            <lightning-button variant="brand" label="Send" onclick={handleSend} ></lightning-button>
        </div>
    </lightning-quick-action-panel>
</template>

Вопрос заключается в том, что в этих трех инпутах отображается корректно только первый (invoice), который мы получили в js файле при помощи импорта с объекта Opportunity, а остальные 2 (name и email), которые мы получаем с контроллера не отображаются, я не понимаю что я сделал не так - почему не отображаются данные с apex контроллера. Возможна проблема заключается со вторым wire (в который я передал этот самый метод контроллера)?
Насколько я вижу по коду - opportunityContactRoles это List. Чтобы получить поля записи, надо эту запись из List достать. Попробуй поиграться с индексами что-то типа такого.
this.opportunityContactRoles.data[0]

Но вообще совет. Не используй wire. Это хрень добавляет кучу сложностей. Так как и не используй getFieldValue и @salesforce/schema

проще сделать такой метод

async connectedCallback() {
    this.opportunityContactRoles = await getOpportunityContactRoles(searchPayload);
    this.firstOpportunityContactRole = this.opportunityContactRoles[0];
}

а на странице просто сделать так:

<lightning-input readonly type="text" variant="standard" label="Recipient Name" value={firstOpportunityContactRole.Contact.FirstName} ></lightning-input>
<lightning-input readonly type="text" variant="standard" label="Recipient Email" value={firstOpportunityContactRole.Contact.Email}></lightning-input>

только в сам SELECT в контроллере надо добавить поля

Contact.FirstName
Contact.Email

Но вообще если делать красиво, то нужно сделать какой DTO класс со всеми нужными полями. Собраться все данные в Apeх контроллере, и уже работать с этим DTO. Но не уверен что Salesforce документация освящает этот момент.
Насколько я вижу по коду - opportunityContactRoles это List. Чтобы получить поля записи, надо эту запись из List достать. Попробуй поиграться с индексами что-то типа такого.
this.opportunityContactRoles.data[0]

Но вообще совет. Не используй [b]wire[/b]. Это хрень добавляет кучу сложностей. Так как и не используй [b]getFieldValue[/b] и [b]@salesforce/schema[/b]

проще сделать такой метод

[code]async connectedCallback() {
    this.opportunityContactRoles = await getOpportunityContactRoles(searchPayload);
    this.firstOpportunityContactRole = this.opportunityContactRoles[0];
}[/code]

а на странице просто сделать так:

[code]<lightning-input readonly type="text" variant="standard" label="Recipient Name" value={firstOpportunityContactRole.Contact.FirstName} ></lightning-input>
<lightning-input readonly type="text" variant="standard" label="Recipient Email" value={firstOpportunityContactRole.Contact.Email}></lightning-input>[/code]

только в сам SELECT в контроллере надо добавить поля

[code]Contact.FirstName
Contact.Email[/code]

Но вообще если делать красиво, то нужно сделать какой DTO класс со всеми нужными полями. Собраться все данные в Apeх контроллере, и уже работать с этим DTO. Но не уверен что Salesforce документация освящает этот момент.
Насколько я понимаю из вопросов, тут проблема скорее НЕ в незнании Salesforce, сколько в незнании Javascript.
А из всего LWC backend надо знать и понимать только вот это
https://developer.salesforce.com/docs/co ... perative
остальная работать простой чистый JS.
Насколько я понимаю из вопросов, тут проблема скорее НЕ в незнании Salesforce, сколько в незнании Javascript. 
А из всего [b]LWC backend[/b] надо знать и понимать только вот это
https://developer.salesforce.com/docs/component-library/documentation/en/lwc/lwc.apex_call_imperative
остальная работать простой чистый JS.