How to remove extra column value from jqgrid json

2019-09-17 03:42发布

问题:

Free Jqgrid has actions column. colmodel:

{"hidden":false,"label":"","name":"_actions","width":72
,"align":"left","template":"actions","fixed":false,"resizable":true,
  "formatoptions":{"editbutton":true,"delbutton":true,"delOptions":{"url":"Delete" }}},

{"label":"Nimetus","name":"Nimi","index":"Nimi","editoptions":{"maxlength":80,"size":80 }

It is populated from remote json data like

{"total":1,
 "page":1,
  "rows":[{"id":"2ARVELDUSARV", "cell":[null,"2ARVELDUSARV"]},
          {"id":"ACME","cell":[null,"ACME"]},
          {"id":"KAKSKOERA","cell":[null,"KAKSKOERA"]}
 ]
}

In cell array first column is not used. If this column is removed, jqgrid does not render data correctly since this column presence is required as placeholder for actions column. How to fix this so that jqgrid will accept data without first column:

{"total":1,
 "page":1,
  "rows":[{"id":"2ARVELDUSARV", "cell":[null,"2ARVELDUSARV"]},
          {"id":"ACME","cell":["ACME"]},
          {"id":"KAKSKOERA","cell":["KAKSKOERA"]}
 ]
}

Update

I looked for data format change as recommended in answer. jqgrid data is created from sql select statement in ASP.NET MVC4 using code below. Web API serializes this to format for json for jqgrid automatically.

How to create result which can serialized to propertyname: value format recommended in answer ?

  object GetDataForJqGrid() {
        IDbConnection conn;
        using (var dataReader = DataAccessBase.ExecuteReader(sql.ToString(), out conn,
               CommandBehavior.CloseConnection | CommandBehavior.SingleResult,
               sql.GetParameters.ToArray()))
        {
            var rowList = new List<GridRow>();
            var pkeys = DatabasePrimaryKey();
            while (dataReader.Read())
            {
                var pkv = new List<object>();
                int offset = 1; // required for actions column
                var row = new GridRow
                {
                    id = IdHelper.EncodeId(pkv),
                    cell = new object[dataReader.FieldCount + offset + imageCount]
                };
                for (int j = 0; j < dataReader.FieldCount; j++)
                   row.cell[offset + j] = dataReader.GetValue(j);
                rowList.Add(row);
            }

            return new
            {
                total = rowList.Count() < rows ? page : page + 1,                                  page, 
          rows = rowList
            };
}

public class GridRow
{
    public string id;
    public object[] cell;
}

回答1:

The most easy way would be to chanege the format of data returned from the server to use repeatitems: false style of the data. I mean the usage of

{
    "total": 1,
    "page": 1,
    "rows": [
        { "id": "2ARVELDUSARV", "Nimi": "2ARVELDUSARV" },
        { "id": "ACME", "Nimi": "ACME" },
        { "id": "KAKSKOERA", "Nimi": "KAKSKOERA"}
    ]
}

or, after adding key: true to the definition of the column Nimi

{
    "total": 1,
    "page": 1,
    "rows": [
        { "Nimi": "2ARVELDUSARV" },
        { "Nimi": "ACME" },
        { "Nimi": "KAKSKOERA"}
    ]
}

instead of

{
    "total": 1,
    "page": 1,
    "rows": [{
        "id": "2ARVELDUSARV",
        "cell": ["2ARVELDUSARV"]
    }, {
        "id": "ACME",
        "cell": ["ACME"]
    }, {
        "id": "KAKSKOERA",
        "cell": ["KAKSKOERA"]
    }]
}

Alternatively one can use jsonReader: { repeatitems: false } event with your current format of data and add jsonmap: "cell.0" property to, which means getting the first element (index 0) from the array cell:

$("#list").jqGrid({
    datatype: "json",
    url: "andrus.json",
    colModel: [
        { label: "", name: "_actions", template: "actions" },
        { label: "Nimetus", name: "Nimi", jsonmap: "cell.0" }
    ],
    iconSet: "fontAwesome",
    jsonReader: { repeatitems: false }
});

see the demo.

I personally would recommend you don't use your original format (cell with array of values) and use just the named property with additional id property (if id value is not included in the item already). If you would do use the solution with jsonmap you should be carefully with changing the order of the columns (using remapColumns) and later reloading of data. You could required to update jsonmap values after the changing the column order. Thus I repeat that I recommend you to change format of data returned from the server.

UPDATED: The Updated part of your question formulate absolutely new question which have no relation with jqGrid. It's pure C# problem. Nevertheless I try to answer, because I use C# too.

What you can do with minimal changes of your code is the following: You should add using System.Dynamic; and using System.Linq; first of all. Then you should replace the code inside of using (...) {...} to about the following

var rowList = new List<dynamic>();
while (dataReader.Read()) {
    var row = new ExpandoObject() as IDictionary<string, object>;
    for (int j = 0; j < dataReader.FieldCount; j++) {
        if (!dataReader.IsDBNull(j)) {
            row.Add(dataReader.GetName(j), dataReader.GetValue(j));
        }
    }
    rowList.Add(row);
}

Serializing of rowList will produce the names properties. If you know the primary key of the data, then you can add id property with the corresponding value in the same way (using row.Add("id", IdHelper.EncodeId(pkv))). I don't included the part because the code which you posted is not full and pkv is currently always new List<object>(), which is wrong. If the data have composed key (multiple value set is unique) then you can make string concatenation of the keys using '_' (underscore) as the separator.