jQuery – jqGrid – comportamento indesiderato in onSelectRow evento

Ho avuto un precedente domanda di pulsanti disponibili in ogni riga di una jqGrid, che si attivano quando la riga è stata selezionata. Con l’aiuto di @Oleg sono stato in grado di farlo funzionare come dovrebbe.

In ulteriori test, tuttavia, ho identificato un comportamento indesiderato che onSelectRow evento. Quello che ho trovato è che se ho una tabella con 3 righe, e cliccare sulla riga 2 (che attiva i pulsanti), quindi (senza mouse sulla riga 2 pulsanti) fare clic sulla riga 3 (che disattiva la riga 2 pulsanti & attiva la riga 3 pulsanti), e cambiare la mia mente di nuovo & fare clic su riga 1 o 2 (non importa), e a CHE punto quindi fare clic sul "Re-Send" (submit) pulsante quello che succede è che la riga selezionata viene poi re-inviato 3 volte separati.

Seguenti sono i timestamp da 4 righe scritte da 1 “rispedire” fare clic su ieri.

2013-05-28 16:49:04.817
2013-05-28 16:49:04.653
2013-05-28 16:49:04.560
2013-05-28 16:49:04.467

Ho messo qualche registrazione nella pagina & confermato che si fa chiamare il POST 4 volte, una volta per ogni click su una riga della griglia.

Le seguenti sezioni contengono la maggior parte delle configurazioni/impostazioni ho attualmente in cui il jqGrid viene costruita.

colNames: ["Destination", "Message Text", "Send Time","Message Action"],
colModel:[
    {name:"Destination",index:"Destination",width:col1width,align:"left", xmlmap:"Rowset>Row>Destination",sortable:false},
    {name:"MessageText",index:"MessageText",width:col2width,align:"left",xmlmap:"Rowset>Row>MessageText",sortable:false},
    {name:"SendTime",index:"SendTime",width:col3width,align:"center",formatter:"date",formatoptions: {"srcformat":"ISO8601Long", "newformat":"Y-m-d H:i:s"},xmlmap:"Rowset>Row>SendTime",sortable:false},
    {name: "msgAct",
    width: col4width,
    align: "center",
    formatter: function() {
        return "<input name='resendMsg' style='height:25px;width:65px;' type='submit' value='Re-Send' disabled='disabled' />" +
               "<input name='cancelMsg' style='height:25px;width:55px;' type='submit' value='Cancel' disabled='disabled' />" 
            }}
    ],
viewrecords: true,
caption: capMsg,
rownum: 0,
height: "100%",
width: gridwidth,
toolbar: [true, "top"],
pager: jQuery("#pager1"),
sortname: "SendTime",
hidegrid: false,                //hides the ability to collapse grid
defaults: {
    altrows: true, 
    recordtext: "View {0} - {1} of {2}",
    emptyrecords:  "No records to view",
    loadonce: true,
    pgtext: "Page  {0} of {1}"
    },

È il seguente onSelectRow evento.

onSelectRow:  function(id) {
    var tr = $(this).jqGrid("getInd",id,true);
    var gridRow = $(this).jqGrid("getRowData",id);
    var srow = $(this).jqGrid("getGridParam","selrow");
    //disable all resendMsg & cancelMsg buttons in the grid
    $(this).find("input[name=resendMsg]").attr("disabled","disabled");
    $(this).find("input[name=cancelMsg]").attr("disabled", "disabled");
    //now enable the buttons for the current row only
    $(tr).find("input[name=resendMsg]").removeAttr("disabled");
    $(tr).find("input[name=cancelMsg]").removeAttr("disabled");
    //disable dropdowns & sendMsg submit button
    //catch the Cancel button click
    $(tr).find("input[name=cancelMsg]").click(function() {
        //disable all resendMsg & cancelMsg buttons in the grid
        $(this).find("input[name=resendMsg]").attr("disabled","disabled");
        $(this).find("input[name=cancelMsg]").attr("disabled", "disabled");
        //enable the dropdowns & clear the selection, reload grid
        ReloadGrid();
        });
    //catch the Re-Send button click
    $(tr).find("input[name=resendMsg]").click(function() {
        ReSendMessage(gridRow.Destination, gridRow.MessageText);
        //disable all resendMsg & cancelMsg buttons in the grid
        $(this).find("input[name=resendMsg]").attr("disabled","disabled");
        $(this).find("input[name=cancelMsg]").attr("disabled", "disabled");
        //enable the dropdowns, clear the selection and exit
        $("#myGrid").jqGrid("resetSelection");
        });
    },

e il resto del jqGrid codice:

gridview: true,
xmlReader:  { 
    root: "Rowsets", 
            row: "Row",
    repeatitems: false,
    id: "SendTime"
    },
loadComplete: function() { 
    //increase row height
    $("td",".jqgrow").height(40);            //data grid rows
     //alternate background of every other row
    $("tr.jqgrow:odd").css({"background-color": "#DDDDDC", "background-image": "none"});
    $("th.ui-th-column").css("font-weight","bold");
    }
});

È come il onSelectRow evento è accumulare il numero di click & poi, chiamando l’evento click funzioni, tuttavia molte volte di fila è stato selezionato, ma un pulsante non è stato cliccato.

Ho testato, però, che se clicco su una riga e quindi fare clic su uno dei pulsanti di invio, che processi come previsto (un “Re-Send” presenta la riga 1 volta, e un “Cancel” cancella la selezione & non altro).

Non so se è possibile, ma si può impedire ad un successivo onSelectRow da sparo se una riga è già selezionata? Si può cancellare la selezione precedente (o reset) per evitare che il onSelectRow (e l’evento click per il pulsante) sparando più volte?

Apprezzerei qualsiasi pensieri, commenti o suggerimenti su come correggere questo comportamento.

MODIFICA

Incluso il codice per beforeSelectRow come indicato in una risposta qui sotto.

$("#myGrid").bind("jqGridBeforeSelectRow", function(e, id, eventOriginal) {
    var gsr = $("#myGrid").jqGrid("getGridParam","selrow");
    console.log(" ****  beforeSelectRow - (before if) lastSel = " + lastSel + "  id = " + id + "   gsr = " + gsr);
    if (id && id !== lastSel) {
        console.log("id && id !== lastSel");
        console.log("   id = " + id +  "    lastSel = " + lastSel);
        };
    if (id !== lastSel) {
        if (lastSel == -1) {   //first time thru
            lastSel = id;
            console.log(" ****  beforeSelectRow - first time thru - new val = " + lastSel + "  gsr = " + gsr);
            return true;
            }
          else {
            console.log(" ****  beforeSelectRow - lastSel - " + lastSel + "   <>  id = "  +id + "    gsr = " + gsr);
            return false;
            }
        }
    else {
        console.log(" ****  beforeSelectRow - otherwise they matched -  lastSel  = " + lastSel + "     id = " + id + "  gsr = " + gsr);
        return true;
        }
    });

Dopo aver spostato il .click evento dal onSelectRow in loadComplete (per il pulsante Annulla come test), ho provato il codice di cui sopra, sia all’interno che all’ & al di fuori del codice per la griglia. Si esegue la stessa in entrambi i modi.

Il problema è che il Cancel pulsante dovrebbe resettare la selezione $("#myGrid").resetSelection(); e ricaricare la griglia. Il codice viene eseguito & non dà un errore, ma la prossima volta beforeSelectRow incendi (quando la griglia viene ricaricato), l’id è sempre lo stesso come lo era quando beforeSelectRow e onSelectRow licenziato quando ho cliccato sulla riga, il che significa che non riesco mai a selezionare una nuova riga fino a quando l’intera pagina viene ricaricata. Solo al caricamento della pagina, è quando beforeSelectRow non fuoco.

MODIFICA

Seguito è riportato il codice per il pulsante Annulla, che si trova ora all’interno del loadComplete evento.

//catch the Cancel button click
$(this).find("input[name=cancelMsg]").click(function() {
    //disable all resendMsg & cancelMsg buttons in the grid
    $(this).find("input[name=resendMsg]").attr("disabled","disabled");
    $(this).find("input[name=cancelMsg]").attr("disabled", "disabled");
    //enable the dropdowns & clear the selection, reload grid
    console.log("ReloadGrid (inside Cancel function) ");
    lastSel = -1;
    $("#myGrid").trigger("reloadGrid");
InformationsquelleAutor steve_o | 2013-05-29



One Reply
  1. 2

    È sbagliato pulsante di collegamento (per usare .click) all’interno di onSelectRow richiamata.

    Invece è possibile spostare il codice per la registrazione di click gestore di eventi all’interno di loadComplete. Si può solo spostare il codice da onSelectRow per loadComplete e sostituire $(tr) per $(this) per la ricerca all’interno di tutti pulsanti di rete e non solo i tasti della riga selezionata. È comunque possibile impostare o rimuovere disabled di un attributo all’interno di onSelectRow richiamata.

    Più sarebbe meglio fare nessun individuo associazione per ogni pulsante. Uno può semplicemente utilizzare onCellSelect o beforeSelectRow che sarà chiamato da click gestore associato tutta griglia. Vedere la risposta e questo per esempi di codice.

    AGGIORNATO: io non sono sicuro che ho capito bene il tuo problema, ma spero che la demo dimostrerà la soluzione del problema. Non ho usato alcun esplicito click gestore. Il cambiamento più importante (che potrebbe importante se si utilizza Internet Explorer) è aggiunta class='cbox' al formattatore per evitare return in la linea di jqGrid codice. La parte più importante del codice è sotto

    colModel: [
        { name: "text", width: 500 },
        { name: "msgAct", width: 150,
            formatter: function () {
                return "<input name='resendMsg' class='cbox' style='height:25px;width:65px;' type='submit' value='Re-Send' disabled='disabled'/>" +
                    "<input name='cancelMsg'  class='cbox' style='height:25px;width:55px;' type='submit' value='Cancel' disabled='disabled'/>"
            }}
    ],
    onSelectRow: function (rowid) {
        var tr = $(this).jqGrid("getInd", rowid, true);
        $(this).find("input[name=resendMsg],input[name=cancelMsg]").attr("disabled", "disabled");
        $(tr).find("input[name=resendMsg],input[name=cancelMsg]").removeAttr("disabled");
    },
    beforeSelectRow: function (rowid, e) {
        var $self = $(this),
            $td = $(e.target).closest("td"),
            iCol = $.jgrid.getCellIndex($td[0]),
            name = $(e.target).attr("name");
        if (this.p.colModel[iCol].name === "msgAct") {
            if (name === "resendMsg") {
                alert("'Re-Send' button clicked in the row with id=" + rowid +
                    "\ntext in the row =\"" + $self.jqGrid("getCell", rowid, "text") + "\"");
            } else if (name === "cancelMsg") {
                alert("'Cancel' button clicked in the row with id=" + rowid);
                setTimeout(function () {
                    $self.trigger("reloadGrid");
                }, 50);
            }
        }
        return true;
    }

    È possibile sostituire gli avvisi all’interno di beforeSelectRow per l’azione di cui avete bisogno.

    • Spostando il .click in loadComplete contribuito a hanno chiamato solo una volta. Tuttavia, ho notato che il rowID è ancora il valore di ciò che è stato, e non è il ripristino, anche se sto chiamando $("#myGrid").ResetSelection(); dall’interno del .click gestore di eventi che si trasferì nel loadComplete. Che significa che se ho 3 righe visualizzate & selezionare la riga 3, quindi premere il pulsante annulla sulla riga, il beforeSelectRow ha ancora la riga 3 id it & a meno che non mi ricarica la pagina, non riesco mai a selezionare qualsiasi altra riga fino a quando la pagina viene ricaricata. Ho incluso il beforeSelectRow codice di cui sopra.
    • Hai scritto a proposito di problemi con “ricarica la griglia” all’interno di beforeSelectRow, ma il codice che hai posato non contengono alcun trigger reloadGrid. Si potrebbe includere il codice che mostra come farlo? Si chiama trigger reloadGrid all’interno di setTimeout? Fare un reset variabili come lastSel prima di ricaricare? Non capisco alcune parti del codice che hai postato. Perché è l’accesso selrow all’interno di jqGridBeforeSelectRow invece di utilizzo id parametro?
    • Aggiunto il codice di cui sopra. Per rispondere alle tue domande: non si chiama trigger reloadGrid all’interno di setTimeout. Variabile lastSel è impostato a -1 all’interno di Annullare l’evento click. Il selrow all’interno del jqGridBeforeSelectRow è utilizzato nel console.log dichiarazioni. Mi è stato di visualizzazione id in beforeSelectRow e si poteva vedere che non era in fase di reset – selrow di visualizzazione per mostrare che me la riga selezionata, avevano infatti stato resettato. Io non sono sicuro di come la id mai si resetta.
    • A AGGIORNAMENTO parte della mia risposta e demo.
    • Grazie per l’aiuto. Io l’ho preso a lavorare in una certa misura. Tuttavia, quello che ho notato è che onSelectRow si attiva ogni volta che la griglia carichi dopo il primo tempo. Ho preso il tuo suggerimento & spostato il pulsante azioni in beforeSelectRow. Una parte del codice che ho omesso è stata la disattivazione caselle a discesa nella onSelectRow. Dal momento che (dopo la prima volta) onSelectRow si attiva ogni volta che non sono mai stati ri-attivato, come la griglia). Dal onSelectRow incendi, penso che ho bisogno di rilevare selected anche. Pensieri? Grazie ancora per TUTTI del vostro aiuto!
    • Forse ho risolto il problema. A meno che non ci sia un modo migliore di farlo, ho messo il codice per attivare tutto spento nel onSelectRow dentro il reinvio/annulla if dichiarazioni in beforeSelectRow. Lì, mi piacerebbe ri-abilitare qualcosa precedentemente disattivato, e disabilitare tutto ciò che è attualmente abilitato, resettare la selezione e quindi ricaricare la griglia. Dopo di che (ancora all’interno del if resend o if cancel) vorrei tornare false da beforeSelectRow. Non è finito il test, ma sembra fare quello che sto chiedendo. Grazie ancora per il vostro aiuto!!
    • Sei il benvenuto! Scusate, ma si può vedere su demo che non onSelectRow sarà licenziato dal caricamento della griglia. Se si ha l’effetto che si dovrebbe esaminare il vostro codice in cui è possibile selezionare in modo esplicito alcuni riga.
    • – il codice demo è in realtà ciò che mi ha aiutato a capire come risolvere il problema. Ho messo un messaggio di log in entrambi onSelectRow e beforeSelectRow per vedere cosa stava succedendo. Al caricamento della pagina, non onSelectRow licenziato. Tuttavia, una volta che ho selezionato una riga, non importa se mi ha colpito Re-Send o CancelonSelectRow sarebbe sempre il fuoco. Quello che ho fatto è stato quando Re-Send o Cancel pulsante è stato gestito in beforeSelectRow era in cui ho fatto il ricaricamento della griglia, & la fece ritorno FALSE. In caso contrario, beforeSelectRow sarebbe tornato TRUE. Grazie ancora!
    • Sei il benvenuto!

Lascia un commento