Oracle Apex interactive grid i dynamiczne sumowanie kolum
Czasami w projekcie, w widoku inteactive grid mamy potrzebę dynamicznego podsumowania wartości wszystkich wierszy w kolumnie (np. by obliczyć wartość faktury) lub wykonania operacji przeliczenia wszystkich składników dokumentu jeśli zmienimy którekolwiek pole w formularzu. Gdyby była to wspomniana wcześniej faktura to np. po zmienie lilości w którymkolwiek wierszu potrzebowalibyśmy obliczyć wartość total tego wiersza na nowo i dokonać wyliczenia podatku, sumy netto i brutto całej faktury.
API apex.region zapewnia pojedynczy interfejs dla wszystkich popularnych funkcji Application Express związanych z regionami. Ten interfejs API zwraca obiekt regionu Application Express, który jest używany do uzyskiwania dostępu do funkcji i właściwości związanych z regionem.
Za pomocą tego API (JavaScript) możemy odczytywać wartość pól i je modyfikować.
Opiszemy przykład który zademonstruje jak zliczyć wartość wszystkich wierszy kolumny i jak wyliczyć wartość jednej z kolumn na podstawie wartości odczytanych z dwóch innych kolumn, dla każdego wiersza.
Tworzymy Dynamic Action kolumny.
Nasz przykład zademonstruje jak po zmianie ceny wyliczy się suma netto dla linii i jednocześnie przeliczy się wartość całej faktury. Rozpoczynamy od utworzenia "item" => "Number field" które w którym kolwiek regionie strony. Załóżmy że nazywa sie P20_NET_TOTAL. To pole będzie pełnić dwie funkcje; spowoduje wykonanie operacji zapisu co uaktualni wartość w polu które jest naszym celem (patrz problem z brakiem aktualizacji wartości) oraz wyswietli sume netto dla wszystkich wierszy kolumny "NET_TOTAL"
Następnie tworzymy Dynamic Action dla kolumny "NET_PRICE". "Event type" = change. Tworzymy dwie TRUE actions. Pierwsza akcja to "Set value" i PL/SQL Expression. W polu wyrażenia wpisujemy ":NET_PRICE". Druga TRUE action to "Execute JavaScript code". Treść kody wygląda następująco:
var model = apex.region("invoice_details").widget().interactiveGrid("getViews", "grid").model;
var o_amt, o_totamt = 0;
col_quantity = model.getFieldKey("ARTICLE_QUANTITY");
col_netprice = model.getFieldKey("NET_PRICE");
model.forEach(function(igrow) {
//Update total
var net_total;
net_total = parseInt(igrow[col_quantity]) * parseFloat(igrow[col_netprice], 10);
if (isFinite(net_total)){
model.setValue(igrow, "NET_TOTAL", net_total.toFixed(2));
}else{
model.setValue(igrow, "NET_TOTAL", '');
}
//Take to total only if product type is...
var product_type = model.getValue(igrow, "PRODUCT_TYPE" );
if(product_type == "oryginal"){
//net sum:
o_amt = parseFloat(igrow[col_netprice], 10);
if (!isNaN(o_amt)) {
o_totamt += o_amt;
}
}else{
//net sum:
s_amt = parseFloat(igrow[col_netprice], 10);
if (!isNaN(s_amt)) {
s_totamt += s_amt;
}
}
//Write sum to
apex.item("P20_NET_TOTAL").setValue(o_totamt.toFixed(2));
}
Możemy też zawrzeć ten kod w funkcji, funkcję umieścić w pliku i wgrać do Static Files. Następnie link do pliku wklejamy we właściwościach strony "JavaScript" => "File URLs" - np. #APP_IMAGES#recalculate_all.js. W oknie DA, JavaScript, Code wpisujemy "recalculate_all();"
function recalculate_all(){
var model =...
..
}
Jeśli chcemy kod wykonwał się także po "focus lost" i podobnie, musimy utoworzyć DA dla każdego z tych zachowań. Przeniesienie kodu do zewnetrznego pliku JS daje nam możliwość obejscia ograniczeń ilości znaków (4000?) i daje większą elastyczność - możemy odwoływać się do tej samej funkcji bez powielania kodu.