Automatisch refreshen nach Auswahl in Popup-LOV

Problembeschreibung

Ich möchte in APEX eine Popup-LOV benutzen, um eine Auswahlliste zu implementieren. Nach der Auswahl in der Popup-LOV soll abhängig von der getroffenen Auswahl eine Region automatisch refreshed werden.

Eigentlich klingt das super einfach! Schon tausend mal gemacht.

Man nimmt eine dynamic Action, hängt sie an ein Change-Event und macht einen Partial-Page-Refresh.

Tja, schade nur, dass das Change-Event nicht zündet.

Bis APEX 4.2 klappt das so nicht. ACHTUNG! Mit APEX 5 haben sie es endlich in den Griff bekommen.

Das Problem hierbei ist, dass das zugrunde liegende Item deaktiviert ist und somit keine Event zünden. Ich bin mir auch nicht sicher, woran es liegt. Eigentlich dachte ich, dass die HTML Spezifikation Schuld daran wäre, aber seitdem ich gesehen habe, dass es mit APEX 5 klappt, denke ich, liegt es wohl doch eher an APEX.

Anyway…

Jedenfall benötigen wir deshalb bis APEX 4.2 einen Workaround. Natürlich gibt es mehrere Wege, wie man einen Workaround hierfür aufsetzen kann. Eine Variante, die mir am einfachsten erscheint, habe ich implementiert und hier im folgenden beschrieben.

Konzept

Die Idee hinter dieser Lösung ist, dass man sich in das on-click Event der Popup-LOV einklingt, die existierende Funktionalität überschreibt bzs. erweitert und die Dynamic-Action im Opener-Window zum refreshen explizit aufruft.

Dabei ist jedoch zu beachten, dass das Change-Event hierbei trotzdem nicht zündet. Wir müssen hier inen kleinen Trick anwenden, damit es klappt – nämlich das Item vor dem refreshen per JQuery aktivieren und anschl. wieder deaktivieren.

 

Lösung

Zuerst erstellen wir im Formular eine JavaScript Funktion mit dem Namen “doRefreshForPopupLov”. Diese Funktion soll später unsere Region explizit refreshen. Der Code sieht in etwa so aus:

function doRefreshForPopupLov() {
  // zuerst enablen wir das Item, in dem wir die Eigenschaft "disabled" entfernen":
  $("#P10_USR_ID").removeAttr('disabled');
  // dann refreshen wir über die dynamic-action mit Hilfe des Event-Triggers:
  apex.event.trigger($("#P10_USR_ID"),"change","");
  // und nun disablen wir das Item wieder, um den Ausgangszustand zu erhalten:
  $("#P10_USR_ID").attr('disabled', 'disabled');
}

Nun müssen wir leider etwas machen, was mir persönlich gar nicht gefällt: wir müssen das Popup-LOV Template ändern (kopieren geht bei diesem Template-Type leider nicht!) und müssen die APEX-Methode “passBack” hacken bzw. neu implementieren.

Hinweis:
Da es bei verschiendenen APEX Versionen theoretisch unterschiedliche Implementierungen geben kann, sollte die “passBack” Methode immer aus der jeweils genutzen Version kopiert werden. Dazu die Popup-LOV aufrufen → rechte Maustaste → Quelltext anzeigen → suchen nach “passBack” → Quellcode der Funktion “passBack” kopieren.

Da dieses Template leider nicht bei den verwendeten Page-Templates angezeigt wird, müssen wir es aufrufen über “Shared Components → Templates → Popup LOV”.
Hier implementieren wir nun unter “Page HTML Head” ein paar benötigte Javascript Funktionen.

ACHTUNG! Die Kopie der passBack Methode, die wie oben beschrieben wurde, kopiert ist, hier nun einfügen und umbenennen in passBackWithRefreh. Dann einfach nun die folgende Zeile an entspr. Stelle einbauen.

// NIDa-Spezifisch:
opener.doRefreshForPopupLov();

Hier nun der gesamte Quelltext für die Popup-LOV:

<script language="JavaScript">
<!--
 
// Neue APEX passBack Function mit eigener Refresh-Erweiterung
function passBackWithRefresh(pReturn, pDisplay){
  var lDisplayField = opener.$x("P10_USR_ID");
  try {
  opener.$s(lDisplayField, pReturn, pDisplay);
  } catch(e) {}
 
  // NIDa-Spezifisch:
  opener.doRefreshForPopupLov();
 
  window.close();
  if(!(lDisplayField.disabled || lDisplayField.type == 'HIDDEN')){lDisplayField.focus();}
};
 
// Die neue "passBack"-Funktion wird nun hierüber an alle Anchor-Tags der LOV-Return-Links angeheftet.
$(function(){
    $('.lovLinks a').each(function(){
        $(this).attr('href', $(this).attr('href').replace('passBack', 'passBackWithRefresh'));
    });
});
 
-->
</script>

Nun sollte alles funktionieren.

Schreibe einen Kommentar