3

这是一个我认为很常见的问题(或设计模式?),所以我希望这篇文章可以帮助其他有类似问题的人......

我有一种很常见的情况,即复杂的表单需要动态地允许用户编辑取决于用户做出的其他选择的数据。我使用 Ajax、jQuery 和 PHP 和 postgres 作为后端数据库。

我已经弄清楚了如何使用 jQuery Ajax 技术根据用户选择的两个值返回单个记录的数据(Ajax 比 php 更漂亮);通常返回值将是我的 HTML 表单可以处理的一条记录。但有时返回值会是两三条记录。在这种情况下,我需要动态添加输入字段并使用返回的数据填充它们。

这是我表格中的代码;Fetch 按钮使用 Selected Marker 值和 Selected LabID 值来查找相关记录,其中包含 Allele_1、Allele_2 和运行日期:

<fieldset>
      <LEGEND><b>Edit Genotype</b></LEGEND>
      <p>
    <boldlabel>Selected Marker</boldlabel><input name=sel_marker length=15 DISABLED>
    <boldlabel>Selected LabID</boldlabel><input name=sel_labid length=10 DISABLED><br>
    <boldlabel>Allele_1</boldlabel><input id=allele1 name=allele_1 size=5 >
    <boldlabel>Allele_2</boldlabel><input id=allele2 name=allele_2 size=5 >
    <boldlabel>Run date</boldlabel><input id=run_date name=run_date size=10 >
    <br>
      </p>              
    <input type="button" name="fetch" id="fetchbutton" value="Fetch" sclass="btn">
    <input type="button" name="save"  value="Save" onclick="savegenotype()" class="btn">
    <br>
    </fieldset>

这是链接到 Fetch 按钮的 javascript 代码:

  function fetchgenotype() {
    // here's where we use an Ajax function to fetch the allele values without reloading the page.
    // Get the index number of the genotype record to retrieve; retrieve it; populate the alleles.

    var mndx = document.EditGenotype.marker.options[document.EditGenotype.marker.selectedIndex].value;
    var sndx = document.EditGenotype.labid.options[document.EditGenotype.labid.selectedIndex].value;

    $.post("fetchAlleles.php", {mndx: mndx, sndx: sndx},
    function(result) {        
      i=0;
      result.each(
        a1='allele1_'||i.toString();
        a2='allele2_'||i.toString();
        r='rundate_'||i.toString();

        $("#run_date").after(a1);
        $("#run_date").after(a2);
        $("#run_date").after(r);
      )
    }, "json");

    return false;
  }

这是单独的 PHP 脚本,它是查找相关数据的 Ajax 部分:

   // query the database.
    $dbconnect = pg_pconnect("host=".$hostname." user=".$dbuser." dbname=".$dbname);    
    if (!$dbconnect)    {
        showerror(0,"Failed to connect to database",'fetchAlleles',16,"username=".$dbuser.", dbname=".$dbname);
        exit;
    }
    $sql = "SELECT allele1, allele2, run_date FROM geno.genotypes WHERE markers_id=".$mndx." AND gsamples_id=".$sndx;

    $fetchresult = pg_exec($dbconnect, $sql);
    if ($fetchresult) {
        $arr = pg_fetch_array($fetchresult, 0, PGSQL_NUM);
        // for debugging
        //print_r($arr);
    } else {
        echo "(25) Failed to retrieve results.<BR>SQL: ".$sql."</br>";
    }

    // It appears necessary to return the array as json encapsulated.
    echo json_encode($arr);
?>
}

我知道,这部分适用于单值情况;但是当返回值是多个记录的数组时,我的表单的 javascript 部分中的 jQuery 代码的语法不正确。我在 a1='allele1_'||i.toString(); 行中遇到错误

任何可以让我直截了当的 jQuery 大师都将不胜感激......

4

1 回答 1

2

我的第一个想法:使用pg_affected_rows找出你是否有一个或多个记录。

我的第二个想法:为什么不pg_fetch_object?我认为你会得到更好(可读)的json。

我的第三个想法:你应该统一 JSON 输出。很常见的做法是 - JSON 响应应该看起来像一个对象数组。如果 DB 只返回一条记录 -> JSON-response 是一个数组,其中只有一个项目。如果 DB 返回多个 -> JSON-response 是一个包含多个项目的数组

JSON 响应示例

//DB return only ONE record
    {
      "items": [
            { 
                "allele1" : "the-value",
                "allele2" : "the-value",
                "run_date" : "the-date"
            }
        ],
      "totalItems : 1
    }

//DB returns more than one records
{
  "items": [
        { 
            "allele1" : "the-value_1",
            "allele2" : "the-value_1",
            "run_date" : "the-date_1"
        },
        { 
            "allele1" : "the-value_2",
            "allele2" : "the-value_2",
            "run_date" : "the-date_2"
        },
        ...
        { 
            "allele1" : "the-value_n",
            "allele2" : "the-value_n",
            "run_date" : "the-date_n"
        }
    ],
  "totalItems : n
}

如果你得到这样的结果,你可以更容易地动态创建输入字段。首先,您可以轻松检查是否收到了一条或多条记录

if(response.totalItems === 1 ) {
    // handle single record
}else if (response.totalItems > 1) {
    // handle multiple records
}

如果有多个记录,您可以使用 jQuery.each() 和 jQuery.map() 进行迭代并生成输入字段

if (response.totalItems > 0) {
    //iterate through all items in JSON-response
    $.each(response.items, function(index, object) {
        // create FIELDSET element
        var $fieldset = $('<fieldset>', {'html' : '<legend>#'+(index+1)+'</legend>'});

        $.map(object, function(value ,key) {
           //create LABEL element and appendInto FIELDSET
           $fieldset.append($('<label>', {'text' : key, 'for' : key}));
           //create INPUT element and appendInto FIELDSET
           $fieldset.append($('<input>', {'id': key, 'name': key, 'value' : value}));
           //create LineBreak
          $fieldset.append('<br />');
        });
        // Append whole FIELDSET with LABEL, INPUT and BR to body (or whatever your placeholder is)
        $('body').append($fieldset);
   });
}
于 2012-05-03T01:40:08.703 回答