20210926 - this.triggeringElement

- Item Name : this.triggeringElement.id

- Item Value : $v(this.triggeringElement)

20210926 - 로그인 페이지 아이콘 대신 이미지로 변경

1. 이미지를 Static Application Files 에 업로드


2. 로그인 페이지 CSS 설정

Page - CSS - Inline :


.t-Login-logo {
    background-image: url('#APP_IMAGES#20210926-LogIn-FBF9F8.bmp'); 
    background-repeat: no-repeat; 
    background-size: cover;
    width: 240px;
    height: 70px;
    background-position: center center;
}
.t-Login-title {
    font-family: 'Hahmlet', serif;
    font-weight: 500;
    font-size: 28px;
}


3. 추가 : 백그라운드 변경 (redwood light 중)

Page - CSS - Inline :


.t-Body-main {
 background-image: url('https://static.oracle.com/cdn/apex/21.1.0/themes/theme_42/1.6/images/rw/textures/texture-11.png')
}

또는


body{
 background-image: url('https://static.oracle.com/cdn/apex/21.1.0/themes/theme_42/1.6/images/rw/textures/texture-11.png');
}





참고

https://www.traust.com/oracle-apex-simple-login-page-theming/

https://www.javainhand.com/2020/07/attractive-login-page-with-social-icons-in-oracle-apex.html

http://dgielis.blogspot.com/2015/09/custom-image-on-your-apex-app-login-page.html

https://apex.oracle.com/pls/apex/gamma_dev/r/demo/redwood


20210923 - Interactive Grid 선택한 열 Row 에 대한 특정 값 찾기

1. 디테일 그리드 등록 버튼 클릭시 마스터의 KEY 값을 읽어 팝업 창으로 전달


    config.initActions = function(actions){
        actions.add({
            name: "DA_PODTL_ClickAdd",
            action: function() {
                var ig$             = apex.region("myStaticIGPO").widget();
                var grid            = ig$.interactiveGrid("getViews","grid");
                var model           = grid.model;
                var selectedRecords = grid.view$.grid("getSelectedRecords");
                var record1         = selectedRecords[0];

                if( typeof record1 === 'undefined' || record1 === null){
                    apex.message.clearErrors();
                    apex.message.showErrors([{
                            type: "error",
                            location: ["page"],
                            message: "발주내역을 먼저 등록/선택 해 주십시오.",
                            unsafe: false
                        }
                    ]);    
                    return false;
                }

                var vPOID = model.getValue(record1,"PO_ID");

                if( typeof vPOID === 'undefined' || vPOID === null || vPOID == ""){
                    apex.message.clearErrors();
                    apex.message.showErrors([{
                            type: "error",
                            location: ["page"],
                            message: "발주내역을 먼저 등록/선택 해 주십시오.",
                            unsafe: false
                        }
                    ]);    
                    return false;
                }

                var l_url = 'f?p=#APP_ID#:5:#SESSION#::NO:RP,5:P5_PO_ID:#POID#';
                    l_url = l_url.replace('#APP_ID#',  $v('pFlowId'));
                    l_url = l_url.replace('#SESSION#', $v('pInstance'));
                    l_url = l_url.replace('#POID#', vPOID);

                // execute PL/SQL API apex_uti.prepare_url to generate a valid Session State Protection checksum
                apex.server.process(
                    'prodRegDA-popup',
                    {x01: l_url},
                    {success: function (pData) {
                            pData = pData.replace(",this", ",'#myStaticIG_ig_toolbar_btnOpenDialogPROD'");
                            apex.navigation.redirect(pData); // Call Modal Dialog Page                            
                        },
                        dataType: "text"
                    }
                );
            }
        });
    }


20210922 - 조건에 따라서 리전 펼치기/접기 Expand and collapsed

1. 리전 설정 (기본적으로 접기)

Region - Appearance - Template : Collapsible

Template Options : Use Template Defaults, Collapsed, Scroll - Default


2. Page Load - Dynamic Action - Execute Javascript


var vAQN = parseInt(apex.item("P5_ADJ_QTY_NORMAL").getValue());
var vAQR = parseInt(apex.item("P5_ADJ_QTY_REFURB").getValue());
var vAQD = parseInt(apex.item("P5_ADJ_QTY_DEFECTIVE").getValue());

if (vAQN > 0 || vAQR > 0 || vAQD > 0)
{
    $('#myStaticCollapsible.a-Collapsible.is-collapsed').removeClass('is-collapsed').addClass('is-expanded');
    $('#myStaticCollapsible.a-Collapsible .a-Collapsible-content').show();
}






참고

https://apex.oracle.com/pls/apex/f?p=44666:1:113177423838007:::::


20210921 - Interactive Grid 행 추가 버튼 대신 Custom 버튼으로 Modal Dialog 팝업 띄우기

1. IG - Attributes - Advanced - JavaScript Initialization Code :

  • IG Static ID 설정 : myStaticIG
  • 버튼 ID 설정 : btnOpenDialogPROD
  • 그리고 버튼 전체 ID 치환 : myStaticIG_ig_toolbar_btnOpenDialogPROD


function(config) {
    let $                = apex.jQuery,
        toolbarData      = $.apex.interactiveGrid.copyDefaultToolbar();
        addrowAction     = toolbarData.toolbarRemove("selection-add-row");
        saveAction       = toolbarData.toolbarRemove("save");
        editAction       = toolbarData.toolbarRemove("edit");
        actionsMenuGroup = toolbarData.toolbarFind("actions2");

    actionsMenuGroup.controls.push({
        type: "BUTTON",
        id: "btnOpenDialogPROD",
        label: "등록",
        icon: "icon-ig-add-row",
        iconBeforeLabel: true,
        hot: true,
        action: "DA_PODTL_ClickAdd"
        });

    config.initActions = function(actions){
        actions.add({
            name: "DA_PODTL_ClickAdd",
            action: function() {
                
                var l_url = 'f?p=#APP_ID#:5:#SESSION#::NO:RP';
                    l_url = l_url.replace('#APP_ID#',  $v('pFlowId'));
                    l_url = l_url.replace('#SESSION#', $v('pInstance'));

                // execute PL/SQL API apex_uti.prepare_url to generate a valid Session State Protection checksum
                apex.server.process(
                    'prodRegDA-popup',
                    {x01: l_url},
                    {success: function (pData) {
                            pData = pData.replace(",this", ",'#myStaticIG_ig_toolbar_btnOpenDialogPROD'");
                            apex.navigation.redirect(pData); // Call Modal Dialog Page                            
                        },
                        dataType: "text"
                    }
                );
            }
        });
    }

    config.toolbarData = toolbarData;
    return config;
}


2. Dynamic Action Dialog Closed 

When - Event : Dialog Closed

Selection Type : jQuery Selector

jQuery Selector : #myStaticIG_ig_toolbar_btnOpenDialogPROD




처음에 안 되어서 이렇게 찾아본 것인데
이상하게도 하다보니 추가로 Dynamic Action 없이 기존 리전 Dialog Close 것으로 Refresh 되었음.

참고

https://blog.virtual7.de/implementing-a-select-list-in-the-interactive-grids-toolbar/


20210918 - 컬럼 배경색 제어 Highlight Column

1. SQL과 HTML Expression 활용


select ename, sal,
       CASE WHEN sal <= 1500 THEN 'background-color:green' 
            WHEN sal > 1500 AND sal <= 3000 THEN 'background-color:orange'
            WHEN sal > 3000 THEN 'background-color:red'
            ELSE NULL
       END css_style
  from  (  
            select 'John' ename, 1500 sal from dual
            union all
            select 'Maxwell' ename, 3000 sal from dual
            union all
            select 'Nike' ename, 4500 sal from dual
        )


SAL Column - Column Formatting - HTML Expression :

<span data-style="#CSS_STYLE#">#SAL#</span>


Dynamic Action - When

Event : After Refresh

Selection Type : Region

Execute JavaScript Code - Code :

apex.jQuery("span[data-style]").each(

  function()

  { 

    apex.jQuery(this).parent().attr('style', apex.jQuery(this).attr('data-style')); 

  }

);

Fire on Initialization : Checked

** 아니면 SQL에서 CSS 명칭을 지정 후 CSS - Inline 코드 활용하여 색상 변경

ex) select 'bd-green' css_name from dual




2. Javascript Only

1.번과 동일한 Dynamic Action

Execute JavaScript Code - Code :


$("#myStaticIR tbody tr td").each(function(){
   if ($(this).attr('headers') != 'TOT') {
     if (parseInt($(this).text()) <= 1500)
        $(this).css({"background-color":"SandyBrown"});
     else if(parseInt($(this).text()) <= 3000)
        $(this).css({"background-color":"lightgreen"});
     else if(parseInt($(this).text()) > 3000)
        $(this).css({"background-color":"red"});
   }
});




3. CSS Only (컬럼 포맷팅, 특별한 경우 마이너스 '-')

1.번과 동일한 Dynamic Action

Actual Column - Column Formatting - HTML Expression :


<span data-number="#ACTUAL#">#ACTUAL#</span>


CSS - Inline :


span[data-number*="-"] {
    color:red;
}


4. (배경색은 아니지만) 페이지 아이템 강조 색상 변경 Page Item Label, Value

Inline CSS :


label[for="P13_COMMENT"], #P13_REMARK {
  font-size: 16px !important;
  font-weight: bold !important;
  color: redimportant;
}


5. 뽀나스 - Hierarchy 구조


select (level*20)-20 the_level,
        empno,ename,mgr
   from emp
connect by prior empno = mgr
  start with mgr is null



<span style="padding-left:#THE_LEVEL#px;">#ENAME#</span>



6. IR column Header

각 항목 SID 설정 후 PAGE CSS : 

#SID_OSTOCK a { color: #D86445; }
#SID_RSTOCK a { color: #D86445; }


20210918 - Interactive Grid, Interactive Report 툴바 메뉴 언어 한글 셋팅

기본적으로 옵션 조정을 하지 않으면 영어로 셋팅이 되고 변경하는 방법은 

1) 처음 Application 을 생성할 때 언어를 선택할 수도 있고 

2) 나중에 Shared Components >> Globalization Attributes >> Edit Globalization Attributes >> Application Primary Language 에서 조정 가능.





20210916 - AJAX Call 예제

AJAX Call 예제


1. https://apex.oracle.com/pls/apex/germancommunities/apexcommunity/tipp/3341/index-en.html


function getEmpInfo () {
  apex.server.process(
    'getEmpInfo',                             // Process or AJAX Callback name
    {x01: apex.item("P1_EMPNO").getValue()},  // Parameter "x01"
    {
      success: function (pData) {             // Success Javascript
        apex.item("P1_EMP_INFO").setValue(pData);
      },
      dataType: "text"                        // Response type (here: plain text)
    }
  );
}

Execute on Page Load


$("#P1_EMPNO").on("change", getEmpInfo);


2. https://www.linkedin.com/pulse/calling-plsql-from-javascript-oracle-apex-rodrigo-mesquita/


Declare
   ln_error_code         Number;
   lv_error_msg          varchar2(4000);   
Begin
FOR i IN 1..apex_application.g_f01.COUNT
LOOP
PROCESS_ORDER (p_order_num => apex_application.g_f01(i),
               p_return_code => ln_error_code ,
               p_return_message => lv_error_msg);
END LOOP;
/* below, the function return a JSON formatted string with the two returned values */
apex_json.open_object;
  apex_json.open_array('output');
    apex_json.open_object;
      apex_json.write('lv_error_code', ln_error_code);
       apex_json.write('lv_error_msg', lv_error_msg);
  apex_json.close_object
   apex_json.close_array;
apex_json.close_object;
End;

function processOrder(id) {
    /* to avoid the user to click on some other order while a order is being processed,
        we show the apex spinner, you need to set a ID on the report. in this case the ID is ORDER_REPORT */var lSpinner$ = apex.util.showSpinner( $( "#ORDER_REPORT" ) );
    /* ajax to call the database procedure */
    apex.server.process("PROCESS_ORDER", { // the ajax callback process name
        dataType: 'text',
        async:false/*by setting to false is equivalent to checking the Wait For Result option in the dynamic action */
        f01 : id, /* The order id passed from the report link */
        pageItems: "#P1_ORDER_ID" // The page item that we want to submit before calling the process.
    }, {
        success: function(pData) {
            /* now we can remove the spinner */
            lSpinner$.remove();
            
            /* The Ajax process will return lv_error_msg and lv_error_code, if lv_error_code = 0 
            show the successful message, if not show the error */ 
            var errorMsg = pData.output[0].lv_error_msg; 
            if (pData.output[0].lv_error_code == '0') {
                apex.message.clearErrors();
                apex.message.alert( 'Order processed successfully' );
            } else {
                apex.message.clearErrors();
                apex.message.showErrors([{
                    type: "error",
                    location: ["page"],
                    message: errorMsg,
                    unsafe: false
                }]);
            }
        }
    });
}



Edit the order id column to call the JavaScript function.

Type: Link
Target: Type: URL / Target: javascript:processOrder(#ORDER_ID#);
Link Text: #ORDER_ID#
Link Attributes: class="t-Button t-Button–simple t-Button–hot t-Button–stretch"


3. https://rimblas.com/blog/2020/07/video-using-apexserverprocess-for-ajax-calls-in-apex/


apex.server.process( "MY_PROCESS", {
    x01: 123,
    f01: jsArray,
    pageItems: "#P1_DEPTNO,#P1_EMPNO"
},
{
    dataType: "text"// default is json
    success: function( data )  {
        // do something here

    },
    error: function( jqXHR, textStatus, errorThrown ) {
        // handle error
    }
).always( function() {
    // code that needs to run for both success and failure cases
 }
);


그 외 참조

http://www.grassroots-oracle.com/2015/12/calling-plsql-from-javascript-in-apex.html

https://docs.oracle.com/database/apex-18.1/AEAPI/apex-server-namespace.htm#AEAPI29517

https://www.youtube.com/watch?v=ga-IgB15wDI

https://www.youtube.com/watch?v=yyuoIcF7hPI


20210916 - 모달 다이얼로그 팝업 창 Modal Dialog Popup

일단 시작점은 상품명을 입력하고 찾는 부분부터.


1. 상품명 Dynamic Action

Name : DA_ItemChangePNM

When - Event : Change

Selection Type : Item

Item : P15_PRODNM

True - Identification - Action : Execute JavaScript Code

Code : apex.event.trigger($("#btnOpenDialogPROD"),"click","");

내용을 입력한 후 Item Change에 대한 이벤트가 감지되면 상품명 옆의 찾기 버튼을 클릭한 것과 같이 이벤트를 트리거함.

찾기 버튼 속성 중 Advanced - Static ID : btnOpenDialogPROD


2. 찾기 버튼 Dynamic Action

Name : DA_FindClick

When - Event : Click

Selection Type : Button

Button : FIND

True - Identification - Action : Execute JavaScript Code

Code :


var vFindV = apex.item("P15_PRODNM").getValue();
var vArray;
var l_url = 'f?p=#APP_ID#:16:#SESSION#::NO:RP,16:P16_FINDC,P16_FINDV:#FINDC#,#FINDV#';

apex.message.clearErrors();
apex.item("P15_PRODID").setValue("", "", true);
apex.item("P15_PRODNM").setValue("", "", true);
apex.event.trigger( "#myStaticIR", "apexrefresh" );

apex.server.process(
    'prodFindDA-select1',
    {x01: vFindV},
    {success: function (pData) {

            vArray = pData.split(":");
            if (vArray[0] == 1)
            {
                apex.item("P15_PRODID").setValue(vArray[1], vArray[1], true);
                apex.item("P15_PRODNM").setValue(vArray[2], vArray[2], true);
                //이어서 조회, refresh
                return true;
            }
            
            l_url = l_url.replace('#APP_ID#',  $v('pFlowId'));
            l_url = l_url.replace('#SESSION#', $v('pInstance'));
            l_url = l_url.replace('#FINDC#',   'prodnm');
            l_url = l_url.replace('#FINDV#',   vFindV);

            // execute PL/SQL API apex_uti.prepare_url to generate a valid Session State Protection checksum
            apex.server.process(
                'prodFindDA-popup',
                {x01: l_url},
                {success: function (pData) {
                        pData = pData.replace(",this", ",'#btnOpenDialogPROD'");
                        apex.navigation.redirect(pData); // Call Modal Dialog Page
                        
                    },
                    dataType: "text"
                }
            );

            return true;
        },
        dataType: "text"
    }
  );

입력한 값을 기준으로 팝업을 오픈하기 전에 select 를 해 보아서 1건만 있으면 바로 찾아온 값을 셋팅하고 없거나 여러 건이라면 팝업 창을 오픈해서 선택할 수 있도록 하는 코드.


3. Select 하여 1건만 있는지 찾기 Ajax

Processing - Ajax Callback 

Identification - Name : prodFindDA-select1

Type : Execute Code

Editable Region : -Select-

Source - PL/SQL Code


declare
  l_value  varchar2(4000);
  l_pid    x0822_prod_mst.prod_id%type;
  l_pnm    x0822_prod_mst.prod_nm%type;
begin
  l_value := apex_application.g_x01;
    
  begin
    select prod_id, prod_nm
      into l_pid, l_pnm
      from x0822_prod_mst 
     where (prod_nm like '%'||l_value||'%');
    
    exception
      when no_data_found then htp.prn('0'); return;
      when too_many_rows then htp.prn('2'); return;
  end;

  htp.prn('1:'||l_pid||':'||l_pnm);
end;


4. 팝업을 위한 URL 만들기 Ajax

Processing - Ajax Callback 

Identification - Name : prodFindDA-popup

Type : Execute Code

Editable Region : -Select-

Source - PL/SQL Code


declare
    l_url    varchar2(2000);   
    l_result varchar2(4000);
begin
    l_result := apex_util.prepare_url(apex_application.g_x01);
    htp.prn(l_result);
end;


5. Modal 팝업 창에서 더블클릭시 값 반환, 창 닫기 Dynamic Action

Identification - Name : DA_DoubleClickIR

When - Event : Double Click

Selection Type : jQuery Selector

jQuery Selector : #myStaticIR td

True - Identification - Action : Execute JavaScript Code

Code :


var vPID = $(this.triggeringElement).closest('tr').find('td[headers="myStaticPID"]').text();
var vPNM = $(this.triggeringElement).closest('tr').find('td[headers="myStaticPNM"]').text();
apex.item("P16_PRODID_RTN").setValue(vPID, vPID, true);
apex.item("P16_PRODNM_RTN").setValue(vPNM, vPNM, true);



Identification - Action : Close Dialog

Setting : Items to Return : P16_PRODID_RTN,P16_PRODNM_RTN


6. 메인 페이지 Dialog Closed Dynamic Action 에서 팝업 창에서 반환된 값 수신

Identification - Name : Dialog Closed from

When - Event : Dialog Closed

Selection Type : jQuery Selector

jQuery Selector : body >> 이렇게 써야한다는 것을 어떻게 알겠습니까.

True - Identification - Action : Execute JavaScript Code

Setting - Code :


var vPID = this.data.P16_PRODID_RTN;
var vPNM = this.data.P16_PRODNM_RTN;

apex.item("P15_PRODID").setValue(vPID, vPID, true);
apex.item("P15_PRODNM").setValue(vPNM, vPNM, true);

그런 후에 관련 리전 Refresh.


7. 뽀나스 : 조회버튼 클릭시 (상품코드, 기준일자) 조건 체크 후 없으면 메세지 보이기

Dynamic Action


var vPRODID = apex.item("P15_PRODID").getValue();
var vSDATE  = apex.item("P15_SDATE").getValue();

vPRODID = vPRODID.trim();
vSDATE  = vSDATE.trim();

if( typeof vPRODID === 'undefined' || vPRODID === null || vPRODID == ""){
    apex.item("P15_PRODNM").setFocus();
    apex.message.clearErrors();
    apex.message.showErrors([{
            type: "error",
            location: ["page", "inline"],
            pageItem: "P15_PRODNM",
            message: "상품명을 입력해 주십시오.",
            unsafe: false
        }
    ]);    
    return false;
}

if( typeof vSDATE === 'undefined' || vSDATE === null || vSDATE == ""){
    apex.item("P15_SDATE").setFocus();
    apex.message.clearErrors();
    apex.message.showErrors([{
            type: "error",
            location: ["page", "inline"],
            pageItem: "P15_SDATE",
            message: "조회기준일을 입력해 주십시오.",
            unsafe: false
        }
    ]);    
    return false;
}



참고해서 구현 해 보면 좋은 것 같은.

https://www.ostrowskibartosz.pl/2019/12/open-modal-page-using-pretius-apex-context-menu/




20250202 - IG 다운로드 버튼 바로 보이기

JS initialization Code : function (config) {     var $ = apex.jQuery,         toolbarData = $.apex.interactiveGrid.copyDefaultToolbar(),  ...