Tło

Odebrałem trochę niekompletnej pracy od innego programisty, która obejmuje wyświetlanie wyników wyszukiwania. Jego podejście polegało na renderowaniu wyników w tabeli HTML za pomocą wbudowanego JavaScript i jQuery w następujący sposób.

Grid using table and inline Javascript

Próbuję dokończyć pracę, ale wolałbym pisać mniej kodu i używać jqGrid, ponieważ zawiera funkcje sortowania i uporządkowania kodu. Uzyskanie wyników przez jqGrid jest łatwe, ale umieszczenie przycisków opcji w pustej kolumnie jest trudniejsze niż się spodziewałem.

Wersja jqGrid w aplikacji to 3.7.2. Siatka musi mieć przyciski opcji po lewej stronie, aby wybór był zgodny z resztą aplikacji.

Gdzie utknąłem

Wydaje się, że nie ma sposobu na posiadanie niezwiązanej kolumny w jqGrid. Oznacza to, że każda kolumna wydaje się potrzebować pola w danych źródłowych. Jeśli nie masz fikcyjnego pola, dane wierszy i nagłówki kolumn staną się niewyrównane.

Natknąłem się na przykład (patrz Edycja wierszy -> Edycja niestandardowa), który zwraca JSON z fikcyjnym polem w danych, a następnie modyfikuje dane siatki, aby wstawić przyciski.

Wolę nie umieszczać tam fikcyjnych danych, ponieważ czuje to brudne :) Chciałbym, aby mój JSON zawierał tylko dane potrzebne do reprezentowania wyników wyszukiwania. Pomyślałem więc, że lepiej byłoby zamiast tego dodać atrapę pola w kodzie skryptu, aby zachować czystość kodu po stronie serwera.

Próbuję zmodyfikować dane zwrócone z wywołania AJAX przed renderowaniem przez jqGrid. Próbowałem podłączyć się do zdarzenia loadComplete, ale kiedy modyfikuję dane, wydaje się, że jest to już renderowane.

Próbowałem również podłączyć się do zdarzenia success w polu ajaxGridOptions options, ale wydaje się, że całkowicie zastępuje to zdarzenie, a jqGrid nie renderuje danych.

Jak mogę zmodyfikować dane zwrócone z wywołania usługi sieciowej przed ich wyrenderowaniem przez jqGrid?

1
John Mills 24 czerwiec 2011, 07:25
Co konkretnie robisz z danymi? Jest kilka opcji, ale zależy to od tego, co robisz.
 – 
Michael Dean
24 czerwiec 2011, 07:45
Na jqGrid mam pustą kolumnę, do której wstawiam formanty. Przykład na trirand.com/blog/jqgrid/jqgrid.html (wiersz Edycja -> Edycja niestandardowa) ma atrapę pola w tablicy komórek, w odpowiedzi JSON, ale chcę dynamicznie dodać atrapę pola do odpowiedzi po stronie klienta, zanim jqGrid je zobaczy i nie będzie mieć atrapy pola w wysłanej odpowiedzi od strony serwera.
 – 
John Mills
24 czerwiec 2011, 08:06
Nie ma uniwersalnego sposobu na modyfikację danych zwracanych z serwera przed przetworzeniem danych przez jqGrid, ale jeśli zwrócone dane mają format JSON, można je przekonwertować na inny format wewnątrz jsonReader lub użyj tylko niestandardowego programu formatującego, aby wyświetlić dane w inny sposób. Czy mógłbyś zawrzeć w swoim pytaniu kod JavaScript, który definiuje jqGrid oraz pełne dane JSON zwrócone z serwera? Czy mógłbyś dodatkowo dokładnie opisać, jakie modyfikacje chcesz wprowadzić? Na przykładzie można znaleźć lepsze rozwiązanie.
 – 
Oleg
24 czerwiec 2011, 10:23
- Dopełniam dane, ponieważ jeśli tego nie zrobisz, dane trafią do niewłaściwych kolumn. Przykład, który połączyłem powyżej, robi to za pomocą następującego kodu: while($row = mysql_fetch_array($result,MYSQL_ASSOC)) { $responce->rows[$i]['id']=$row[id]; $responce->rows[$i]['cell']=array("",$row[id],$row[invdate],$row[name],$row[amount],$row[tax],$row[total],$row[note]); $i++; } Zwróć uwagę na "" dodany jako pierwsze pole.
 – 
John Mills
24 czerwiec 2011, 11:55

3 odpowiedzi

Najlepsza odpowiedź

Rozwiązanie w mojej poprzedniej odpowiedzi zepsuło sortowanie, więc wymyśliłem inne rozwiązanie.

Ponieważ jqGrid nie zapewnia podpięć do wygodnej modyfikacji danych, konieczne było cofnięcie poziomu i podpięcie do jQuery. Zamieniłem metodę $.ajax() na własną. Najpierw sprawdza, czy operacja jest inicjowana przez jqGrid, a jeśli tak, dopełnia dane, wywołuje oryginalny program obsługi jqGrid success, a następnie dodaje przyciski opcji do siatki. Sortowanie nadal działa, typ danych to nadal json i nie ma ręcznych wywołań addJSONData i nadal jestem w stanie osiągnąć to, czego potrzebowałem z poprzedniego rozwiązania. Zasadniczo, zrobienie tego małego hacka jQuery pozwala mi obejść się bez robienia jakichkolwiek hacków jqGrid, które są znacznie bardziej kłopotliwe.

// Set up $.ajax() hook for modifying the data before jqGrid receives it
if (!this._ajaxOverridden) {
    var oldAjax = $.ajax;
    $.ajax = function (options) {
        // Check whether this call is from jqGrid to our web service
        if (options.url == config.eventSearchUrl && options.success) {
            // Wrap the success event handler with our own handler that pads the data and creates the radio buttons
            var oldSuccess = options.success;
            options.success = function () {
                thisEventSearchDialog._padData(arguments[0]);
                oldSuccess.apply(this, arguments);
                thisEventSearchDialog._createRadioButtons();
            }
        }
        oldAjax(options);
    };
    this._ajaxOverridden = true;
}
0
John Mills 30 czerwiec 2011, 06:42

Udało mi się wymyślić, jak to zrobić. Zamiast pozwalać jqGrid automatycznie ładować dane, trzeba ręcznie wykonać żądanie, a następnie załadować je za pomocą wywołania addJSONData.

Mój jqGrid jest zdefiniowany w znaczniku w następujący sposób:

<fieldset>            
    <div style="display:none" class="searchResults">
        <table id="eventSearchDialog-results">
        </table>
        <div id="eventSearchDialog-pager">
        </div>
    </div>
</fieldset>

Inicjuję siatkę następującym kodem:

// Initialize the grid
this._searchResults = this._dialog.find("#eventSearchDialog-results");
this._searchResults.jqGrid(
{
    datatype: "local",
    colNames: ['', 'Event Name', 'Event Type', 'Start Date', 'End Date', 'Location', 'Event Country', 'Sports'],
    colModel: [
                { name: 'selector', index: 'selector', width: 30 },
                    { name: 'EventName', index: 'EventName', formatter: jqgridCellFormatter, width: 150 },
                { name: 'EventType', index: 'EventType', formatter: jqgridCellFormatter, width: 120 },
                { name: 'StartDate', index: 'StartDate', formatter: jqgridCellFormatter, width: 100 },
                { name: 'EndDate', index: 'EndDate', formatter: jqgridCellFormatter, width: 100 },
                { name: 'Location', index: 'Location', formatter: jqgridCellFormatter, width: 100 },
                { name: 'EventCountry', index: 'EventCountry', formatter: jqgridCellFormatter, width: 100 },
                { name: 'Sports', index: 'Sports', formatter: jqgridCellFormatter }
                    ],
    rowNum: 10,
    rowList: [10, 20, 30],
    pager: this._dialog.find("#eventSearchDialog-pager"),
    pginput: true,
    sortname: 'EventName',
    viewrecords: true,
    sortorder: "asc",
    hidegrid: false,
    height: "auto",
    shrinkToFit: true,
    width: 630,
    jsonReader:
                    {
                        page: "pageIndex",
                        total: "pageCount",
                        records: "recordCount",
                        root: "rows",
                        repeatitems: true
                    },
    prmNames:
    {
        page: "pageIndex",
        rows: "pageSize",
        sort: "sortField",
        order: "sortOrder"
    }
}
);
// Set the data type to JSON, we don't do this in the options because it will cause a request to occur,
// but we do need it to be set to JSON so that the calls to addJSONData work later.
this._searchResults.jqGrid("setGridParam", { datatype: "json" });

Ładuję siatkę danymi z wywołania jQuery $.ajax(), a w obsłudze zdarzeń success dopełniam dane, a następnie ładuję je do jqGrid za pomocą addJSONData.

Mój JSON wygląda tak:

{
    "pageCount":1,
    "pageIndex":1,
    "recordCount":2,
    "rows":
    [
        {"id":3, "cell":["Stevens Event 2", "Commonwealth Games", "03/05/2011", "16/05/2011", "sersdfweqr", "New Zealand", ["Archery"]]},
        {"id":4, "cell":["Test - multiple sports", "Other", "01/05/2011", "30/06/2011", "Kobe", "Japan", ["Judo", "Karate", "Motor Sport", "Motorcycling", "Taekwondo"]]}
    ]
}

To jest mój program obsługi success:

success: function (data, textStatus, xhr) {
    // Pad data for our radio button column that has no corresponding field in the data
    for (var counter = 0; counter < data.rows.length; counter++) {
        data.rows[counter].cell.splice(0, 0, null);
    }

    thisEventSearchDialog._searchResults[0].addJSONData(data);
    thisEventSearchDialog._createRadioButtons();
},

JqGrid zawierający kolumnę przycisków radiowych, dla których potrzebne były dane fikcyjne. Bez danych fikcyjnych dane wiersza nie pasują do nagłówków. tu wpisz opis obrazu

2
John Mills 27 czerwiec 2011, 03:56
Nie dołączyłeś kodu jqgridCellFormatter, co jest bardzo ważne w Twoim przypadku. Jeśli używasz właściwości repeatitems: true jsonReader, dane dla każdej kolumny powinny być ciągami, a nie tablicą. Jak chcesz wyświetlić kolumnę Sports? Dlaczego nie używasz standardowego programu formatującego date dla kolumn StartDate i StartDate? Uważam, że użycie datatype:'local' i ręczne wywołanie addJSONData jest bardzo złym obejściem. Są lepsze rozwiązania.
 – 
Oleg
24 czerwiec 2011, 17:23
@oleg- Tak więc z obrazu, który umieściłem w odpowiedzi, widać przyciski radiowe, które dodałem. To właśnie staram się osiągnąć. Inny programista ma w aplikacji inne siatki, które wyglądają tak, ale zostały wykonane za pomocą tabel i JavaScript. Dostałem zadanie dokończenia niektórych prac, ale wolę używać jqGrid niż niechlujnych tabel i skryptu wbudowanego. Co sugerujesz, aby jqGrid wyglądał mniej więcej jak obrazek, ale nie używał addJSONData i datatype:'local'?
 – 
John Mills
27 czerwiec 2011, 04:08

To jest stare pytanie i może nie dotyczyć wspomnianej wersji jqGrid (3.7.2), ale wydaje się, że jest z tym związane: Jak "wstępnie przetworzyć" odpowiedź ajax przed wyświetleniem w jqGrid i jeśli mam rację (około są powiązane), to poprawną odpowiedzią jest parametr/funkcja dataFilter parametru ajaxGridOption. U mnie zadziałało.

0
Community 23 maj 2017, 14:52