jqGrid Free - Возможность загрузки/сохранения состояния в виде кнопок

Я использовал этот пост в качестве основы для моего кода, позволяющего сохранить состояние сетки, нажав кнопку "Сохранить", и загрузить, нажав кнопку "Загрузить".

У меня это почти работает, поскольку оно сохраняет и повторно загружает любые данные фильтра, однако, если я изменяю порядок или видимость каких-либо столбцов, эти изменения не сохраняются при нажатии кнопки сохранения.

Я не понимаю этот комментарий в исходном коде

// идентификатор текстового ввода filterToolbar: "gs_" + colModel.name

if(col_arr[i].search && $("#gs_" + col_arr[i].name).val().length) { toolbar_search_array.push({ name: col_arr[i].name, value: $("#gs_" + col_arr[i].name).val() }); }

В результате я получаю сообщение об ошибке консоли при нажатии кнопки «Сохранить». Если я прокомментирую этот раздел, я смогу сохранить критерии фильтра без порядка столбцов и видимости.

Ниже приведен рабочий пример моего кода.

$(function() {
 "use strict";
    $.jgrid.defaults.guiStyle = "bootstrap";
    $.jgrid.defaults.iconSet = "fontAwesome";
    var template1 = {
        "groupOp": "AND",
        "rules": [{
            "field": "r",
            "op": "eq",
            "data": "YES"
        }]
    };

    var template2 = {
        "groupOp": "AND",
        "rules": [{
            "field": "hz",
            "op": "eq",
            "data": "YES"
        }]
    };
	
		 var mygrid = jQuery("#jqGrid").jqGrid({
				url: 'https://dl.dropboxusercontent.com/s/nh7rcwcimxljjr2/data.json',
				datatype: "json",
				cmTemplate: {
					autoResizable: false,
					align: "center",
				    searchoptions: {
				        searchOperMenu: true,
				        sopt: ["bw" ,"eq", "ne" , "lt", "le" ,"gt" ,"ge" , "bn" ,"in" ,"ni" ,"ew" ,"en" ,"cn" ,"nc" ,"nu" ,"nn"]
				    }
				},
				colModel: [{
            label: 'Position',
            name: 'p',
            width: 100
        }, {
            label: 'Equipment Nbr',
            key: true, // ??? only if e is unique in the input data
            name: 'e'
        }, {
            label: 'Length',
            name: 'l',
            width: 95
        }, {
            label: 'Height',
            name: 'ch',
            width: 90
        }, {
            label: 'ISO Code',
            name: 'i',
            width: 110
        }, {
            label: 'Carrier',
            name: 'c',
            width: 95
        }, {
            label: 'Bay',
            name: 'ba',
            width: 75
        }, {
            label: 'Row',
            name: 'ro',
            width: 75
        }, {
            label: 'Tier',
            name: 'ti',
            width: 75
        }, {
            label: 'Type',
            name: 'ty',
            width: 90
        }, {
            label: 'Status',
            name: 's',
            width: 90
        }, {
            label: 'Bundle?',
            name: 'b',
            width: 100
        }, {
            label: 'Attached Nbr',
            name: 'a',
        }, {
            label: 'Pos Format',
            name: 'pf',
            width: 125
        }, {
            label: 'VGM',
            name: 'wv',
            width: 100
        }, {
            label: 'Weight',
            name: 'w',
            width: 100
        }, {
            label: 'OOG',
            name: 'o',
            width: 75
        }, {
            label: 'Dimensions',
            name: 'dn',
            width: 200
        }, {
            label: 'Hazardous',
            name: 'hz',
            width: 120
        }, {
            label: 'IMDG Code',
            name: 'im',
            width: 125
        }, {
            label: 'UN Number',
            name: 'un',
            width: 125
        }, {
            label: 'Reefer',
            name: 'r',
            width: 90
        }, {
            label: 'Temp',
            name: 'tp',
        }, {
            label: 'Range',
            name: 'ra',
            width: 130
        }, {
            label: 'Description',
            name: 'd',
            width: 125
        }, {
            label: 'Handling',
            name: 'h',
            width: 125
        }, {
            label: 'Load Remarks',
            name: 'lr',
            width: 140
        }, {
            label: 'POL',
            name: 'pl',
            width: 80
        }, {
            label: 'POD',
            name: 'pd',
            width: 80
        }, {
            label: 'Optional POD',
            name: 'op',
            width: 140
        }, {
            label: 'Destination',
            name: 'de',
            width: 125
        }, {
            label: '1st POD',
            name: 'p1',
            width: 110
        }, {
            label: '2nd POD',
            name: 'p2',
            width: 110
        }, {
            label: '3rd POD',
            name: 'p3',
            width: 110
        }, {
            label: '4th POD',
            name: 'p4',
            width: 110
        }, {
            label: '5th POD',
            name: 'p5',
            width: 110
        }, {
            label: 'Transhipment Port',
            name: 'pt',
            width: 175
        }, {
            label: 'Next POD',
            name: 'np',
            width: 115
        }, {
            label: 'Ref Code',
            name: 'rc',
            width: 110
        }, {
            label: 'Ref',
            name: 'ref',
            width: 80
        }],
	
				viewrecords: true, 
        autowidth: true,
        sortable: true,
        height: 400,
        rowNum: 17,
        shrinkToFit: false,
        autoresizeOnLoad: false,
        loadonce: true,
				colMenu : true,
        sortname: 'p',
        hoverrows: true,
        iconSet: "fontAwesome",
				rowNum: 250,
				autoResizing: { compact: true },
				rowList: [250, 1000, 2500, "10000:All"],
        rownumbers: true,
    		rownumWidth: 60,
        multiselect: true,
        multiPageSelection: true,
        pager: true,
        groupingView: {
            groupOrder: ["desc"],
            groupText: ["<b>{0}</b> - {1} record(s) found"],
            groupColumnShow: [true],
				groupCollapse: true
        },
        searching: {
            stringResult: true,
            searchOperators: true,
            loadDefaults: false,
            multipleSearch: true,
            caption: "Advanced Query Builder",
            Find: " Filter",
            Reset: " Reset",
            multipleGroup: true,
            showQuery: false,
            tmplNames: ["Reefers", "Hazardous"],
            tmplFilters: [template1, template2]
        }
    }).jqGrid('filterToolbar')
    	.jqGrid("gridResize")
    	.jqGrid("navGrid", {
				iconsOverText: true,
				addtext: "Add",
				edittext: "Edit",
				deltext: "Delete",
				searchtext: "Search",
				refreshtext: "Refresh",
				viewtext: "View",
				view: true
			})
			.jqGrid("navButtonAdd", {
                caption: "Show/Hide Filters",
                id: "toggleToolbar",
                //buttonicon: "ui-icon-calculator",
                //commonIconClass: "ui-icon",
                buttonicon: "ui-pg-button-text ui-pg-button-icon-over-text fa-toggle-off",
                title: "Toggle toolbar",
                onClickButton:function(){
									mygrid[0].toggleToolbar()
								} 
            })
			.jqGrid("navButtonAdd", {
                caption: "Clear Filters",
                id: "clearFilters",
                //buttonicon: "ui-icon-calculator",
                //commonIconClass: "ui-icon",
                buttonicon: "ui-pg-button-text ui-pg-button-icon-over-text fa-eraser",
                title: "Clear Filters",
                onClickButton:function(){
									mygrid[0].clearToolbar()
								} 
            })
			.jqGrid("navButtonAdd", {
			    caption: "Show/Hide Columns",
			    buttonicon: "ui-pg-button-text ui-pg-button-icon-over-text fa-table",
			    title: "Choose columns",
			    onClickButton: function () {
			        $(this).jqGrid("columnChooser", {
			            done: function (perm) {
			                if (perm) {
			                    this.jqGrid("remapColumns", perm, true);
			                    saveColumnState.call(this);
			                }
			            }
			        });
			    }
			})
			.jqGrid("navButtonAdd", {
                caption: "Default Settings",
                buttonicon: "ui-pg-button-text ui-pg-button-icon-over-text fa-times",
                title: "Clear saved grid's settings",
                onClickButton: function () {
                    window.location.reload();
                }
            });
			
			

    $("#dynamicGrouping").change(function() {
        var groupingName = $(this).val();
        if (groupingName) {
            $("#jqGrid").jqGrid("setGridParam", {rowNum: 9999})
            	.jqGrid('groupingGroupBy', groupingName);
        } else {
            $("#jqGrid").jqGrid("setGridParam", {rowNum: 250})
            	.jqGrid('groupingRemove');
            	$('#jqGrid').trigger( 'reloadGrid' );
        }
    });
    $("#getSelectedRows").click(function() {
		var selectedIDs = $("#jqGrid").getGridParam("selarrrow");
		alert(selectedIDs.length === 0 ? "No rows are selected" : selectedIDs.join());
    });
    
    
}),
	

				$("#savestate").click(function(){
					saveState();
				});
				$("#loadstate").click(function(){
					loadState();
				});
	
				function navigateToLang(lng) {
            $.jgrid.setRegional('jqGrid',{regional: lng});
        }
        
        function getSelectedRows() {
            var grid = $("#jqGrid");
            var rowKey = grid.getGridParam("selrow");

            if (!rowKey)
                alert("No rows are selected");
            else {
                var selectedIDs = grid.getGridParam("selarrrow");
                var result = "";
                for (var i = 0; i < selectedIDs.length; i++) {
                    result += selectedIDs[i] + ",";
                }

                alert(result);
            }                
        }
	

function saveState(){

    // i have to access the colModel in order to get the names of my columns
    // which i need to get the values of the filter-toolbar textboxes later:
    var col_arr = $("#jqGrid").jqGrid("getGridParam", "colModel");

    // my own array to save the toolbar data:
    var toolbar_search_array = [];
    /*
    for(var i = 0, max = col_arr.length; i < max; i++)
    {
        // only saving the data when colModel's "search" is set to true
        // and value of the filterToolbar textbox  got a length
        // the ID of the filterToolbar text-input is "gs_" + colModel.name
        if(col_arr[i].search && $("#gs_" + col_arr[i].name).val().length)
        {
             toolbar_search_array.push({ name: col_arr[i].name, value: $("#gs_" + col_arr[i].name).val() });
        }
    }*/

    // putting everything into one object
    var pref = {
        // 1. toolbar filter data - used to fill out the text-inputs accordingly
        toolbar :   toolbar_search_array,

        // 2. postData - contains data for the actual filtering 
        post :      $("#jqGrid").jqGrid("getGridParam", "postData"),

        // 3. settings - this data is also included in postData - but doesn't get applied 
        // when using 'setGridParam'
        sortname:   $('#jqGrid').jqGrid('getGridParam', 'sortname'),
        sortorder:  $('#jqGrid').jqGrid('getGridParam', 'sortorder'),
        page:       $('#jqGrid').jqGrid('getGridParam', 'page'),
        rowNum:     $('#jqGrid').jqGrid('getGridParam', 'rowNum')

    };

    //saving in localStorage
    localStorage.setItem("jqGrid",  JSON.stringify( pref ));
};

function loadState(){
		var localsave = JSON.parse(localStorage.getItem("jqGrid"));
		
		// these settings are also saved in postData, 
		// but they don't get applied to the grid when setting the postData:
		$('#jqGrid').jqGrid('setGridParam', {
		    sortname: localsave.sortname,
		    sortorder: localsave.sortorder,
		    page: localsave.page,
		    rowNum: localsave.rowNum
		});
		
		// this applies the filtering itself and reloads the grid. 
		// it's important that you don't forget the "search : true" part:
		$("#jqGrid").jqGrid("setGridParam", { 
		    search : true,
		    postData : localsave.post
		}).trigger("reloadGrid");
		
		// this is loading the text into the filterToolbar 
		// from the array of objects i created:
		console.log(localsave.toolbar);
		for(i = 0, max = localsave.toolbar.length; i < max; i++)
		{
		    $("#gs_" + localsave.toolbar[i].name).val( localsave.toolbar[i].value );
		}	
	
}
a.soptclass {
  border: 2px;
}
th {
  background-color: #aaa;
}
.two-col {
  overflow: hidden;
  /* Makes this div contain its floats */
}
.two-col .col1,
.two-col .col2 {
  width 49%;
}
.two-col .col1 {
  float: left;
}
.two-col .col2 {
  float: right;
}
.two-col label {
  display: block;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/free-jqgrid/4.13.5/css/ui.jqgrid.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/free-jqgrid/4.13.5/js/jquery.jqgrid.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap-theme.min.css" rel="stylesheet" />
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />


	<div style="margin-left:20px; margin-right:20px;">

<div class="two-col">
    <div class="col1">
        <div class="form-group">
						<label for="dynamicGrouping">Group Data By:</label>
						<select id="dynamicGrouping" class="form-control" style="width:auto;">
				        <option value="">No Grouping</option>
				        <option value="c">Carrier</option>
				        <option value="l">Length</option>
				        <option value="h">Height</option>
				        <option value="i">ISO Code</option>
				        <option value="ba">Bay</option>
				        <option value="s">Status</option>
				        <option value="o">Is OOG?</option>
				        <option value="hz">Is Hazardous?</option>
				        <option value="r">Is Reefer?</option>
				    </select>
				</div>
    </div>


</div>

    <table id="jqGrid"></table>
    <div id="jqGridPager"></div>
	<br>
	<button id="savestate" class="btn btn-default">Save Table State</button>

	<button id="loadstate" class="btn btn-default">Load Table State</button>
	</br>
	 <input class="btn btn-default" type="button" value="Get Selected Container Numbers" onclick="getSelectedRows()" />   
</div>


person MarkT    schedule 05.12.2016    source источник


Ответы (1)


Ответ уже старый. Фрагмент кода, который вы включили, взят из функции refreshSerchingToolbar, которая больше не нужна, потому что бесплатная jqGrid 4.13.5 должна автоматически заполнять элементы ввода/выбора панели инструментов фильтра (см. ответ). Вы не выложили полную рабочую демку, и я не могу указать вам точные изменения в коде, но вам нужно просто удалить ненужный вызов refreshSerchingToolbar из loadComplete и удалить код функции refreshSerchingToolbar.

О других проблемах: я не могу воспроизвести проблему с сохранением/восстановлением видимости или порядка столбцов на демонстрация. Если какие-то проблемы действительно существуют, пожалуйста, опишите точный тестовый пример.

person Oleg    schedule 07.12.2016
comment
Я использовал вашу демонстрацию, чтобы моя таблица почти работала. Состояние таблицы теперь корректно сохраняет как критерии columnChooser, так и критерии фильтра, однако при обновлении страницы фильтр не используется. См. мою демонстрацию< /b> Не могли бы вы взглянуть и сообщить мне, что мне нужно добавить, чтобы это заработало? Я вижу, что в вашей демонстрации все работает нормально, поэтому я, должно быть, сделал что-то не так. - person MarkT; 07.12.2016
comment
@MarkT: Не могли бы вы описать точный тестовый пример для воспроизведения проблемы. Если установить некоторые фильтры и нажать ENTER, можно увидеть отфильтрованные результаты. Один ca После этого можно нажать F5, чтобы перезагрузить страницу. Видно, что страница будет загружена с последним примененным фильтром. Я использовал Chrome 55 в своем тесте. - person Oleg; 08.12.2016
comment
Если вы загрузите демонстрацию, затем введите SEGU в фильтре Equipment Nbr и нажмите Enter, вы увидите, что записи отфильтрованы до 61. Если вы затем нажмете F5, вы увидите, что в фильтре все еще есть SEGU, но результаты больше не фильтруются, и вы имеют 2273 записи. Я тестирую на Mac с Safari, Firefox и Chrome. - person MarkT; 08.12.2016
comment
@MarkT: вы должны добавить опцию forceClientSorting: true, чтобы решить проблему. Он применяет фильтр (из postData.filters) и сортирует данные на стороне клиента перед отображением сетки. Чаще всего рекомендуется использовать опцию forceClientSorting: true одновременно с loadonce: true. - person Oleg; 08.12.2016