Erfassen Sie Ihre Fortschritte
Trailhead-Startseite
Trailhead-Startseite

Installieren der Beispielanwendung

Lernziele

Nachdem Sie diese Lektion abgeschlossen haben, sind Sie in der Lage, die folgenden Aufgaben auszuführen:
  • Installieren der Beispielanwendung "Record Viewer"
  • Erklären der Struktur der Record Viewer-Anwendung
  • Anzeigen eines Datensatzes in der Record Viewer-Anwendung

Installieren der Record Viewer-Anwendung

Machen wir uns an den Code! Um mehr über die User Interface API zu erfahren, installieren Sie nun die Beispielanwendung Record Viewer. Mit der Record Viewer-Anwendung können Sie Datensätze erstellen, lesen, aktualisieren und löschen. Da es sich um eine Beispielanwendung handelt, enthält sie auch eine Benutzeroberfläche, die die JSON-Antworten aus der User Interface API anzeigt. Erstellen eines Opportunity-Datensatzes in der Record Viewer-Beispielanwendung
Tipp

Tipp

Wenn Sie die praktische Aufgabe am Ende dieser Einheit absolvieren möchten, müssen Sie diese Schritte durchführen. Falls Sie keinen Trailhead Playground haben, blättern Sie nach unten bis zur Aufgabe und erstellen einen.

  1. Installieren Sie zuerst Git, falls es noch nicht installiert ist.
  2. Duplizieren Sie das Git-Repo "Record Viewer". Informationen zum Duplizieren eines Repos finden Sie unter Cloning a repository in der GitHub-Hilfe.
  3. Record Viewer wird in einem Docker-Container ausgeführt. Installieren Sie die stabile Version von Docker Engine (Community). Docker bittet Sie, einen Account zu erstellen, um die Software herunterzuladen.
  4. Starten Sie Docker.
Hinweis

Hinweis

Wählen Sie unter Windows in "Docker-Einstellungen" erst "Freigegebene Laufwerke" und dann das lokale Laufwerk, auf dem Sie Anwendung "Record Viewer" dupliziert haben.

Record Viewer ist eine verbundene Anwendung, also eine Anwendung, die über APIs mit Salesforce kommuniziert. Die Anwendung wird nicht auf der Salesforce Platform ausgeführt, ist jedoch über APIs damit verbunden. Um festzulegen, wie sich Record Viewer bei Salesforce authentifiziert, erstellen Sie in Setup eine verbundene Anwendung.

  1. Geben Sie in Ihrem Trailhead Playground in Setup den Begriff Anwendung ein und wählen Sie Anwendungs-Manager aus.
  2. Klicken Sie auf "Neue verbundene Anwendung" und geben Sie folgende Angaben ein:
    • Name der verbundenen Anwendung: RecordViewer
    • Kontakt-E-Mail: Ihre E-Mail-Adresse
  3. Wählen Sie "OAuth-Einstellungen aktivieren" aus und geben Sie folgende Einstellung ein:
    • Rückmeldungs-URL: https://localhost:8443/oauth-redirect
    • Ausgewählte OAuth-Umfänge: Zugriff auf Ihre Daten und Datenverwaltung (api)
  4. Klicken Sie auf Speichern.
  5. Klicken Sie auf der Seite "Neue verbundene Anwendung" auf Weiter.
  6. Kopieren und speichern Sie den Verbraucherschlüssel (auch OAuth-Client-ID genannt). Sie benötigen ihn später.
Damit Record Viewer von einem Webbrowser aus HTTP-Anforderungen an Salesforce stellen kann, richten Sie in Ihrem Trailhead Playground Cross-Origin Resource Sharing (CORS) ein.
  1. Geben Sie in Setup CORS ein und wählen Sie CORS aus.
  2. Klicken Sie auf Neu.
  3. Geben Sie https://localhost:8443 als Ursprungs-URL-Muster ein.
  4. Klicken Sie auf Speichern.

Um die Anwendung Record Viewer zu erstellen und den Server zu starten, verwenden Sie eine Befehlszeilenschnittstelle wie Terminal unter macOS oder Windows-Eingabeaufforderung.

Verwenden Sie zunächst den Befehl cd, um das Verzeichnis in das Verzeichnis RecordViewer zu ändern, das Sie auf Ihrem lokalen Computer dupliziert haben. Ersetzen Sie den Pfad in diesem Beispiel durch den Pfad zum Verzeichnis "RecordViewer". Wenn sich beispielsweise das Verzeichnis RecordViewer in Ihrem Mac-Benutzerverzeichnis befindet, geben Sie cd ~/RecordViewer ein.
cd /replace/with/path/to/RecordViewer

Führen Sie anschließend diese Docker-Befehle aus.

docker-compose build && docker-compose up -d
Zum Starten der Record Viewer-Anwendung öffnen Sie in einem Browser https://localhost:8443.
Hinweis

Hinweis

Die Record Viewer-Anwendung nutzt ein selbstsigniertes SSL-Zertifikat, weshalb manche Browser melden, dass Ihre Verbindung nicht privat ist. Es stellt jedoch kein Risiko dar, hier fortzufahren und die Anwendung zu laden. In Chrome klicken Sie auf Advanced (Erweitert) und dann auf Proceed to the site (Website laden). In Firefox klicken Sie auf Advanced (Erweitert) und fügen Sie eine Ausnahme hinzu. Im Internet Explorer klicken Sie auf Continue to this website (Diese Website laden). In Safari klicken Sie auf Show Details (Details anzeigen) und visit this website (diese Website besuchen).

Hinweis

Hinweis

Wenn localhost die Verbindung ablehnt, verwenden Sie stattdessen die IP-Adresse Ihres Computers, z. B. https://192.168.34.34:8443. Verwenden Sie diesen Wert auch im Ursprungs-URL-Muster von CORS.

Damit Record Viewer zu Anforderungen an Salesforce berechtigt ist, geben Sie den Anmelde-URL für Salesforce, https://login.salesforce.com, und den Verbraucherschlüssel ein, den Sie aus der verbundenen Anwendung gespeichert haben, und klicken auf "Login".Anmeldebildschirm der Record Viewer-Anwendung

Um der Record Viewer-Anwendung die Berechtigung für den Zugriff auf Ihre Salesforce-Organisation zu erteilen, prüfen Sie Ihren Benutzernamen auf Richtigkeit und klicken dann auf "Zulassen".Bildschirm 'Zugriff zulassen?'

Hinweis

Hinweis

Letztendlich wird der Benutzer bei Salesforce abgemeldet. Um der Anwendung erneut zu autorisieren, laden Sie die Anmeldeseite: https://localhost:8443/login. Geben Sie den Salesforce-Anmelde-URL https://login.salesforce.com und den Verbraucherschlüssel ein, den Sie aus der verbundenen Anwendung gespeichert haben.

Verwenden der Record Viewer-Anwendung

Verwenden Sie Record Viewer, um Salesforce-Datensätze anzuzeigen, zu bearbeiten, zu erstellen und zu löschen. Record Viewer nutzt die User Interface API für die Durchführung dieser Vorgänge für Salesforce-Datensätze. Die App bietet auch eine praktische Möglichkeit, die JSON-Antwort der User Interface API zu betrachten.

Bevor wir uns einen Datensatz in Record Viewer ansehen, lassen Sie uns einen Datensatz in Salesforce ansehen, damit wir vergleichen können.
  1. Öffnen Sie in einem Browser die Salesforce-Organisation, mit der Sie die verbundene RecordViewer-Anwendung erstellt haben.
  2. Klicken Sie auf Accounts und anschließend auf Neu.
  3. Geben Sie als Accountname Universal Containers ein.
  4. Geben Sie als Telefonnummer 206 555 1212 ein und klicken Sie auf Speichern.
  5. Klicken Sie auf "Details", um die Datensatz-Detailseite des neuen Datensatzes anzuzeigen.
Account-Datensatzdetails in Lightning Experience
Sehen wir uns denselben Datensatz jetzt in der Record Viewer-Anwendung an.
  1. Öffnen Sie in einem Browser die Seite https://localhost:8443.
  2. Klicken Sie unter "Zuletzt verwendete Elemente" auf Universal Containers.
    Hinweis

    Hinweis

    Falls "Universal Containers" nicht angezeigt werden, aktualisieren Sie die Seite.

Die Record Viewer-Anwendung zeigt die Datensatz-Detailseite.Account-Datensatzdetails in der Record Viewer-Anwendung

Wir haben über die Vorzüge der UI API gesprochen, die darin bestehen, dass ihre Antworten die in der Salesforce-Organisation vorgenommenen Metadatenänderungen berücksichtigen. Lassen Sie uns also ein Feld aus dem Accountlayout in der Salesforce-Organisation entfernen und sehen, was in Record Viewer passiert.

"Universal Containers" enthält eine Telefonnummer, die Datensatz-Detailseite enthält aber auch ein Feld "Fax". Da heute keiner mehr ein Faxgerät verwendet, entfernen wir dieses Feld jetzt aus dem Seitenlayout.

  1. Geben Sie in Ihrem Trailhead Playground in Setup den Begriff Objekt ein und wählen Sie Objekt-Manager aus.
  2. Klicken Sie auf Account | Seitenlayouts | Accountlayout.
  3. Klicken Sie im Seitenlayout-Editor auf das Symbol "Entfernen", um das Feld "Fax" zu entfernen, und klicken Sie dann auf Speichern.

Seitenlayout-Editor mit ausgewählten Feld 'Fax'

Kehren Sie nun zur Record Viewer-Anwendung zurück und klicken Sie auf View Record, um den Universal Containers-Datensatz neu zu laden. Voilà! Das Feld "Fax" ist verschwunden, und Sie haben nicht eine Codezeile geändert.Account-Datensatzdetails in der Record Viewer-Anwendung ohne das Feld 'Fax'

In diesem Fall wurde das Feld aus dem Layout entfernt. In der Praxis muss der Administrator Sie nicht informieren, wenn das Layout geändert wird – Ihre Anwendung passt sich dann einfach an!

Struktur der Record Viewer-Anwendung

Um mit der User Interface API zu arbeiten, können Sie jedes Web-Framework oder jede Sprache verwenden, mit denen HTTP-Anforderungen möglich sind. Polymer, React, Angular, Vue, iOS, Android – verwenden Sie die Technologie Ihrer Wahl.

Die Record Viewer-Anwendung ist eine Einzelseitenanwendung, die mit React, Redux und Redux-Saga erstellt wurde. Wir werden schnell die Grundlagen dieser Technologien erläutern, wenn wir uns die Dateistruktur der Anwendung anschauen. Falls Sie nicht mit React und Redux vertraut sind, ist das völlig in Ordnung. Wir möchten Ihnen lediglich die Grundkonzepte erläutern.

Ihr Ziel ist es zu lernen, wie Sie auf User Interface API-Ressourcen zugreifen und die Antworten verarbeiten. Bei jedem Framework und jeder Sprache werden diese Aufgaben etwas anders durchgeführt, aber die Kernkonzepte sind die gleichen und die API verhält sich gleich.

Die Record Viewer-Anwendung wurde erstellt mit:

  • Pug: generiert HTML-Seiten aus serverseitigen Vorlagen
  • React: Eine JavaScript-Bibliothek, mit der Sie benutzerdefinierte Komponenten erstellen und kombinieren können, um Benutzeroberflächen auszugeben
  • Redux: speichert den Zustand einer React-Anwendung in einem so genannten Store, einem einzelnen, unveränderlichen JavaScript-Objekt. React-Komponenten entsenden JavaScript-Objekte namens Aktionen, die von Reducern abgefangen werden. Reducer sind JavaScript-Funktionen, die Aktionen als Eingabe verwenden, um den Redux-Zustand zu aktualisieren.
  • Redux-Saga: Wie Reducer sind Sagas JavaScript-Funktionen, die ausgeführt werden, wenn sie eine Aktion abfangen. Sagas verwalten asynchrone Anforderungen an die User Interface API. Am Ende eines asynchronen Vorgangs entsenden Sagas eine Aktion, die von einem Reducer abgefangen werden kann, der den Store aktualisiert. Sagas verhindern ein Wirrwarr aus Rückrufen.
  • Node.js: eine serverseitige Laufzeitumgebung für JavaScript-Anwendungen

Sehen wir uns diese abstrakten Konzepte in der Praxis an. Starten Sie Ihre bevorzugte IDE und öffnen Sie den Ordner RecordViewer, den Sie aus GitHub geklont haben. Dateistruktur der Record Viewer-Anwendung in VS Code. Die Struktur enthält die Ordner 'actions', 'components', 'containers', 'helpers', 'reducers' und 'sagas'.

Sehen wir uns zunächst den Ordner views an, der die HTML-Vorlagen von Pug enthält. Die Anwendung enthält drei Ansichten: die Anmeldeseite, auf der Sie die Salesforce-Anmeldeinformationen eingegeben haben, die Datensatzansicht, die den Haupt-Container der Anwendung darstellt, und eine Fehlerseite, die Sie hoffentlich noch nicht zu Gesicht bekommen haben. Die vierte Pug-Vorlage ist eine OAuth-Authentifizierungsumleitung.

Bei erfolgreicher Authentifizierung wird die Vorlage recordView.pug geladen und ruft das in der Datei "root.js" definierte renderRoot auf. Ab diesem Zeitpunkt führt die Record Viewer-Anwendung clientseitigen, in diese einzelne Webseite geladenen Code aus.
<!-- /views/recordView.pug -->

doctype html
html
  block head
    title Record Viewer
    // Metadata and style sheet links removed to keep sample short

    script(type='text/javascript', src='https://code.jquery.com/jquery-2.0.3.min.js')
    script(type='text/javascript', src='root.js')

  body
    .slds-grid.slds-wrap
      nav.slds-col.slds-size--1-of-1
        .slds-page-header
          p.slds-page-header__title.slds-truncate.slds-align-middle
            a(href='/recordView') Record Viewer
          p.slds-page-header__info powered by User Interface API
    #root
    script.
      $( document ).ready(function() {
        let rootNode = document.getElementById("root");
        renderRoot("#{targetUrl}", "#{accessToken}", "#{recordId}", rootNode);
      });
Die Datei "/client-src/root.js" lädt die Anwendung. Sie verbindet die Root-Komponente RecordViewerWrapper mit der Root der Redux Zustands-Reducer und der Saga-Middleware. Zur Erinnerung: Reducer aktualisieren den Zustand, und Sagas senden Anforderungen an die User Interface API und senden Aktionen mit den Ergebnissen.
/* Excerpt from /client-src/root.js */

// Root renderer for record viewer.
global.renderRoot = function(instanceUrl, accessToken, recordId, rootNode) {
  const sagaMiddleware = createSagaMiddleware()
  const store = createStore(rootReducer, {login:{instanceUrl, accessToken}, record:{recordId}}, applyMiddleware(sagaMiddleware));
  sagaMiddleware.run(rootSaga);

  ReactDOM.render(
    <Provider store={store}>
      <div>
        <RecordViewerWrapper />
      </div>
    </Provider>,
    rootNode);
}
Die React-Komponente RecordViewerWrapper.js befindet sich im Ordner containers. Diese Komponente ist eine verbundene Komponente auf oberster Ebene, die die RecordViewer-Komponente einkapselt. Die Funktion mapStateToProps gibt an, wie der Redux-Zustand an Eigenschaften von RecordViewer gebunden wird.
/* Excerpt from /client-src/containers/RecordViewerWrapper.js */

// Presentational Component that uses state to decide how to
// construct the RecordViewer.
const mapStateToProps = (state) => {
  if (state.record.record) {
    return {
      screen: 'RECORD',
      record: state.record.record,
      headerRecordId: state.header.recordId,
      mode: state.record.mode,
      context: state.context,
      prevMode: state.record.prevMode,
      creds: state.login,
      picklists : state.picklists,
      depGraph: state.depGraph,
      rawjson: state.rawjson,
      error: state.error
    }
  } else if (state.record.recordId) {
    return {
      screen: 'FETCH_RECORD',
      recordId: state.record.recordId,
      mode: 'View',
      context: state.context,
      creds: state.login,
      rawjson: state.rawjson,
      error: state.error
    }
  }
 
  // Additional mappings removed to shorten sample
RecordViewWrapper enthält zudem eine mapDispatchToProps-Funktion, die Redux-Aktionen an React-Eigenschaften binden, sodass React-Komponenten Aktionen in Reaktion auf verschiedene Ereignisse senden können. Wissen Sie noch, was Aktionen sind? Sie dienen als Eingaben für Reducer, also den Funktionen, die den Zustand der Anwendung ändern.
/* Excerpt from /client-src/containers/RecordViewerWrapper.js */

const mapDispatchToProps = (dispatch) => {
  return {
    onFetchRecord: (creds, id, context) => {
      dispatch(actions.fetchRecord(creds, id, context))
    },
    onRecordClick: (creds, id, context) => {
      dispatch(actions.fetchRecord(creds, id, context))
    },
    onViewRecordClick: (creds, id, context) => {
      dispatch(actions.fetchRecord(creds, id, context))
    },
    onFormFactorSelect: (formFactor, recordId) => {
      dispatch(actions.updateFormFactor(formFactor, recordId))
    },

   // Additional mappings removed to shorten sample
Die connect()-Methode verbindet schließlich diese beiden Zuordnungen mit der einfachen RecordViewer-Komponente.
/* Excerpt from /client-src/containers/RecordViewerWrapper.js */

const RecordViewerWrapper = connect(
  mapStateToProps,
  mapDispatchToProps
) (RecordViewer)

export default RecordViewerWrapper

Die Aktionen, Reducer und Sagas befinden sich in den Ordnern actions, reducers und sagas.

Eine Aktion ist ein einfaches Objekt, das eine type-Eigenschaften aufweisen muss und andere Eigenschaften haben kann. Die type-Eigenschaft identifiziert die Aktion. Alle Aktionen sind in der Datei "/actions/index.js" definiert.
/* Excerpt from /client-src/actions/index.js */

export const fetchEntities = (creds) => {
  return {
    type: 'FETCH_ENTITIES',
    creds
  }
}

export const receiveEntities = (entities) => {
  return {
    type: 'RECEIVE_ENTITIES',
    entities,
    receivedAt: Date.now()
  }
}
Folgen wir dem "Happy Path", also der Basisfunktionalität der Aktion fetchEntities. Die Datei "rootSaga.js" registriert alle Sagas in der Record Viewer-Anwendung. Wenn eine Aktion an den Store gesendet wird und ihre type-Eigenschaft mit einer Zeichenfolge in einer takeEvery-Funktion übereinstimmt, löst die Funktion die zugehörige Saga aus. Der Aktionstyp FETCH_ENTITIES löst die Saga entitiesFetcher aus.
/* /client-src/sagas/rootSaga.js */

import { takeEvery } from 'redux-saga'

import recentItemsFetcher from './recentItemsFetcher'
import recordFetcher from './recordFetcher'
import recordDeleter from './recordDeleter'
import recordUpdater from './recordUpdater'
import entitiesFetcher from './entitiesFetcher'
import recordCreator from './recordCreator'
import cloneDefaultsFetcher from './cloneDefaultsFetcher'
import createDefaultsFetcher from './createDefaultsFetcher'
import picklistsFetcher from './picklistsFetcher'
import depGraphValueUpdater from './depGraphValueUpdater'

export default function* rootSaga() {
  yield takeEvery('FETCH_RECORD', recordFetcher)
  yield takeEvery('FETCH_RECENT_ITEMS', recentItemsFetcher)
  yield takeEvery('DELETE_RECORD', recordDeleter)
  yield takeEvery('SAVE_RECORD', recordUpdater)
  yield takeEvery('FETCH_ENTITIES', entitiesFetcher)
  yield takeEvery('CREATE_RECORD', recordCreator)
  yield takeEvery('FETCH_CREATE_DEFAULTS', createDefaultsFetcher);
  yield takeEvery('FETCH_CLONE_DEFAULTS', cloneDefaultsFetcher);
  yield takeEvery('FETCH_PICKLISTS', picklistsFetcher);
  yield takeEvery('UPDATE_DEP_GRAPH_FIELD_VALUE', depGraphValueUpdater)
}
Die Saga "entitiesFetcher.js" erzeugt eine Anforderung an User Interface API, um eine Liste der Objekte abzurufen, die die API unterstützt. Die UI API-Ressource ist /ui-api/object-info. In einer späteren Einheit wird erläutert, wie der vollständige URL gebildet wird. Wenn Sie mit Salesforce REST-APIs vertraut sind, wissen Sie dies bereits, da das Muster immer dasselbe ist. Und wie andere Salesforce REST-APIs, verwendet die User Interface API ebenfalls OAuth 2.0. Das Bearer-Token wird in der Authorization-Kopfzeile weitergegeben. Wir stellen die Kopfzeile X-Chatter-Entity-Encoding auf false ein, damit die Antwort nicht verschlüsselt wird.
/* /client-src/sagas/entitiesFetcher.js */

import { call, put } from 'redux-saga/effects'

import { receiveEntities } from '../actions'

export default function* entitiesFetcher(action) {

  let mruUrl = action.creds.instanceUrl + '/services/data/v48.0/ui-api/object-info'

  let req = {
    method: 'GET',
    headers: {
      'Authorization' : 'Bearer ' + action.creds.accessToken,
      'X-Chatter-Entity-Encoding': false}
    }

  try {
    const response = yield call(fetch, mruUrl, req)
    const responseJson = yield response.json()
    yield put(receiveEntities(responseJson))
  } catch(err) {
    console.error('Describe sobjects error: ' + JSON.stringify(err))
  }
}
Sehen Sie die Zeile yield put(receiveEntities(responseJson))? Suchen Sie nach receiveEntities im vorherigen Codebeispiel aus "/actions/index.js". Sehen Sie die Aktion receiveEntities? Gut. Wenn der UI API-Vorgang erfolgreich ist, sendet die Saga die Aktion receiveEntities, die die JSON-Antwort enthält. Der Reducer "entities.js" fängt die Aktion ab und verwendet sie als Eingabe, um den Redux-Zustand zu aktualisieren.
/* /client-src/reducers/entities.js */

const entities = (state = {sobjects: []}, action) => {
  switch (action.type) {
    case 'RECEIVE_ENTITIES':
      return {
        sobjects: action.entities.objects,
        receivedAt: action.receivedAt
      }
    default:
      return state
  }
}

export default entities

Der Reducer aktualisiert einen Teil des Redux-Zustands. Nach der Änderung werden die React-Komponenten, die dieses Teil des Anwendungszustands abonnieren, automatisch aktualisiert.

In der Record Viewer-Anwendung befinden sich React-Komponenten, die HTML live erstellen, im Ordner components. Diese Komponenten definieren die Teile der Benutzeroberfläche der Anwendung. Die Komponente "CreateableEntitiesList.js" definiert UI, die ein Menü in der Record Viewer-Anwendung anzeigt. Das Menü enthält die Liste der unterstützten Objekte, die beim Aufruf von /ui-api/object-info zurückgegeben wurde. Die RecordViewer-Anwendung empfängt die Entitäten und zeigt sie in der CreateableEntitiesList-Komponente an.Popup-Menü 'Create New Record' mit einer Liste zu erstellender Objekte
Tipp

Tipp

Im RecordViewer-Code wird häufig der Begriff entities (Entitäten) verwenden, der Objekte bedeutet. Bezeichnungen wie CreateableEntitiesList sind also gleichbedeutend mit "list of creatable objects", also einer Liste erstellbarer Objekte. Anders ausgedrückt: Sie können einen Datensatz aus jedem der Objekte in dieser Liste erstellen! Diese Objekte werden von der User Interface API unterstützt.

In React erstellen Sie Komponenten, um eine Benutzeroberfläche zu erzeugen, was bedeutet, dass übergeordnete Komponenten aus verschachtelten untergeordneten Komponenten zusammengesetzt sein können. Bei der Anwendungsentwicklung teilen Sie die Funktionalität in einfache Komponenten auf und kombinieren diese zu komplexeren Komponenten.

Wenn Sie sich die Komponentennamen im Ordner components ansehen, wird klar, dass sich bei der Record Viewer-Anwendung alles um die Arbeit mit Datensätzen dreht: Record.js, RecordButton.js, RecordSection.js. Im Komponentencode können Sie die verschachtelten untergeordneten Komponenten erkennen. Die Komponente RecordSection enthält beispielsweise verschachtelte RecordRow-Komponenten.
/* Excerpt from /client-src/components/RecordSection.js */

// Component that displays a Record section.
const RecordSection = ({section, error, editValues, picklists, onFieldValueUpdate, allowEdit, index, objectInfo, onEditDepGraph, uiMode, recordView}) => {

  return (
    <tbody>
      { section.useHeading &&
       <tr>
         <td colSpan="4" key={'sectionHeading' + index} className="slds-text-heading--small slds-p-left--medium slds-p-top--small slds-p-bottom--medium">
           {section.heading}
         </td>
       </tr>
      }
      {section.rows.map((row, i) =>
        <RecordRow
          key={'sectionRow' + index + ',' + i}
          allowEdit={allowEdit}
          uiMode={uiMode}
          picklists={picklists}
          onFieldValueUpdate={onFieldValueUpdate}
          error={error}
          editValues={editValues}
          row={row}
          sectionIndex={index}
          rowIndex={i} 
          objectInfo={objectInfo}
          recordView={recordView}
          onEditDepGraph={onEditDepGraph}/>
      )}
   </tbody>
  );
}
Wechseln Sie nun zu Ihrer IDE und sehen Sie sich die Record-Komponente (Record.js) an. Sie enthält eine <RecordSection>- und eine <DepGraphEditor>-Komponente sowie mehrere <RecordButton>-Komponenten.

Kommen wir zu guter Letzt zum Ordner helpers, der einige JavaScript-Hilfsfunktionen enthält. Diese Funktionen transformieren die Antworten der User Interface API in Datenmodelle, die die Benutzeroberfläche der Record Viewer-Anwendung unterstützen. Der Code in "recordLayout.js" erstellt das interne Datenmodell für Layouts und der Code in "depGraphHelper.js" den Editor für abhängige Auswahllisten. Diese Dateien sehen wir uns später noch genauer an.