Login Register

dojox.data.QueryReadStore (1.0)

New in 1.0, QueryReadStore is very similar to ItemReadStore. They both use JSON as their exchange format. The difference is in the way they query data. ItemReadStore makes one fetch from the server, and handles all sorting and filtering in the client. That's fine for hundreds of records, even thousands. But for hundreds of thousands of records or slow Internet connections, that's less feasible.

QueryReadStore makes a request to the server for each sorting or query. This makes it ideal for large datasets with small windows of data, as in dijit.FilteringSelect.

Query Translation

A dojo.data request follows a specific JSON format. As an example, suppose we have a FilteringSelect which looks up states. When the user presses "A", the dojo.data request is:

{
   query: {name: "A*"},
   queryOptions: {ignoreCase: true},
   sort: [{attribute:"name", descending:false}],
   start: 0,
   count: 10
}

Now we want to hand this off to the server. Odds are, your server doesn't recognize incoming JSON, and asking it to do so is too restrictive. Instead, most server queries follow a REST pattern like this:

states.php?q=A*

Fortunately, it's easy to translate between the two. You simply subclass QueryReadStore like this:

dojo.provide("custom.ComboBoxReadStore");
dojo.declare("custom.ComboBoxReadStore", dojox.data.QueryReadStore, {
    fetch:function(request) {
	request.serverQuery = {q:request.query.name};
        // Call superclasses' fetch
	return this.inherited("fetch", arguments);
    }
});

We can place this file into a folder "custom" at the same level as the dojo, dijit and dojox directories of the distribution. (See Creating Your Own Modules for a discussion and alternatives.

You can download QueryReadStore.php below (it's also in /dojox/data/tests/stores/QueryReadStore.php) to run this example on a PHP server. The server portion hands over a portion of the states that fits the query. The full client program:

<!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>QueryReadStore Demo</title>
    <style type="text/css">
        @import "http://o.aolcdn.com/dojo/1.0.0/dijit/themes/tundra/tundra.css";
        @import "http://o.aolcdn.com/dojo/1.0.0/dojo/dojo.css"
    </style>
    <script type="text/javascript" src="http://o.aolcdn.com/dojo/1.0.0/dojo/dojo.xd.js"
            djConfig="parseOnLoad: true">
</script>
    <script type="text/javascript">
       dojo.require("dojo.parser");
       dojo.require("dojox.data.QueryReadStore");
       dojo.require("dijit.form.FilteringSelect");
       dojo.require("custom.ComboBoxReadStore");
    </script>
</head>
<body class="tundra">
    <div dojoType="ComboBoxReadStore" jsId="store"
         url="QueryReadStore.php"
         requestMethod="get">

    </div>
    State: <input id="fs" dojoType="dijit.form.FilteringSelect" store="store" pageSize="5" />
</body></html>
AttachmentSize
QueryReadStore.php_.txt5.18 KB

help

I was not able to run the example....
I checked the example the list is not populating...
what should i do? I tried with 1.0 and 1.0.1 both QueryReadStore.html example..... page is dispalying but not showing data?

Example broken plus check your PHP version

First of all, the example seems to be broken as "custom.ComboBoxReadStore" doesn't exist in content delivery network. However, it's easy to fix because the definition can be grabbed from a test page, where ComboBox uses a customized QueryReadStore. Just drop this fixed version on the same directory as that test page on your box:

<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>QueryReadStore Demo</title>
        <style type="text/css">
            @import "../../../dojo/resources/dojo.css";
            @import "../../../dijit/themes/tundra/tundra.css";
        </style>
        <script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script>
        <script type="text/javascript">
            dojo.require("dijit.form.ComboBox");
            dojo.require("dijit.form.FilteringSelect");
            dojo.require("dojox.data.QueryReadStore");

            dojo.provide("ComboBoxReadStore");
            dojo.declare(
                "ComboBoxReadStore",
                dojox.data.QueryReadStore,
                {
                    fetch:function(request) {
                        request.serverQuery = {q:request.query.name};
                        return this.inherited("fetch", arguments);
                    }
                }
            );
        </script>
    </head>
    <body class="tundra">
        <div dojoType="ComboBoxReadStore" jsId="store"
             url="stores/QueryReadStore.php"
             requestMethod="get">

        </div>
        State: <input id="fs" dojoType="dijit.form.FilteringSelect" store="store" pageSize="5" />
    </body>
</html>

Example won't work with old PHP versions, so you might also want to check you PHP version. PHP page uses json_encode function that has been in PHP only for a year - since version 5.2.0. Simple way to check PHP version is with a PHP page that contains only phpinfo function:

<?
    phpinfo();
?>

thanks

I was using PHP 4.0... i got it working now... :D

Does someone have a jsp example

I am trying to use Dojo for a new project at work, and PHP is a non-starter, since we are using jsp for the rest of the product.

Can someone point to working examples of Dojo 1.x.x with a jsp back end?

I would love to see a working dojox.data.QueryReadStore jsp example.

how about this as a java example of QueryReadStore...

Didn't do the pagination and there's likely some libaries you could import to do the json but this will work. Just save this as QueryReadStore.jsp, and then go into QueryReadStore.html and change the extension from php to .jsp.

<%@page import="java.util.*" %>
<%
HashMap qrs = new HashMap();

HashMap Alabama = new HashMap();
qrs.put("Alabama", Alabama);
Alabama.put("name", "Alabama");
Alabama.put("label", "Alabama");
Alabama.put("abbreviation", "AL");

HashMap Alaska = new HashMap();
qrs.put("Alaska", Alaska);
Alaska.put("name", "Alaska");
Alaska.put("label", "Alaska");
Alaska.put("abbreviation", "AK");

String q = request.getParameter("q"); ;
System.out.println("q=" + q);

if (q != null && q.endsWith("*")) {
	q = q.substring(0,q.lastIndexOf("*"));
	System.out.println("q=" + q);
}

ArrayList ret = new ArrayList();		

Set qrsKeys = qrs.keySet();
Iterator Iter = qrsKeys.iterator();
while (q != null && Iter.hasNext()) {
        String key = (String)(Iter.next());
        System.out.println("KEY=" + key + " - " + qrs.get(key));
        if (0 == key.indexOf(q)){
        	ret.add(qrs.get(key));
        }
}
/*
		 Handle paging, if given.
		if (array_key_exists("start", $_REQUEST)) {
			$ret = array_slice($ret, $_REQUEST['start']);
		}
		if (array_key_exists("count", $_REQUEST)) {
			$ret = array_slice($ret, 0, $_REQUEST['count']);
		}
 */
%>
{
"items":
[
<%
int size = ret.size();
Iter = ret.iterator();
while (Iter.hasNext()) {
	HashMap item = (HashMap)Iter.next();
	int index = ret.indexOf(item);
	String comma = null;
	if (size > 1 && ((size-1) !=index)) {comma=",";} else {comma="";}
%>
 { identifier:"<%=item.get("name")%>", name:"<%=item.get("name")%>", label:"<%=item.get("label")%>", abbreviation:"<%=item.get("abbreviation")%>"}<%=comma%>
<% } %>
]
}

QueryReadStore with form data

Is there a easy way to parse form-data into the query?
I have a searchformular with more than one searchparameter.
How can I get a datasore?
Thanks for help!

xhr-Request in QueryReadStore

The xhr-Request in the QueryReadStore is done with
var xhrHandler = xhrFunc({url:this.url, handleAs:"json-comment-optional", content:serverQuery});

I have some problems with the "json-comment-optional" ... wouldn't it be possible to define the handleAs - Parameter when I define the store??

Thanks!

i also have a problem with the xhr-Request...

because i need to define sync:true

actually, it's even necessary for this PHP example, because as result of each server request the text in the FilteringSelect is being replaced, and if the user types too fast (actually while the server request is on the go), it messes up the text in the FilteringSelect. i would call this a bug.
my solution is to make the xhr calls synchronized (and not asynchronized).

regards,
ewilde.

Dojo bug tracking and forums

@zet4080, ewilde: Please, file bug reports and enhancement ideas to Dojo Trac (Log in: guest/guest).

@martin.eller, pcarmichael: Support questions to Dojox forums.

QueryReadStore not fit for Tree widget

See recent Trac issue and the discussion: QueryReadStore can't be used to provide data for a Tree widget.

Example using paging?

Does anyone have an example like the one above supporting paging on the server side?

The PHP script of the example above does interpret the request parameters "start" and "count", but these parameters not sent by the client. I tried to extend the example above:
- added the "pageSize"-attribute to the FilteringSelect
- modified the fetch-function by adding request.start and request.count to the server query

When I try to load the second page of a list of returned values, the PHP script replies these items but they are not displayed in the FilteringSelect. Instead, the drop down window is being closed and the "invalid value" message is being displayed.

What else has to be done?

Best regards,
Ralph