2016年11月14日 星期一

EasyUI Datagrid 中超連結的編輯問題

這幾天繼續修改 twstockbot 程式, 首先是加寫 trade_records 資料表的部分, 其中我在 inventory 欄位自作聰明地加進超連結, 覺得這樣很方便, 只要按該欄位的 "是", 就透過 ajax 在後端將 "Y" 修改為 "N", 然後重新載入 Datagrid 時就會顯示 "否", 反之亦然.

Datagrid 的顯示內容為超連結在之前測試 EasyUI 的 Datagrid 時有試過, 那時是向外連結到 Yahoo 股市, 單純顯示的話很簡單, 參考下面文章的範例 7-1 與 7-2 :

# jQuery EasyUI 測試 : Datagrid (一)

但是若需要編輯 Datagrid 的紀錄的話, 內容為超連結的欄位會帶來問題, 如下圖所示 :



我覺得這樣很糟糕, 我不能容忍形式上的不完美, 決定去除這個很方便的超連結, 在去除前做一下紀錄, 以便將來在不需要編輯內容的場合要用到點擊超連結這功能時參考.

這個 inventory 欄位的 HTML 部分如下,  就是一個名為 inventory 的 Combobox :

  <div id="trade_records_dialog" class="easyui-dialog" title="新增紀錄" style="width:360px;height:350px;"  data-options="closed:'true',buttons:'#trade_records_buttons'">
    <form id="trade_records_form" style="padding:10px">
      <div style="margin:5px">
        <label style="width:70px;display:inline-block;">股票代號 : </label>
        <input id="stock_id" name="stock_id" class="easyui-combobox" data-options="missingMessage:'此欄位為必填',required:true">
      </div>
      <div style="margin:5px">
        <label style="width:70px;display:inline-block;">買進價格 : </label>
        <input name="buy_price" class="easyui-numberbox" data-options="missingMessage:'此欄位為必填',required:true" style="width:100px;">
      </div>
      <div style="margin:5px">
        <label style="width:70px;display:inline-block;">買進股數 : </label>
        <input name="shares" class="easyui-numberbox" data-options="missingMessage:'此欄位為必填',required:true" value="1000" style="width:100px;">
      </div>
      <div style="margin:5px">
        <label style="width:70px;display:inline-block;">買進日期 : </label>
        <input name="buy_date" id="buy_date" type="text" data-options="missingMessage:'此欄位為必填',required:true">
      </div>
      <div style="margin:5px">
        <label style="width:70px;display:inline-block;">庫存中 : </label>
        <select name="inventory" class="easyui-combobox" data-options="panelHeight:'auto',missingMessage:'此欄位為必填',required:true" style="width:60px;">
          <option value="Y">是</option>
          <option value="N">否</option>
        </select>
      </div>

      <div style="margin:5px">
        <label style="width:70px;display:inline-block;">賣出日期 : </label>
        <input name="sell_date" id="sell_date" type="text" data-options="">
      </div>
      <div style="margin:5px">
        <label style="width:70px;display:inline-block;">賣出價格 : </label>
        <input name="sell_price" class="easyui-numberbox" data-options="" style="width:100px;">
      </div>
      <div style="margin:5px">
        <label style="width:70px;display:inline-block;">持有人 : </label>
        <select id="stock_owner" name="stock_owner" class="easyui-combobox" style="width:140px;" data-options="panelHeight:'auto',
        url:'./apps/STOCK.php?op=get_users',
        valueField:'name',
        textField:'name'
        ">
        </select>
        <input type="hidden" id="op" value="">
        <input type="hidden" id="id" value="">
      </div>
      <div style="margin:5px">
        <label style="width:70px;display:inline-block;">備註 : </label>
        <input name="remark" type="text" class="easyui-textbox" style="width:230px">
      </div>
    </form>
  </div>
  <div id="trade_records_buttons" style="padding-right:15px;">
    <a href="#" id="clear_trade_record" class="easyui-linkbutton" iconCls="icon-clear" style="width:90px">重設</a>
    <a href="#" id="cancel_trade_record" class="easyui-linkbutton" iconCls="icon-cancel" style="width:90px">取消</a>
    <a href="#" id="save_trade_record" class="easyui-linkbutton" iconCls="icon-ok" style="width:90px">確定</a>
  </div>
</div>

關於下拉式選單 ComboBox 的用法參考 :

# Easyui 測試 : Combobox 下拉式選單

而 EasyUI 的 Datagrid 設定如下 :

    $('#trade_records').datagrid({
      columns:[[
        {field:'id',title:'id',sortable:true},
        {field:'stock_id',title:'股號',sortable:true},
        {field:'stock_name',title:'公司'},
        {field:'buy_date',title:'買進日',sortable:true},
        {field:'buy_price',title:'買進價',sortable:true},
        {field:'shares',title:'買進股數',sortable:true},
        {field:'close',title:'收盤價'},
        {field:'book_profit',title:'帳面損益(%)'},
        {field:'inventory',title:'庫存中',sortable:true},
        {field:'sell_price',title:'賣出價',sortable:true},
        {field:'sell_date',title:'賣出日',sortable:true},
        {field:'realized_profit',title:'實現損益(%)'},      
        {field:'stock_owner',title:'持有人',sortable:true}
        ]],
      url:"apps/STOCK.php",
      queryParams:{op:"list_trade_records"},
      method:"post",
      fitColumns:true,
      singleSelect:true,
      pagination:true,
      pageSize:10,
      rownumbers:true
      });

此處收盤價是查詢 stocks_list 表得來的, 兩個損益是計算而來的, 都不在 trade_records資料表中, 都無法在 Datagrid 中參與排序, 因此 sortable 不能設為 true. 

在 op=list_trade_records 程式段落中, 我餵給 Datagrid 中此欄位的是一個超連結 :

        if ($RS[$i]["inventory"]=="N") {
          $inventory="<a href='#' onclick='change_inventory(".
                     '"'.$RS[$i]["id"].'","Y")'."')>否</a>";
          }
        else {
          $inventory="<a href='#' onclick='change_inventory(".
                     '"'.$RS[$i]["id"].'","N")'."')>是</a>";
          }

注意這裡因為要避免標籤屬性值與字串的括號的衝突, 我交互使用了單引號與雙引號, 當然也可以用跳脫字元, 但我很討厭一堆跳脫字元擠在一起的感覺. 超連結的 click 動作處理函數是一個 change_inventory() 函數, 需要傳遞此交易紀錄的 id 與想要改變的狀態值給它, 例如現在是 "否", 那就要傳按下超連結時希望改為 "是" 的 "Y" 給它. 此函數位於 op=trade_records 程式區塊內的最上層 (不是在 jQuery 物件內) :

  function change_inventory(id, inventory){
    $(function(){
      var url="./apps/STOCK.php?op=change_inventory&id=" + id +
              "&inventory=" + inventory;
      $.get(url, function(){
        $("#trade_records").datagrid("reload",{op:"list_trade_records"});
        });
      });
    }

此函數使用 ajax 的 get 方法要求後端執行 op=change_inventory 這個區塊, 完成後重新載入 Datagrid 內容. 這個區塊的內容如下 :

  case "change_inventory" : {
    $id=$_REQUEST["id"];
    $data_array["inventory"]=$_REQUEST["inventory"];
    $result=update("trade_records", $data_array, "id", $id);
    if ($result===TRUE) {
      $status="success";
      $msg="ok";
      }
    else {
      $status="failure";
      $msg="資料更新錯誤!";
      }
    $arr["status"]=$status;
    $arr["msg"]=$msg;
    echo json_encode($arr);
    break;
    }

亦即它只是將 inventory 這個欄位的值從 "Y" 改為 "N" 或 "N" 改為 "Y" 而已. 由於 EasyUI 表單 的 load 方法一定會將 Datagrid 中被編輯的那一列內容載入到表單元素中, 對於 ComboBox 而言, 應該是會載入到 option 元素的 value 屬性中, 於是造成上面那張圖中的怪異現象, 似乎破壞了 HTML 的格式正規性 :

    $("#edit_trade_record").bind("click",function(){
      var row=$("#trade_records").datagrid("getSelected");
      if (row) {
        $("#trade_records_dialog").dialog("open").dialog("setTitle","編輯交易紀錄");
        $("#trade_records_form").form("load",row);
        $("#op").val("update_trade_record");
        $("#id").val(row.id); //edit 需要傳送 id
        }
      else {$.messager.alert("訊息","請選擇要編輯的交易紀錄!","info");}
      });

因為之前沒有實作過這種功能, 記下來以後可能用得到.

2016-11-15 補充 :

下一步 :
加入買入本益比與賣出本益比欄位.
加入總資產資料表 : 保險, 股票, 投資型保單等

2016-11-16 補充 :

今天想測試看看是否 EasyUI 已解決 FireFox 在 ComboBox 無法搜尋中文問題, 將 index.php 與 main.php 各製作了cdn 版與 local 版, 亦即根目錄下多了 index_local.php, index_cdn.php, main_local.php, main_cdn.php 四個檔案, 其中 local 匯入本地自備的 jQuery 與 EasyUI 函式庫; 而 cdn 則匯入 EasyUI 官網最新的 CDN 來源. 要切換時就複製 local 或 cdn 檔去覆蓋 index.php 與 main.php 即可. CDN 環境配置參考 :

jQuery EasyUI 環境配置

使用最新的 CDN 測試結果一樣, 在 FireFox 使用 ComboBox 時仍然因為無法送出中文的 q 參數而無法做中文搜尋, 參考 :

Easyui 測試 : Combobox 下拉式選單


沒有留言 :