Tag Archive joget

Byphunsanit

JoGet: Bean Shell Create Json

วิธีดีที่สุดในการให้ข้อมูลจำนวนมากให้ javascript คือรูปแบบ json ไม่เว้นแม้แต่ใน JoGet เพราะถึงแม้จะสามารถดึงข้อมูลจาก input หรือ grid ได้ แต่มันจะถูกบันทึกลง database ไปด้วยแถมดูรก

วิธีที่ดีอีกวิธีคือให้ beanshell ใน section ดึงข้อมูลจาก query แล้วแสดงออกมาใน input ตัวเดียว

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.joget.apps.app.service.AppUtil;
import org.joget.apps.form.model.Element;
import org.joget.apps.form.model.FormData;
import org.joget.apps.form.model.FormRow;
import org.joget.apps.form.model.FormRowSet;
import org.joget.apps.form.service.FormUtil;
import org.joget.commons.util.LogUtil;
import org.json.simple.JSONObject;

public FormRowSet load(Element element, String username, FormData formData) {

 FormRowSet rows = new FormRowSet();

 Connection con = null;
 try {
  DataSource ds = (DataSource) AppUtil.getApplicationContext().getBean("setupDataSource");
  con = ds.getConnection();

  sql = "SELECT appId, appVersion, name FROM jwdb.app_app WHERE published = 1;";
  //LogUtil.info("Bean Shell Create Json", "sql = " + sql);

  if (!con.isClosed()) {
   PreparedStatement stmt = con.prepareStatement(sql);
   ResultSet rs = stmt.executeQuery();

   /* create json */
   JSONObject json = new JSONObject();
   while (rs.next()) {
    JSONObject item = new JSONObject();

    item.put("appVersion", rs.getObject("appVersion"));
    item.put("name", rs.getObject("name"));

    json.put(rs.getObject("appId"), item);
   }

   /* add json to input */
   FormRow row = new FormRow();
   rows.add(row);
   row.put("json", json.toString());
  }

 } catch (Exception e) {
  LogUtil.error(getClassName(), e, "Bean Shell Create Json");
 } finally {
  try {
   if (con != null) {
    con.close();
   }
  } catch (SQLException e) {}
 }

 return rows;
}

return load(element, primaryKey, formData);

ตัวอย่างฟอร์ม

{
    "className": "org.joget.apps.form.model.Form",
    "properties": {
        "noPermissionMessage": "",
        "loadBinder": {
            "className": "org.joget.apps.form.lib.WorkflowFormBinder",
            "properties": {}
        },
        "name": "Bean Shell Create Json",
        "description": "",
        "postProcessorRunOn": "both",
        "permission": {
            "className": "",
            "properties": {}
        },
        "id": "BeanShellCreateJson",
        "postProcessor": {
            "className": "",
            "properties": {}
        },
        "storeBinder": {
            "className": "org.joget.apps.form.lib.WorkflowFormBinder",
            "properties": {}
        },
        "tableName": "prototypes"
    },
    "elements": [
        {
            "elements": [
                {
                    "elements": [
                        {
                            "className": "org.joget.apps.form.lib.TextArea",
                            "properties": {
                                "readonly": "",
                                "validator": {
                                    "className": "",
                                    "properties": {}
                                },
                                "workflowVariable": "",
                                "id": "json",
                                "label": "JSON",
                                "placeholder": "",
                                "rows": "10",
                                "value": "",
                                "cols": "100",
                                "readonlyLabel": ""
                            }
                        }
                    ],
                    "className": "org.joget.apps.form.model.Column",
                    "properties": {
                        "width": "100%"
                    }
                }
            ],
            "className": "org.joget.apps.form.model.Section",
            "properties": {
                "readonly": "",
                "loadBinder": {
                    "className": "org.joget.apps.form.lib.BeanShellFormBinder",
                    "properties": {
                        "useAjax": "",
                        "cacheIdlePause": "120",
                        "cacheInterval": "",
                        "script": "import java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport javax.sql.DataSource;\nimport org.joget.apps.app.service.AppUtil;\nimport org.joget.apps.form.model.Element;\nimport org.joget.apps.form.model.FormData;\nimport org.joget.apps.form.model.FormRow;\nimport org.joget.apps.form.model.FormRowSet;\nimport org.joget.apps.form.service.FormUtil;\nimport org.joget.commons.util.LogUtil;\nimport org.json.simple.JSONObject;\n\npublic FormRowSet load(Element element, String username, FormData formData) {\n\n FormRowSet rows = new FormRowSet();\n\n Connection con = null;\n try {\n  DataSource ds = (DataSource) AppUtil.getApplicationContext().getBean(\"setupDataSource\");\n  con = ds.getConnection();\n\n  sql = \"SELECT appId, appVersion, name FROM jwdb.app_app WHERE published = 1;\";\n  //LogUtil.info(\"Bean Shell Create Json\", \"sql = \" + sql);\n\n  if (!con.isClosed()) {\n   PreparedStatement stmt = con.prepareStatement(sql);\n   ResultSet rs = stmt.executeQuery();\n\n   /* create json */\n   JSONObject json = new JSONObject();\n   while (rs.next()) {\n    JSONObject item = new JSONObject();\n\n    item.put(\"appVersion\", rs.getObject(\"appVersion\"));\n    item.put(\"name\", rs.getObject(\"name\"));\n\n    json.put(rs.getObject(\"appId\"), item);\n   }\n\n   /* add json to input */\n   FormRow row = new FormRow();\n   rows.add(row);\n   row.put(\"json\", json.toString());\n  }\n\n } catch (Exception e) {\n  LogUtil.error(getClassName(), e, \"Bean Shell Create Json\");\n } finally {\n  try {\n   if (con != null) {\n    con.close();\n   }\n  } catch (SQLException e) {}\n }\n\n return rows;\n}\n\nreturn load(element, primaryKey, formData);"
                    }
                },
                "permissionReadonly": "",
                "permission": {
                    "className": "",
                    "properties": {}
                },
                "comment": "",
                "id": "section1",
                "label": "Bean Shell Create Json",
                "storeBinder": {
                    "className": "",
                    "properties": {}
                },
                "readonlyLabel": ""
            }
        }
    ]
}

Byphunsanit

javascript: string to JSON.parse()

หลังจากใช้ MySQL: return json format กันเป็นแล้วเรามาลองใช้กับ joget แทนที่จะต้องไปเขียน beanshell ให้ยุ่งยาก (พลาดง่ายๆ อีกตะหาก) ดูจริงๆ แล้วสามารถใช้กับหน้าเว็บทั้งหมดไม่ใช่แค่ joGet เพราะมันคือ javascript พื้นฐาน

เปิดฟอร์มที่ต้องการมา

  1. สร้าง section ขึ้นมา โดยกำหนด Load Binder เป็น JDBC Binder และ SQL SELECT Query ใส่ query ที่ต้องการ เช่น
    SELECT
        CONCAT('[',
                GROUP_CONCAT(JSON_OBJECT('label', name, 'value', appId)),
                ']') AS optionsList
    FROM
        jwdb.app_app
    ORDER BY name ASC
  2. ลาก Hidden Field มาตั้ง id เป็น optionsList ใน section ที่สร้างไว้
  3. เขียน javascript ดึงค่ามาจาก string json ที่เก็บไว้ใน input ชื่อ optionsList โดยใช้ JSON.parse() เผื่อความปลอดภัย ควรใช้ JSON.parse() ใน try catch เพราะว่าถ้า json ที่ได้ผิดปกติจะสามารถควบคุมได้ ลาก Custom HTML มาแล้วใส่ code
    <table class="table table-striped" id="tableA">
        <thead>
            <tr>
                <th scope="col" style="width:20px;">#</th>
                <th scope="col">Name</th>
                <th scope="col">Value</th>
            </tr>
        </thead>
        <tbody>
        </tbody>
    </table>
    <script>
        $(document).ready(function () {
    
            let html = new Array();
            let no = 0;
            let optionsList = $('#optionsList');
            try {
                let temp = JSON.parse(optionsList.val());
    
                if (temp.length > 0) {
                    $.each(temp, function (index, value) {
                        no++;
                        html.push('<tr><th scope="row">' + no + '</th><td>' + value.label + '</td><td>' + value.value + '</td><tr>');
                    });
                }
                if (html.length == 0) {
                    html = '<tr><th scope="row">-</th><td>-</td><td>-</td><tr>';
                } else {
                    html = html.join("\n");
                }
            } catch (e) {
                console.log(e.message);
                html = '<h1>Error!!</h1>';
            }
            $('#tableA > tbody').html(html);
    
        });
    </script>

สามารถ copy form ตัวอย่างได้จาก json

{
    "className": "org.joget.apps.form.model.Form",
    "properties": {
        "noPermissionMessage": "",
        "loadBinder": {
            "className": "org.joget.apps.form.lib.WorkflowFormBinder",
            "properties": {}
        },
        "name": "JSON Parse",
        "description": "",
        "postProcessorRunOn": "both",
        "permission": {
            "className": "",
            "properties": {}
        },
        "id": "JSONParse",
        "postProcessor": {
            "className": "",
            "properties": {}
        },
        "storeBinder": {
            "className": "org.joget.apps.form.lib.WorkflowFormBinder",
            "properties": {}
        },
        "tableName": "prototypes"
    },
    "elements": [
        {
            "elements": [
                {
                    "elements": [
                        {
                            "className": "org.joget.apps.form.lib.HiddenField",
                            "properties": {
                                "useDefaultWhenEmpty": "",
                                "workflowVariable": "",
                                "id": "optionsList",
                                "value": ""
                            }
                        }
                    ],
                    "className": "org.joget.apps.form.model.Column",
                    "properties": {
                        "width": "100%"
                    }
                }
            ],
            "className": "org.joget.apps.form.model.Section",
            "properties": {
                "readonly": "",
                "loadBinder": {
                    "className": "org.joget.plugin.enterprise.JdbcLoadBinder",
                    "properties": {
                        "jdbcDatasource": "default",
                        "sql": "SELECT \n    CONCAT('[',\n            GROUP_CONCAT(JSON_OBJECT('label', name, 'value', appId)),\n            ']') AS optionsList\nFROM\n    jwdb.app_app\nORDER BY name ASC"
                    }
                },
                "permissionReadonly": "",
                "permission": {
                    "className": "",
                    "properties": {}
                },
                "comment": "",
                "id": "section1",
                "label": "",
                "storeBinder": {
                    "className": "",
                    "properties": {}
                },
                "readonlyLabel": ""
            }
        },
        {
            "elements": [
                {
                    "elements": [
                        {
                            "className": "org.joget.apps.form.lib.CustomHTML",
                            "properties": {
                                "autoPopulate": "",
                                "id": "field2",
                                "label": "",
                                "value": "<table class=\"table table-striped\" id=\"tableA\">\n    <thead>\n        <tr>\n            <th scope=\"col\" style=\"width:20px;\">#</th>\n            <th scope=\"col\">Name</th>\n            <th scope=\"col\">Value</th>\n        </tr>\n    </thead>\n    <tbody>\n    </tbody>\n</table>\n<script>\n    $(document).ready(function () {\n\n        let html = new Array();\n        let no = 0;\n        let optionsList = $('#optionsList');\n        try {\n            let temp = JSON.parse(optionsList.val());\n\n            if (temp.length > 0) {\n                $.each(temp, function (index, value) {\n                    no++;\n                    html.push('<tr><th scope=\"row\">' + no + '</th><td>' + value.label + '</td><td>' + value.value + '</td><tr>');\n                });\n            }\n            if (html.length == 0) {\n                html = '<tr><th scope=\"row\">-</th><td>-</td><td>-</td><tr>';\n            } else {\n                html = html.join(\"\\n\");\n            }\n        } catch (e) {\n            console.log(e.message);\n            html = '<h1>Error!!</h1>';\n        }\n        $('#tableA > tbody').html(html);\n\n    });\n</script>"
                            }
                        }
                    ],
                    "className": "org.joget.apps.form.model.Column",
                    "properties": {
                        "width": "100%"
                    }
                }
            ],
            "className": "org.joget.apps.form.model.Section",
            "properties": {
                "readonly": "",
                "loadBinder": {
                    "className": "",
                    "properties": {}
                },
                "permissionReadonly": "",
                "permission": {
                    "className": "",
                    "properties": {}
                },
                "comment": "",
                "id": "section2",
                "label": "Options List",
                "storeBinder": {
                    "className": "",
                    "properties": {}
                },
                "readonlyLabel": ""
            }
        }
    ]
}

Byphunsanit

JoGet: Save PDF From Jasper Report

ตัวอย่างการ save pdf file ที่สร้างมาจาก JasperReports ก่อนที่จะส่งให้ user ทางอีเมล์ เพื่อที่ฝ่ายที่เกี่ยวข้องจะได้นำไฟล์มาตรวจสอบความถูกต้องในภายหลังว่ารีพอร์ตที่เป็น pdf ไฟล์ที่ส่งไปมีเนื่้อหายังไงจากไฟล์ที่บันทึกเอาไว้

เราสามารถทำได้โดยใช้ plugin Bean Shell Tool ตามตัวอย่าง

import java.util.HashMap;
import java.util.Map;
import javax.sql.DataSource;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRExporterParameter;
import net.sf.jasperreports.engine.JasperExportManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import net.sf.jasperreports.engine.export.JRXlsExporter;
import org.joget.apps.app.service.AppUtil;

public Object execute() {

/* get parameters from outside activity tools box */
String id = "#variable.id#";

String documentRoot = "C:\\Joget-v5-Enterprise\\apache-tomcat-8.0.20\\webapps\\jw\\";

/* connection to default datasource */
DataSource ds = (DataSource) AppUtil.getApplicationContext().getBean("setupDataSource");
con = ds.getConnection();

/* load JasperReports template */
String sourceFileName = documentRoot + "assets\\JasperReports\\app.jasper";

Map parameters = new HashMap();

/* send parameters to jasper report */
parameters.put("id", id);

/* genrate pdf file and save to local directory */
printFileName = JasperFillManager.fillReportToFile(sourceFileName, parameters, con);
if (printFileName != null) {
JasperExportManager.exportReportToPdfFile(printFileName, documentRoot + "datas\\policies\\" + id + ".pdf");
}

return null;
}

//call execute method
return execute();

อธิบายการทำงาน จะเรียกใช้ beanshell เข้าไปเรียก class เดียวกับที่ joget ใช้ จึงมั่นใจได้ว่ารีพอร์ตที่ออกมาจะเหมือนกับที่ joget ใช้จริงๆ โดยจะอ่านไฟล์ .jasper มาจาก “C:\Joget-v5-Enterprise\apache-tomcat-8.0.20\webapps\jw\assets\JasperReports\app.jasper” จากนั้นจะสรุปออกมาเป็นไฟล์ .jrprint เอาไว้ใน “C:\Joget-v5-Enterprise\apache-tomcat-8.0.20\webapps\jw\assets\JasperReports\” เหมือนกัน แต่ชื่อไฟล์อาจจะต่างกันโดยจะตั้งตาม atrbut name ที่อยู่ใน tag jasperReport และสร้างไฟล์ pdf เก็บไว้ที่ “C:\Joget-v5-Enterprise\apache-tomcat-8.0.20\webapps\jw\datas\policies” ตาม ที่กำหนดไว้ที่ใน JasperExportManager.exportReportToPdfFile

เพราะว่าไฟล์ใน “C:\Joget-v5-Enterprise\apache-tomcat-8.0.20\webapps\jw” สามารถเรียกดูได้จาก url จึงควรระวังเรื่อง Information leakage เอาไว้ด้วย

Byphunsanit

Joget: แสดงเฉพาะ form / datalist

น้อง (รึเปล่า) ที่ทำงานต้องการจะแสดง datalist ในฟอร์ม ทำให้เกิดการค้นหาข้อมูลกันนิดหนึ่ง แต่จริงๆ แล้วก็มีอยู่ในแอปตัวอย่างของ Joget นั่นละ แต่ไม่ยักกะเขียนไว้ในคู่มือ Datalist Builder

สมมุติว่า url ของหน้าที่แสดง datalist คือ http://localhost:8080/jw/web/userview/crm/crm_userview_sales/_/UsersDashboard ถ้าจะแสดงเฉพาะส่วน body ไม่เอา header และ footer ได้ง่ายๆเพียงแค่ใส่ ?embed=true ไปเท่านั้น คือ http://localhost:8080/jw/web/userview/crm/crm_userview_sales/_/UsersDashboard?embed=true หลังจากนี้ก็จะเหมาะที่จะแสดงใน iframe หรือ เรียกใช้จาก ajax ได้แล้ว

จากนั้นหลังการค้นคว้าเพิ่มเติมก็ได้เจอกับ Embedded Mode ที่สามารถเพิ่ม /embed/ ก่อน /userview/ เช่น http://localhost:8080/jw/web/userview/crm/crm_userview_sales/_/UsersDashboard เป็น http://localhost:8080/jw/web/embed/userview/crm/crm_userview_sales/_/UsersDashboard

วิธีนี้สามารถใช้กับฟอร์มได้เหมือนกัน เช่น http://localhost:8080/jw/web/userview/crm/crm_userview_sales/_/UserForm?id=clark เป็น http://localhost:8080/jw/web/userview/crm/crm_userview_sales/_/UserForm?id=clark&embed=true และ http://localhost:8080/jw/web/userview/crm/crm_userview_sales/_/UserForm?id=clark&embed=true

Byphunsanit

Joget: สร้างรายงาน pdf excel

การสร้างรายงานใน joget ทำได้โดยใช้ Jaspersoft® Studio สร้างรูปแบบรายงาน จากนั้นก็ให้ joget เรียกใช้ jasper libary สร้างรายงานออกมาให้เรา

การกรอกข้อมูล report

  1. สร้าง report ให้เรียบร้อยใน jaspersoft studio
  2. เปิด user view ขึ้นมา กด Add Category ด้านล่าง ขึ้นมาใหม่ คลิก Permission Icon คลิก Hide From Menu จะได้ไม่แสดง ในเมนูให้ผู้ใช้เห็น
  3. ลาก JasperReports มาวางใน Category ของเรา
  4. กรอกข้อมูล
    • Custom ID เป็น id ที่จะอ้างถึงเวลาที่เราต้องการดู report
    • Label เป็นแค่ชื่อที่ทำให้จำ JasperReports ว่าตัวไหนเป็นตัวไหน จะเห็นแค่ใน user view เท่านั้นไม่เกี่ยวกับตอนออกรายงาน ควรตั้งชื่อให้สื่อความหมาย
  5. Jasper Reports Definition (JRXML) คือ code ที่ได้มาจาก jaspersoft studio
  6. คลิก next
  7. Datasource คือ database connection ปกติใช้เป็น Default Datasource
  8. คลิก next
  9. ระบุ parameters ที่ส่งให้ report โดย
    • Name คือ ชื่อ parameter ที่ report ต้องการ
    • Value คือ ค่าที่จะส่งไป ถ้าส่งค่าด้วย url สามารถใช้ hash variable #requestParam. ชื่อ parameter # ได้เลยเช่น #requestParam.member_id#

การเรียกดูรายงาน

จะทำได้โดยเรียก

  • url domain / server ip /: port โดยทั่วไปคือ 8080
  • action=report
  • appId= application id
  • appVersion= version ของ user view
  • key=_&
  • menuId= คือ Custom ID ใน userview นั่นเอง
  • type= จะแสดงเป็นไฟล์ format อะไร มีให้เลือก pdf และ xls
  • userviewId= คือ id ของ userview
  • query string ที่จะส่ง parameter ให้ report เช่น &member_id=xxxxx

ถ้า

  • userview ของเรามี url http://localhost:8080/jw/web/console/app/develop/1/userview/builder/testUserview
  • Custom ID มีค่า profile
  • Parameter ที่ต้องส่งไปคือ member_id

จะเรียกดูรายงานได้จากรูปแบบ http://localhost:8080/jw/web/json/plugin/org.joget.plugin.enterprise.JasperReportsMenu/service?action=report&appId=develop&appVersion=1&key=_&menuId=profile&type=pdf&userviewId=testUserview&member_id=0910097693

Byphunsanit

Joget: แสดงเซ็กชั่นฟอร์มแบบแท็บ

การกำหนดให้แสดง section ของฟอร์มโดยเปลี่ยนค่าใน input เหมือน Joget: กำหนดการแสดงไม่แสดง section ด้วย input มันไม่ค่อยจะเป็นธรรมชาติเท่าไหร่ ผู้ใช้จะคุ้นเคยกับ tabs มากกว่า

ทำได้โดย

  1. ให้ทำตามวิธี Joget: กำหนดการแสดงไม่แสดง section ด้วย input ก่อน
  2. ให้ลาก Custom HTML มาในตำแหน่งที่ต้องการ ใส่ javascript ตามตัวอย่าง
    <ul class="nav nav-tabs" id="tabsA">
    <li class="nav-item">
    <a class="active nav-link show" data-toggle="tab" href="#section1">Section 1</a>
    </li>
    <li class="nav-item">
    <a class="nav-link" data-toggle="tab" href="#section2">Section 2</a>
    </li>
    <li class="nav-item">
    <a class="nav-link" data-toggle="tab" href="#section3">Section 3</a>
    </li>
    </ul>
    <script src="/jw/assets/scripts.js"></script>
    <script>
    $(document).ready(function() {
    
    navSection();
    
    });
    </script>
  3. ไฟล์ javascript ที่เก็บ function แยกเอาไว้ reused ได้หลายๆ ครั้ง
    /*
    pitt phunsanit
    show / hide section with tabs
    version 1
    */
    function navSection() {
    let hash = window.location.hash.substr(1);
    let visibilityControl = $("#visibilityControl");
    let tabsA = $("#tabsA");
    
    if (hash != visibilityControl.val()) {
    $('a[href="#' + hash).click();
    visibilityControl.val(hash);
    }
    
    $("li > a", tabsA).on("click", function() {
    visibilityControl
    .val(
    $(this)
    .attr("href")
    .substr(1)
    )
    .trigger("change");
    });
    }

การแสดงไม่แสดง form section จะเห็นเป็น tabs ธรรมดาๆ ดูเป็นธรรมชาติขึ้นมากกว่าเดิม ตัวอย่างฟอร์ม

{"className":"org.joget.apps.form.model.Form","properties":{"id":"sectionTabs","loadBinder":{"className":"org.joget.apps.form.lib.WorkflowFormBinder"},"tableName":"prototypes","description":"","name":"Section Tabs","storeBinder":{"className":"org.joget.apps.form.lib.WorkflowFormBinder"}},"elements":[{"elements":[{"elements":[{"className":"org.joget.apps.form.lib.HiddenField","properties":{"id":"visibilityControl","workflowVariable":"","value":"section1","useDefaultWhenEmpty":""}},{"className":"org.joget.apps.form.lib.CustomHTML","properties":{"id":"dynamicTabsA","autoPopulate":"","value":"<ul class=\"nav nav-tabs\" id=\"tabsA\">\n    <li class=\"nav-item\">\n        <a class=\"active nav-link show\" data-toggle=\"tab\" href=\"#section1\">Section 1<\/a>\n    <\/li>\n    <li class=\"nav-item\">\n        <a class=\"nav-link\" data-toggle=\"tab\" href=\"#section2\">Section 2<\/a>\n    <\/li>\n    <li class=\"nav-item\">\n        <a class=\"nav-link\" data-toggle=\"tab\" href=\"#section3\">Section 3<\/a>\n    <\/li>\n<\/ul>\n<script src=\"\/jw\/assets\/scripts.js\"><\/script>\n<script>\n    $(document).ready(function() {\n\n        navSection();\n\n    });\n<\/script>","label":""}}],"className":"org.joget.apps.form.model.Column","properties":{"width":"100%"}}],"className":"org.joget.apps.form.model.Section","properties":{"id":"section1","loadBinder":{"className":"","properties":{}},"visibilityControl":"","regex":"","visibilityValue":"","storeBinder":{"className":"","properties":{}},"permission":{"className":"","properties":{}},"label":""}},{"elements":[{"elements":[{"className":"org.joget.apps.form.lib.TextField","properties":{"id":"field1","readonlyLabel":"","workflowVariable":"","maxlength":"","encryption":"","validator":{"className":"","properties":{}},"value":"","label":"Section 1","readonly":"","size":""}}],"className":"org.joget.apps.form.model.Column","properties":{"width":"100%"}}],"className":"org.joget.apps.form.model.Section","properties":{"id":"section1","loadBinder":{"className":"","properties":{}},"visibilityControl":"visibilityControl","regex":"","visibilityValue":"section1","storeBinder":{"className":"","properties":{}},"permission":{"className":"","properties":{}},"label":"Section 1"}},{"elements":[{"elements":[{"className":"org.joget.apps.form.lib.TextField","properties":{"id":"field2","readonlyLabel":"","workflowVariable":"","maxlength":"","encryption":"","validator":{"className":"","properties":{}},"value":"","label":"Section 2","readonly":"","size":""}}],"className":"org.joget.apps.form.model.Column","properties":{"width":"100%"}}],"className":"org.joget.apps.form.model.Section","properties":{"id":"section2","loadBinder":{"className":"","properties":{}},"visibilityControl":"visibilityControl","regex":"","visibilityValue":"section2","storeBinder":{"className":"","properties":{}},"permission":{"className":"","properties":{}},"label":"Section 2"}},{"elements":[{"elements":[{"className":"org.joget.apps.form.lib.TextField","properties":{"id":"field3","readonlyLabel":"","workflowVariable":"","maxlength":"","encryption":"","validator":{"className":"","properties":{}},"value":"","label":"Section 3","readonly":"","size":""}}],"className":"org.joget.apps.form.model.Column","properties":{"width":"100%"}}],"className":"org.joget.apps.form.model.Section","properties":{"id":"section3","loadBinder":{"className":"","properties":{}},"visibilityControl":"visibilityControl","regex":"","visibilityValue":"section3","storeBinder":{"className":"","properties":{}},"permission":{"className":"","properties":{}},"label":"Section 3"}}]}
Byphunsanit

Joget:กำหนดการแสดงไม่แสดง section ด้วย input

joget ได้เตรียมการแสดงฟอร์และไม่แสดงฟอร์มตามเงื่อนไขไว้โดยวิธีที่ง่ายที่สุดคือ แสดง section ตามค่าใน input ที่มี

  1. ในหน้า form builder ให้ลาก Hidden Field หรือ Text Field มาในตำแหน่งที่ต้องการ ตั้งชื่อเช่น visibilityControl
  2. ไปที่ section ที่ต้องการควบคุมการแสดง คลิก Edit Section
  3. คลิก next
  4. คลิก next
  5. กำหนด Visibility Control Rules โดย
    • Join Type เลือก And หรือ Or ตามเงื่อนไขที่ต้องการ
    • Reverse Value ให้ติ๊กถ้าต้องการให้ทำงานเมื่อ มีค่าตรงข้ามกับค่าใน Field
    • Field ID ที่เก็บสถานะ เช่น visibilityControl
    • Field Value ค่าที่ต้องการนำมาเปรียบเที่ยบ
    • Using Regular Expressions? ถ้าใช้ Regular Expressions เปรียบเทียบเช่น 5|8|2525 จะแสดง section เมื่อค่าใน visibilityControl เท่ากับ 5 หรือ 8 หรือ 2525

ทดลองเปลี่ยนค่าของ visibilityControl และสังเกตุความเปลี่ยนแปลงดู

Byphunsanit

Joget: สร้าง Chained select box

บางครั้งก็ต้องสร้างฟอร์มโดยเลือกข้อมูลที่สัมพันธ์กันเช่น ถ้าเค้าตอบมาว่าผู้ชาย คำนำหน้านามของเค้าคงไม่ใช่นางสาว การที่ select box ฉลาดพอที่จะไม่ถามว่า คุณคือนาง หรือ นางสาว ผู้ใช้จะใช้เวลาในการกรอกข้อมูลน้อยลง

ทำได้โดยการสร้าง Chained select box

  1. ในหน้า form builder ให้ลาก Select Box มาในตำแหน่งที่ต้องการ อาจจะอ่าน Joget: สร้าง select box จาก database ถ้ายังไม่เคยสร้างซีเล็คบ๊อกซ์
  2. คลิก Edit icon หลัง input
  3. สร้าง Grouping โดย
    • ถ้าสร้าง options แบบ Options (Hardcoded) ให้ใส่ Grouping โดยมีค่าเท่ากับ ค่าใน parent input
    • ถ้าสร้าง options แบบ JDBC Binder ให้ query โดยมี
      • Column ที่ 1 จะถูกใช้เป็น value ใน แต่ละ option
      • Column ที่ 2 จะเป็น label
      • Column ที่ 3 จะถูกใช้เป็น Grouping ที่จะรวม option ให้เป็นกลุ่ม เป็น Grouping โดยมีค่าเท่ากับ ค่าใน parent input

        SELECT
        id AS value, c_name AS label, c_sex_id AS grouping
        FROM
        app_fd_titles
        ORDER BY label ASC
    • คลิก next
    • คลิก next
    • Field ID to control available options based on Grouping ให้ใส่ id ของ parent input เช่น ใส่ sex_id โดย sex_id เป็น dropdown box ที่มีตัวเลือก ชาย = 2 หญิง = 1 ถ้าต้องการให้ option ไหนแสดงเมื่อ sex_id ถูกเลือกว่าเป็นผู้ชาย (2) ก็ให้ grouping มีค่าเท่ากับ 2

    ดังนั้นค่าในตารางคำนำหน้านาม ควรจะเป็นตามรูปแบบ

    app_fd_titles
    Id label Grouping
    Please select
    1 Miss 1
    2 Mr 2
    3 Mrs 1
    4 Ms 1
    5 Mx 1

    เมื่อ sex_id มีค่าเท่ากับ 1 joget จะแสดง แต่ตัวเลือก Mr เท่านั้น

    Noteแต่ถ้า Grouping ไม่มีค่า จะแสดงออกมาด้วย เหมือนที่แสดงตัวเลือก Please select

    อ่านเพิ่มเติม ส่วนตัว: Joget: สร้าง select box จาก database

Byphunsanit

Joget: สร้าง select box จาก database

การสร้างตัวเลือกใน joget ไม่ควรใช้วิธีกำหนด ตัวเลือกในแต่ละฟอร์ม เพราะว่าถ้ามีการแก้ตัวเลือก จะต้องไปหาว่า dropdown box ตัวนี้มีอยู่ในฟอร์มไหนบ้าง แต่ถ้าเราดึงค่ามาจากดาต้าเบสแค่ไปเพิ่ม / แก้ไขในตารางที่เกี่ยวข้อง เทสซักหน้า ก็เสร็จแล้ว

  1. ในหน้า form builder ให้ลาก Select Box มาในตำแหน่งที่ต้องการ
  2. คลิก Edit icon หลัง input
  3. กรอกข้อมูล
    • ID จะใข้เป็น id ของ input และจะสร้าง column ตามรูปแบบ C_{id} ในตารางที่ผูกกับฟอร์มที่เราวาง input ในดาต้าเบสด้วย
    • Label เป็นฉลากให้กับตัว input
    • Or Choose Options Binder เลือกเป็น JDBC Binder
  4. คลิก next
  5. กรอกข้อมูล
    • Datasource เลือก Default Datasource
    • ติ๊ก Add Empty Option เพื่อที่จะได้ใส่ option ที่ไม่ได้เลือกอะไร ที่ yii จะเรียกว่า prompt นั่นเอง จากนั้นให้กรอก Empty Option Label ที่จะแสดงเป็น label ของ option เช่น Please select
    • SQL SELECT Query ให้กรอก query โดย
      • Column ที่ 1 จะถูกใช้เป็น value ใน แต่ละ option
      • Column ที่ 2 จะเป็น label

      ตัวอย่าง

      SELECT
      id AS value, c_name AS label
      FROM
      app_fd_titles
      ORDER BY c_name ASC

ข้อมูลตัวอย่าง

CREATE TABLE `app_fd_titles` (
`id` int(2) unsigned NOT NULL,
`dateCreated` datetime DEFAULT NULL,
`dateModified` datetime DEFAULT NULL,
`createdBy` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
`createdByName` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
`modifiedBy` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
`modifiedByName` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
`c_name` varchar(255) DEFAULT NULL,
`c_sex_id` int(1) unsigned DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO `app_fd_titles` (`id`,`dateCreated`,`dateModified`,`createdBy`,`createdByName`,`modifiedBy`,`modifiedByName`,`c_name`,`c_sex_id`) VALUES (1,NULL,NULL,NULL,NULL,NULL,NULL,'Miss',1);
INSERT INTO `app_fd_titles` (`id`,`dateCreated`,`dateModified`,`createdBy`,`createdByName`,`modifiedBy`,`modifiedByName`,`c_name`,`c_sex_id`) VALUES (2,NULL,NULL,NULL,NULL,NULL,NULL,'Mr',2);
INSERT INTO `app_fd_titles` (`id`,`dateCreated`,`dateModified`,`createdBy`,`createdByName`,`modifiedBy`,`modifiedByName`,`c_name`,`c_sex_id`) VALUES (3,NULL,NULL,NULL,NULL,NULL,NULL,'Mrs',1);
INSERT INTO `app_fd_titles` (`id`,`dateCreated`,`dateModified`,`createdBy`,`createdByName`,`modifiedBy`,`modifiedByName`,`c_name`,`c_sex_id`) VALUES (4,NULL,NULL,NULL,NULL,NULL,NULL,'Ms',1);
INSERT INTO `app_fd_titles` (`id`,`dateCreated`,`dateModified`,`createdBy`,`createdByName`,`modifiedBy`,`modifiedByName`,`c_name`,`c_sex_id`) VALUES (5,NULL,NULL,NULL,NULL,NULL,NULL,'Mx',1);
Bypitt phunsanit

joget:Form Options Binder

ตัวอย่างการดึงฐานข้อมูลมาแสดงเป็น select box โดยใช้ Bean Shell

  1. ใน Form Binder คลิก selectbox ที่ต้องการ
  2. Or Choose Options Binder เลือกเป็น Bean Shell Form Binder
  3. คลิก next จะเปลี่ยนไปหน้า Edit Select Box > Configure Bean Shell Form Binder > Advanced Options ให้นำ code ไปใส่ไว้
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import javax.sql.DataSource;
    import org.joget.apps.app.service.AppUtil;
    import org.joget.apps.form.model.Element;
    import org.joget.apps.form.model.FormData;
    import org.joget.apps.form.model.FormRow;
    import org.joget.apps.form.model.FormRowSet;
    import org.joget.apps.form.service.FormUtil;
    import org.joget.commons.util.LogUtil;
    
    public FormRowSet load(Element element, String primaryKey, FormData formData) {
    FormRowSet rows = new FormRowSet();
    Connection con = null;
    try {
    /*retrieve connection from the default datasource*/
    DataSource ds = (DataSource) AppUtil.getApplicationContext().getBean("setupDataSource");
    con = ds.getConnection();
    /*execute SQL query*/
    if (!con.isClosed()) {
    String sql = "SELECT PROVINCE_ID AS value, TRIM(PROVINCE_NAME) AS label FROM province ORDER BY PROVINCE_NAME ASC";
    PreparedStatement stmt = con.prepareStatement(sql);
    ResultSet rs = stmt.executeQuery();
    
    FormRow option = new FormRow();
    
    option.setProperty(FormUtil.PROPERTY_LABEL, "please select");
    //option.setProperty(FormUtil.PROPERTY_VALUE, (String) rs.getObject("value").toString());
    
    rows.add(option);
    
    while (rs.next()) {
    FormRow option = new FormRow();
    
    option.setProperty(FormUtil.PROPERTY_LABEL, (String) rs.getObject("label"));
    option.setProperty(FormUtil.PROPERTY_VALUE, (String) rs.getObject("value").toString());
    
    rows.add(option);
    }
    }
    } catch (Exception e) {
    LogUtil.error("Sample app - Form 1", e, "Form Options Binder");
    } finally {
    /*always close the connection after used*/
    try {
    if (con != null) {
    con.close();
    }
    } catch (SQLException e) { /*ignored*/ }
    }
    return rows;
    }
    
    /*call load method with injected variable*/
    return load(element, primaryKey, formData);

การเซ็ต value ของ option บางครั้งต้องแปลง integer เป็น string ด้วยเช่น option.setProperty(FormUtil.PROPERTY_VALUE, (String) rs.getObject(“value”).toString());