Immer wieder ist es gefordert in klassischen Fiori List Reports Dokumente (oft PDFs) anzuzeigen. Über OData v4 ist dies auch nicht wirklich schwer umzusetzen, da es die Möglichkeit gibt Felder über Edm.Stream zu deklarieren. Über den Stream Support zeigt Fiori Elements die Dateien dann entweder als Link oder Vorschau an. Ist man aber noch auf einem 7.40 Release unterwegs bzw. hat man da schon mit anderen Herausforderungen zu kämpfen.
- OData-Service selbst implementieren (natürlich v2)
- Fiori-Elements Custom Action implementieren um den PDF-Absprung zu ermöglichen
OData-Service implementieren
Klassisch über SEGW in meinem Fall eine eigene Entität z.B. Document mit den entsprechenden Schlüsselfeldern die für die Anzeige des Dokuments wichtig sind. Zudem ein Feld ContentType, welches den Typ der Datei definiert.
Der Content Typ wird dann über eine Redefinition der Methode define in der mpc_ext-Implementierung als solcher definiert.
super->define( ).
DATA(lo_entity_type) = model->get_entity_type( iv_entity_name = 'Document' ) ).
IF lo_entity_type IS BOUND.
DATA(lo_property) = lo_entity_type->get_property( iv_property_name = 'ContentType' ).
lo_property->set_as_content_type( ).
ENDIF.
Um sich den Inhalt des angeforderten PDFs zu holen muss in der dpc_ext-Implementierung die Methode get_stream des Interfaces /iwbep/if_mgw_appl_srv_runtime redefiniert werden. Dort wird dann die Logik des PDF-Inhaltes ermittelt und als xString zurückgegeben. Geht natürlich auch für andere MIME-Typen. Wichtig am Ende ist der Header-Hinweis content-disposition mit dem Wert inline, damit das PDF embedded angezeigt werden kann und nicht heruntergeladen wird.
DATA ls_stream TYPE ty_s_media_resource.
DATA lv_pdf_content TYPE xstring.
"Logik zur Ermittlung PDF-Inhalt
ls_stream-value = lv_pdf_content.
ls_stream-mime_type = 'application/pdf'.
copy_data_to_ref( EXPORTING is_data = ls_stream
CHANGING cr_data = er_stream ).
set_header( is_header = VALUE #( name = 'Content-Disposition' value = 'inline; filename=' && |Test.pdf| ) ).
Fiori-Elements Custom Action implementieren
Geht einfach über VSCode und das Guided Development.
Der Guide ist auch relativ einfach im Endeffekt wird die Seite (List Report oder Object Page) ausgewählt, Text und Position des Buttons festgelegt und der Name für die zu rufenden Funktion in der Controller Extension definiert.
Am Ende des Ganzen hat man seine eigene Custom Action zur Ausprogrammierung zur Verfügung (ListReportExt.controller.js).
Darin kann man jetzt den PDF-Aufruf über das PDF Viewer-Control implementieren.
customDocument: function(oEvent) {
var item = oEvent.getSource().getParent().getParent().getSelectedItem();
var path = item.getBindingContext().getPath();
var model = oEvent.getSource().getParent().getParent().getModel();
var obj = model.getProperty(path);
var keyfield1 = obj.Keyfield1; //Selektiertes Schlüsselfeld
var keyfield2 = obj.Keyfield2; //Selektiertes Schlüsselfeld
var oPdfViewer = new PDFViewer();
this.getView().addDependent(oPdfViewer);
var sServiceURL = this.getView().getModel().sServiceUrl;
var sSource = sServiceURL + "/documentSet(Keyfield1='"+ keyfield1 +"',Begda='"+ keyfield2 +"')/$value";
oPdfViewer.setSource(sSource);
oPdfViewer.setTitle( "PDF");
oPdfViewer.open();
}
Ergebnis beim Klick auf PDF anzeigen. Es öffnet sich ein Beispiel-PDF:
In meiner Anforderung war noch ein vorgeschaltetes Popup notwendig, welches es ermöglichen sollte einen Zeitraum auszuwählen bevor das PDF angezeigt wurde. Dafür musste noch ein eigenes Dialog-Fragment erstellt werden. Bei Interesse kann dieses Beispiel noch in einem weiteren Beitrag vorgestellt werden basierend auf diesem Beitrag.
Sei der Erste der einen Kommentar abgibt