带有REST API的可编辑jQuery网格建议 [英] Editable jQuery Grid Recommendations with REST API

查看:151
本文介绍了带有REST API的可编辑jQuery网格建议的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

首先,我已经阅读过这个问题例如或在这里搜索界面。



我给你从jqGrid的例子,但我发现这个问题很常见。 我想强调一下,RESTfull服务不会为排序,分页和数据过滤提供标准接口。



在使用jqGrid的情况下REST满URL将默认获取其他参数。它是:页面 rows ,它们指定页面编号和服务要求的页面大小, sidx sord 参数指定了排序列和排序方向, _search 过滤器(最后一个在格式),它允许支持过滤。如果需要,可以使用jqGrid的 prmNames 选项重命名参数。



我建议您阅读有关问题的答案询问有关URL的编码。我认为零件 _search = false& rows = 20&page = 1& sidx =& sord = asc 不属于资源,因此最好发送信息作为参数,而不是作为URL的一部分。



我在回答中主要想表达的是,使用纯经典RESTfull API不足以实现良好的用户界面。您将不得不扩展与用于分页,排序和过滤的附加参数的接口,否则您将无法创建高性能和用户友好的Web GUI。


First, i already read the question "jQuery Grid Recommendations" but it doesn't answer to my question.

I have a small REST API with MongoDB Backend just :

Get all equipements :

GET /equipements HTTP/1.1
{{_id:key1, name:Test Document 1, plateforme:prod}, {_id:key2, name:Test Document 2, plateforme:prod}, ...}

Get equipement with the key : key1

GET /equipements/key1 HTTP/1.1
{"_id": "key1", "name": "Test Document 1", "plateforme": "prod"}

Add new equipement

PUT /equipements HTTP/1.1  {"_id": "key8", "name": "Test Document 3", "plateforme": "prod"}
HTTP/1.0 200 OK

Now, I need to find an easy way to allow lambda user to add/view/del equipments. So i think a web interface with a jQuery like UI is the best. I tried with Sencha Rest Proxy but I do not know javascript and I fails to adapt the example.

How fix my javascript for my REST backend?

AND/OR

Can you recommend a simpler alternative to Sencha Rest Proxy? (which works with my REST backend)

Answer : jqGrid

AND/OR

What jQuery Grid would you recommend me? (which works with my REST backend)

Answer : jqGrid

Final question : Why my cells are not editable with double click ?

Appendices

Server Side (EDIT : Add methode POST)

#!/usr/bin/python
import json
import bottle
from bottle import static_file, route, run, request, abort, response
import simplejson
import pymongo
from pymongo import Connection
import datetime



class MongoEncoder(simplejson.JSONEncoder):
    def default(self, obj):
                # convert all iterables to lists
        if hasattr(obj, '__iter__'):
            return list(obj)
        # convert cursors to lists
        elif isinstance(obj, pymongo.cursor.Cursor):
            return list(obj)
        # convert ObjectId to string
        elif isinstance(obj, pymongo.objectid.ObjectId):
            return unicode(obj)
        # dereference DBRef
        elif isinstance(obj, pymongo.dbref.DBRef):
            return db.dereference(obj)
        # convert dates to strings
        elif isinstance(obj, datetime.datetime) or isinstance(obj, datetime.date) or isinstance(obj, datetime.time):
            return unicode(obj)
        return simplejson.JSONEncoder.default(self, obj)



connection = Connection('localhost', 27017)
db = connection.mydatabase

@route('/static/<filename:path>')
def send_static(filename):
    return static_file(filename, root='/home/igs/restlite/static')

@route('/')
def send_static():
    return static_file('index.html',root='/home/igs/restlite/static/')

@route('/equipements', method='PUT')
def put_equipement():
    data = request.body.readline()
    if not data:
        abort(400, 'No data received')
    entity = json.loads(data)
    if not entity.has_key('_id'):
        abort(400,'No _id specified')
    try:
        db['equipements'].save(entity)
    except ValidationError as ve:
        abort(400, str(ve))

@route('/equipements', method='POST')
def post_equipement():
    data = request.forms

    if not data:
        abort(400, 'No data received')
    entity = {}
    for k,v  in data.items():
        entity[k]=v

    if not entity.has_key('_id'):
        abort(400,'No _id specified')
    try:
        db['equipements'].save(entity)
    except ValidationError as ve:
        abort(400, str(ve))


@route('/equipements/:id', methodd='GET')
def get_equipement(id):
    entity = db['equipements'].find_one({'_id':id})
    if not entity:
        abort(404, 'No equipement with id %s' % id)
    return entity

@route('/equipements', methodd='GET')
def get_equipements():
    entity = db['equipements'].find({})
    if not entity:
        abort(404, 'No equipement')
    response.content_type = 'application/json'
    entries = [entry for entry in entity]
    return MongoEncoder().encode(entries)

run(host='0.0.0.0', port=80)

EDIT : JQGrid :

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>Rest Proxy Example</title>
    <link rel="stylesheet" type="text/css" href="/static/css/ui.jqgrid.css" />
    <link rel="stylesheet" type="text/css" href="/static/css/jquery-ui-1.8.20.custom.css" />

    <script type="text/javascript" src="/static/js/jquery.js"></script>
    <script type="text/javascript" src="/static/js/jquery.jqGrid.min.js"></script>
    <script type="text/javascript" src="/static/js/grid.locale-fr.js"></script>
    <script type="text/javascript">
        jQuery(document).ready(function(){
            var lastsel;

jQuery("#list2").jqGrid({
    url:'equipements',
    datatype: "json",
    colNames:['Id','Name', 'Plateforme'],
    colModel:[
        {name:'_id',index:'_id', width:50, editable:true},
        {name:'name',index:'_id', width:300, editable:true},
        {name:'plateforme',index:'total', width:200,align:"right", editable:true},
    ],
    rowNum:30,
    rowList:[10,20,30],
    pager:'pager2',
    sortname: '_id',
    viewrecords: true,
    width: 600,
    height: "100%",
    sortorder: "desc",
    onSelectRow: function(_id){
        if(_id && _id!==lastsel){
            jQuery('#liste2').jqGrid('restoreRow',lastsel);
            jQuery('#liste2').jqGrid('editRow',_id,true);
            lastsel=_id;
        }
    },
    jsonReader: {
        repeatitems: false,
        id: "_id",
        root: function (obj) { return obj; },
        records: function (obj) { return obj.length; },
        page: function (obj) { return 1; },
        total: function (obj) { return 1; }
    },
    editurl:'equipements',
    caption:"Equipements"
});
jQuery("#list2").jqGrid('navGrid','#pager2',{edit:true,add:true,del:true});
});
    </script>
</head>
<body>
    <table id="list2"></table>
    <div id="pager2"></div>
    <br />

</body>
</html>

解决方案

You can use jqGrid to communicate with your RESTfull service. jqGrid supports tree editing modes: cell editing, inline editing and form editing. Moreover the inline editing can be initialized in different ways. For example one can call editRow method inside of onSelectRow or ondblClickRow callback or use navGrid to add "Delete" button in the navigator toolbar and inlineNav to add "Add" and "Edit" buttons. Another way will be to use formatter: "actions" to include "editing" buttons in one column of the grid. You can find all the ways in the official jqGrid demo. More technical implementation details you can find in the answer.

I find personally important that you understand another important aspect of the usage of RESTfull services in the web front-end. The problem is that standard RESTfull API don't any standard interface for sorting, paging and filtering of the data. I try to explain the problem below. After that I hope it will be clear my recommendation to extend the current standard RESTfull API with additional methods which have additional parameters and which provide sorting, paging and filtering functionality.

The problem is very easy to understand if you have large dataset. It has no sense to display in the grid for example 10000 rows of data at once. The user is unable to see the data on the screen without scolling or paging of data. Moreover because of the same reasons it has sense to implement sorting and even filtering of the data. So it is much more practical to display only one page of data at the beginning and give the user some interface for paging the data. In the standard pager of jqGrid which looks like

the user can go to the "Next", "Last", "Previous" or "First" page or choose the page size:

additionally the user can specify the desired page by direct input of the new page and pressing of Enter:

In the same way the user can click on the header of any column to sort the grid data by the column:

Another very important user interface element (important from the users point of view) could be some filtering interface like here for example or searching interface like here.

I give you example from jqGrid, but I find the problem as common. I want to emphasize that RESTfull service gives you no standard interface for sorting, paging and filtering of the data.

In case of usage jqGrid the RESTfull url will get by default additional parameters. It's: page, rows which specify the page number and the page size which will be asked from the service, sidx and sord parameters which specify the sorting column and the sorting direction and _search and filters (the last is in the format) which allows to support filtering. One can rename the parameters if needed using prmNames option of jqGrid.

I recommend you to read the answer on the question which are asked about the encoding of the URL. I think that the part _search=false&rows=20&page=1&sidx=&sord=asc is not belong to resource and so it's better to send the information as parameters and not as the part of URL.

What I mainly wanted to express in my answer is that the usage of pure classical RESTfull API is not sufficient to implement good user interface. You will have to extend the interface with additional parameters used for paging, sorting and filtering or you will be not able to create performant and user friendly web GUI.

这篇关于带有REST API的可编辑jQuery网格建议的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆