FIORI: $expand dla konkretnego rekodu (nie setu)

Jeśli programujesz, administrujesz, integrujesz i masz wątpliwość lub obawę, to właśnie najlepsze miejsce dla Ciebie. Pisz śmiało...
emil
Posty: 140
Rejestracja: pt gru 27, 2019 11:02 am
Has thanked: 29 times
Been thanked: 44 times

FIORI: $expand dla konkretnego rekodu (nie setu)

Post autor: emil »

Opierając się na wskazówkach z
https://www.techippo.com/2017/09/bind-e ... -view.html
spróbowałem wyciągnąć wszystkie dane dotyczące szkoleń wybranego numeru ewidencyjnego.

Przy testowaniu getaway`a widzę, że dostaję z backendu poprawne zwrotki, czyli:

(...)PracownicySet('00000128')?$expand=toSzkolenia zwraca mi wszystkie rekordy ze szkoleniami, które dotyczą pracownika o wskazanym pernr.

Jeśli usunę nr ewid z adresu (uzyskując PracownicySet?$expand=toSzkolenia ) otrzymuję szkolenia wszystkich numerów ewid, do których mam dostęp w ramach swoich uprawnień.

Teraz przechodzimy na frontend:

Kod: Zaznacz cały

<mvc:View     
controllerName="zprofman3.zprofman3.controller.Object"
 xmlns:mvc="sap.ui.core.mvc" 
 xmlns="sap.m"
 xmlns:f="sap.f"
 xmlns:layout="sap.ui.layout" 
 xmlns:core="sap.ui.core" 
 height="100%" 
 xmlns:app="http://schemas.sap.com/sapui5/extension/sap.ui.core.CustomData/1">
    <f:DynamicPage class="sapUiNoContentPadding" showFooter="true" preserveHeaderStateOnScroll="true" toggleHeaderOnTitleClick="false">
        <!-- DynamicPage Header -->
        <f:header>
            <f:DynamicPageHeader pinnable="false">
                <layout:HorizontalLayout allowWrapping="true">

                    <layout:VerticalLayout id="idHeader" class="sapUiMediumMarginEnd" >
                        <ObjectIdentifier title="{Nazwisko} {Imie} ({Pernr})" />
                        <ObjectAttribute  text="Jednostka org.: {Zorg1}" />
                        <ObjectAttribute  text="Stanowisko: {Stanowisko}" />
                        <ObjectAttribute  text="Komórka org.: {Zorg2}" />

                    </layout:VerticalLayout>
                </layout:HorizontalLayout>
            </f:DynamicPageHeader>
        </f:header>
        <f:content>

<VBox>

   <List 
    items="{path : '/PracownicySet' , parameters:{expand : 'toSzkolenia'} }"
    id="szkolenia"
    headerText="Szkolenia">
   <items>
    <CustomListItem>
    <content>
      <Title text="Nagłówek do numeru ewid: {Pernr}"></Title>
      <List items="{toSzkolenia}">
     <items>
      <ObjectListItem title="Szkolenie: {Tytul1}" intro="{Kod}">
      </ObjectListItem>
     </items>
      </List>
    </content>
     </CustomListItem>
    </items>
   </List>		

</VBox>

        </f:content>
    </f:DynamicPage>
</mvc:View>
Jak widać, dla listy deklaruję sobie items="{path : '/PracownicySet' , parameters:{expand : 'toSzkolenia'} }" (analogicznie jak w przykładzie z linku), co skutkuje zwrotką w postaci wszystkich rekordów dot szkoleń dla wszystkich pernr do których mam uprawnienia.
Nie bardzo rozumiem, jak mógłbym przekazać informację, że nie chodzi mi o cały PracownicySet, a na przykład /PracownicySet('00000123')
Z ciekawości próbowałem na sztywno podać jakiś pernr - nie dało rady, VSC i przeglądarką rzucały się o zbędny cudzysłów, który rozwalał dalej całą składnię.

Oczywiście finalnie zależy mi na tym, by frontend wyświetlił jedynie te rekordy, które dotyczą wskazany nr ewid (widoczny w url https://<ciach>/PracownicySet('00000123').

Sam interesujący mnie pernr, mam w view w {Pernr}.

Poniżej, jako uzupełnienie, controller.js:

Kod: Zaznacz cały

sap.ui.define([
    "./BaseController",
    "sap/ui/model/json/JSONModel",
    "sap/ui/core/routing/History",
    "../model/formatter"
], function (BaseController, JSONModel, History, formatter) {
    "use strict";

    return BaseController.extend("zprofman3.zprofman3.controller.Object", {

        formatter: formatter,

        /* =========================================================== */
        /* lifecycle methods                                           */
        /* =========================================================== */

        /**
         * Called when the worklist controller is instantiated.
         * @public
         */
        onInit : function () {
            // Model used to manipulate control states. The chosen values make sure,
            // detail page shows busy indication immediately so there is no break in
            // between the busy indication for loading the view's meta data
            var oViewModel = new JSONModel({
                    busy : true,
                    delay : 0
                });
            this.getRouter().getRoute("object").attachPatternMatched(this._onObjectMatched, this);
            this.setModel(oViewModel, "objectView");
        },
        /* =========================================================== */
        /* event handlers                                              */
        /* =========================================================== */

        /**
         * Event handler  for navigating back.
         * It there is a history entry we go one step back in the browser history
         * If not, it will replace the current entry of the browser history with the worklist route.
         * @public
         */
        onNavBack : function() {
            var sPreviousHash = History.getInstance().getPreviousHash();
            if (sPreviousHash !== undefined) {
                // eslint-disable-next-line fiori-custom/sap-no-history-manipulation
                history.go(-1);
            } else {
                this.getRouter().navTo("worklist", {}, true);
            }
        },

        /* =========================================================== */
        /* internal methods                                            */
        /* =========================================================== */

        /**
         * Binds the view to the object path.
         * @function
         * @param {sap.ui.base.Event} oEvent pattern match event in route 'object'
         * @private
         */
        _onObjectMatched : function (oEvent) {
            var sObjectId =  oEvent.getParameter("arguments").objectId;
            this._bindView("/PracownicySet" + sObjectId  );
        },

        /**
         * Binds the view to the object path.
         * @function
         * @param {string} sObjectPath path to the object to be bound
         * @private
         */
        _bindView : function (sObjectPath) {
            var oViewModel = this.getModel("objectView");

           this.getView().bindElement({
                path: sObjectPath,
                events: {
                    change: this._onBindingChange.bind(this),
                    dataRequested: function () {
                        oViewModel.setProperty("/busy", true);
                    },
                    dataReceived: function () {
                        oViewModel.setProperty("/busy", false);
                    }
                }
            });
        },

        _onBindingChange : function () {
            var oView = this.getView(),
                oViewModel = this.getModel("objectView"),
                oElementBinding = oView.getElementBinding();

            // No data for the binding
            if (!oElementBinding.getBoundContext()) {
                this.getRouter().getTargets().display("objectNotFound");
                return;
            }

            var oResourceBundle = this.getResourceBundle(),
                oObject = oView.getBindingContext().getObject(),
                sObjectId = oObject.Pernr,
                sObjectName = oObject.PracownicySet;

                oViewModel.setProperty("/busy", false);
                oViewModel.setProperty("/shareSendEmailSubject",
                    oResourceBundle.getText("shareSendEmailObjectSubject", [sObjectId]));
                oViewModel.setProperty("/shareSendEmailMessage",
                    oResourceBundle.getText("shareSendEmailObjectMessage", [sObjectName, sObjectId, location.href]));
        },
        _onClickButton: function(){
            const oControler = this;
            const sPernr = oControler.pernr;

            const oView = oControler.getView();
            const oTitleControl=oView.byId("idTitle");
            const sTitle=oTitleControl.getText();

            this.getRouter().navTo("stanowiska", {
                objectId: sPernr
            });
        }
    });
});
Co do jakości kodu - nie linczujcie mnie proszę, wspieram się tym, co VSC generuje tworząc apkę kreatorem.

Ogólny zamysł na apkę jest następujący: pierwszy ekran wyświetla listę podległych pracowników, drugi wyświetla szczegółowe informacje o podległych pracownikach. Co ważne: szczegóły to kilka różnych itabów zawierających 0-n rekordów.
K602
Posty: 148
Rejestracja: śr sie 24, 2022 11:50 am
Has thanked: 74 times
Been thanked: 91 times

Re: FIORI: $expand dla konkretnego rekodu (nie setu)

Post autor: K602 »

Nie znoszę JS i Fiori... sorry za offtop. ale nie pomogę... :)

Może zrób klasyczne WebDynrpro :)
SAP ABAP Certified Developer
emil
Posty: 140
Rejestracja: pt gru 27, 2019 11:02 am
Has thanked: 29 times
Been thanked: 44 times

Re: FIORI: $expand dla konkretnego rekodu (nie setu)

Post autor: emil »

K602 pisze: wt paź 08, 2024 1:59 pm Może zrób klasyczne WebDynrpro :)
No właśnie przepisuję z webdynpro na fiorkę...
Tzn. próbuję :P
K602
Posty: 148
Rejestracja: śr sie 24, 2022 11:50 am
Has thanked: 74 times
Been thanked: 91 times

Re: FIORI: $expand dla konkretnego rekodu (nie setu)

Post autor: K602 »

Pytanie, czy na pewno potrzebnie, bo my wiele aplikacji WD, po prostu odpalamy w nowym FIORI pulpicie, w postacie kafelek...
SAP ABAP Certified Developer
emil
Posty: 140
Rejestracja: pt gru 27, 2019 11:02 am
Has thanked: 29 times
Been thanked: 44 times

Re: FIORI: $expand dla konkretnego rekodu (nie setu)

Post autor: emil »

Tak, tym razem to konieczne.
Męczę temat w ramach nauki nowego środowiska.