Skip to content

Releases: wq/ 2.0

02 Nov 18:27
Choose a tag to compare 2.0.0 is the first stable release of the 2.0 series! Be sure to check out the latest documentation and the release notes for wq 2.0 when upgrading.

This release updates the Material UI integration introduced in 1.3, and also includes react-native compatible versions of all core components. The old jQuery Mobile based renderer has been completely removed.

All changes by @sheppard.

Changes since 2.0 alpha 2

Breaking Changes

  • Custom fieldsets should now be registered like other inputs, rather than as generic components (18fa253).

New Features

  • Support both v2 and v3 theme versions for react-native-paper. Specify theme.version in your @wq/material configuration to set the version used. The default is 3, but you may want to set it to 2 if you are upgrading an existing react-native app from @wq/material 1.3. (f3e823d)
  • To facilitate hot module reloading (like that provided with Vite), there is a new that includes the React development build (bc636a1)

Bug Fixes & Enhancements

  • Improve HighlightPopup & TabGroup styles (48889d3)
  • Fix FileArray state issue (71ff82f)
  • Improve memoization of useRouteTitle() and useReverse() (441caab, 265d8e2)
  • Improve object id lookup when applying delete through outbox (265d8e2)
  • Fix Geo & Draw state issues (441caab)
  • Fix type of default 404 template name (441caab)

Other changes since 1.3.0

Changes in Alpha

  • Update third-party libraries to latest versions, following renames as needed
  • Remove @wq/jquery-mobile and @wq/leaflet
  • Split @wq/material into separate @wq/material-web and @wq/material-native implementations.
  • Split @wq/map-gl into separate @wq/map-gl-web and @wq/map-gl-native implementations.
  • Replace MapBox with MapLibre
  • Introduce several new mapping and layout components
  • Improve data model

Changes in Alpha 2

  • Reduce file size of wq.js, while providing additional exports
  • Leverage in-map Popup on larger screens
  • Provide react-native equivalents of all input types
  • Update @wq/map-gl-native to use @maplibre/maplibre-react-native and improve state management. 2.0 alpha 2

25 Aug 16:03
Choose a tag to compare 2.0 alpha 2 is the second preview of the next version of, as part of the wq 2.0 alpha 2 release. This release improves the usage of @mui/material imports in wq.js, provides react-native-paper equivalents for all of @wq/material's Input Types, and updates maplibre-react-native support in @wq/map-gl-native.

All changes by @sheppard.

@wq/material-web & wq.js

  • Update wq.js to export additional components from @mui/material, including ImageList and ToggleButtonGroup (a12809f)
    • As always, use import { ImageList } from "@mui/material" in combination with @wq/rollup-plugin to take advantage of these exports. If you would like to import one of the remaining components not exported by wq.js, use the full path (e.g. import Stack from "@mui/material/Stack") to ensure the import is ignored by the @wq/rollup-plugin.
  • Fix tree shaking for mui-file-dropdown (d2aa481). This dependency was causing all of import * "@mui/material" to be included in wq.js even though not everything was being used or re-exported. Adjusting the import reduced the size of wq.js by over 50%.
  • Update wq.js to export @mui/material/utils, including createSvgIcon (8feb269). This facilitates using @wq/rollup-plugin with modules that import custom icons from @mui/icons-material. Only the unique icon data will be included in each built plugin file, rather than duplicating createSvgIcon since that is already included in wq.js.
  • Ensure data attributes from formik-mui are propagated correctly to options in Select (1beec6f, 06fcbbb)


  • Implement react-native-paper versions of File, Toggle, and Radio inputs (69c05a7)
  • Ensure all input types display hints and error messages as appropriate (69c05a7)
  • Implement side panel and tab components to improve mapping UI (69c05a7, 7d69e39)


  • Use react-map-gl's Popup for highlighted features on larger screens, while preserving the panel-style popup for mobile (21f5966).


  • Switch from @rnmapbox/maps to @maplibre/maplibre-react-native (ee19186)
  • Update map state hooks to match improvements to @wq/map-gl-web in v2.0.0a1 (0881093, 69c05a7) 2.0 alpha

22 Jun 02:28
Choose a tag to compare 2.0 alpha is a preview of the next version of, as part of the wq 2.0 alpha release. The default interface has been upgraded to MUI v5 with MapLibre integration, and support for legacy jQuery Mobile & Leaflet projects has been completely removed.

All changes by @sheppard.

Packaging & Ecosystem

A number of changes significantly improve integration with npm and other build tools, as well as Node itself.

  • All third-party packages have been updated to latest package versions. In particular, @material-ui/core (v4) has been upgraded to the latest @mui/material (v5). (9f9515c, b468228, 28e79ce, 4568600, 6453db3, 84eb5b3, 2c635b4, 79b28cf, 2cd8832).

  • All imports (including package-internal imports) are now ESM-compliant with .js extensions. It is now possible to execute directly from Node. (wq/wq#58, 34f07d9, c47b145)

  • @wq/material has been split into separate implementation packages, @wq/material-web and @wq/material-native. @wq/material automatically re-exports from @wq/material-web when running in e.g. Create React App, and from @wq/material-native when running in e.g. Expo. This separation makes it possible to correctly specify the necessary dependencies for each implementation, while remaining compatible with the latest NPM package specifications. Similarly, @wq/map-gl has been split into separate @wq/map-gl-web and @wq/map-gl-native packages; see below for details. (wq/wq#59, b21881a, 984d97a).

  • Support for wq 1.2-style AMD projects has been completely removed, as well as the @wq/jquery-mobile and @wq/leaflet npm packages. These are maintained in the 1.3 branch if needed. (#111, eb238c0, 1bbbe37, a6dc7bf, 60cd668)

  • Several improvements have been made to the wheel generation process. (0225fc2, ad137bf, b2c946f)

wq.js improvements

The pre-built wq.js script included in (and on npm) now exports several additional MUI components for use in plugins built with @wq/rollup-plugin. Since these imports are processed at runtime, wq.js automatically warns if an export is not found (44ade26, c39aa11, 5f018b3).

For example, @wq/rollup-plugin will transform this:

import { FakeComponent } from "@mui/material";

Into this:

import { modules } from "./wq.js";
const { FakeComponent } = modules["@mui/material"];

When this code is executed in the browser, wq.js will warn that it doesn't have that component (and return an empty component instead, to avoid completely breaking the UI.) Note that some valid @mui/material components are missing from wq.js and will return the same error - see modules.js for what's included.

Also note that the mapping engine is now shipped as a separate .js file and not baked into wq.js (31ad8b8, see below).

MapLibre Integration

Since MapBox is no longer open source, it has been replaced with MapLibre in the default configuration for both web and native (#128).

  • @wq/map-gl-web now exports a setEngine() function that accepts the library object to use. When installing @wq/map-gl and @wq/map-gl-web from npm, this must be called explicitly. When installing from PyPI, the pre-built wq.js file already sets this to the output of ./maplibre-gl.js, which is deployed in the same directory as wq.js (31ad8b8, b468228).
  • The React integration has been switched from react-mapbox-gl to react-map-gl. The latter supports swapping the map engine for MapLibre, and also has built-in support for reusing map instances when components are replaced via navigation state changes. The StickyMap component and associated offscreen component hacks have been removed in favor of this built-in support. (31ad8b8, 2cc0f40, 6215aa9).
  • @wq/map-gl-native leverages @rnmapbox/maps, which defaults to MapLibre Native by default. See the @rnmapbox/maps documentation for information on how to override the default. (0deeb88)

New & Updated Components

Several new components have been added to the registry to provide a more complete UI out of the box.

New Map Components

AutoMap now supports displaying a MUI-styled toolbar with radio buttons for switching the basemap, switches for toggling overlay layers, and a simple legend for each overlay. This support required the addition of several new component types, as shown below (0da45cd, 361ea6c, c39aa11, 2da4718).

Component Description
MapProvider Top level component providing a context for referencing a nearby map object
useMapInstance This hook existed before, but it now finds the map through the MapProvider context instead of the @wq/map redux state.
MapLayers Virtual node wrapping all AutoBasemap and AutoOverlay nodes. The default is just a Fragment
MapContainer Layout node that contains both the Map component and the new MapToolbar MapToolbar
SidePanel Lightweight responsive drawer for embedding in e.g. map views.
CheckboxButton Checkbox for cases that don't require a form input
RadioButton Radio button for cases that don't require a form input
Switch Switch component
Legend Renders the legend for an individual overlay. (Note that MapToolbar was named Legend in 1.3. )
LegendIcon Legend Icon component

The conceptual component tree for a typical AutoMap layout is now as follows:

          <RadioButton />
          <Switch />
            <LegendIcon />
        <MapInteraction />
        <MapAutoZoom />
        <MapIdentify />
            <Tile />
            <Geojson />
        <Highlight />
  <HighlightPopup />

These components can customized or disabled through configuration, through the component registry, and (in the case of MapToolbar) through props provided to <AutoMap/>. Set <AutoMap toolbar={<CustomToolbar/>} /> to override the default, or <AutoMap toolbar={false} /> to disable it.

New Layout Components

The default layout has been improved for both desktop and mobile devices, through the addition of a number of components.

Component Description Commit
Logo Site logo shown in app bar. Set config.logo to an image path, or overrride the component. 3a51fe7
NavMenu Responsive site navigation menu. On small screens this will appear via NavMenuPopup, while larger screens will use NavMenuFixed. NavMenu itself is registered as a view component that is the same as Index by default but can be overridden. d68754c, 7e9e157
TabGroup Based on @mui/materia's Tabs, but automatically renders the content for the selected tab. Used in @wq/map's updated DefaultList and DefaultDetail to support a tabbed layout on small screens. 461add6
TabItem Based on @mui/material's Tab, but with support for @wq/react's icon registry. Accepts children which are conditionally rendered by TabGroup 461add6
BottomNavigation @mui/material's BottomNavigation 461add6
BottomNavigationAction Based on @mui/material's BottomNavigationAction, but with support for @wq/react's icon registry. 461add6
TablePagination @mui/material's TableNavigation cfd1993
TableContainer @mui/material's TableContainer cfd1993

Updated Components

Component Description Commit
Accordion Renamed from ExpansionPanel 9f9515c
PropertyTable Now renders nested fieldsets and arrays as sub-tables instead of JSON d27b71d
OutboxList Fix flex layout 7b1f09a
IconButton Throw specific error if icon is missing, rather than waiting for React to fail 47cb370
Select Improve formik-mui integration & also support native <select> c39aa11, ffd813e, 727231b


05 Apr 12:09
Choose a tag to compare 1.3.0 is the first stable release of the 1.3 series! Be sure to check out the latest documentation and the release notes for wq 1.3 when upgrading.

This release stabilizes the new UI introduced in 1.3 alpha, with a particular focus on improving mapping & React Native/Expo support.

Note: While's React Native / Expo support is already being used in production apps, not all components supported by's web build have working native equivalents. Complete native support and documentation will be provided by 2.0.

All changes by @sheppard.

Changes since 1.3 beta

@wq/map & @wq/map-gl

React Native / Expo Support

@wq/react & @wq/material

@wq/model & @wq/router

Other changes since 1.2.0

  • Changes in Alpha

    • Replace AMD / RequireJS with ES Modules
    • Replace jQuery Mobile + Mustache with React + Material UI
    • Replace Leaflet with Mapbox GL
    • Replace Application Cache with Service Worker
    • Replace PhoneGap Build with Installable PWA and React Native + Expo
    • Maintain copies of deprecated libraries for compatibility with older projects (will remove in 2.0)
  • Changes in Alpha 2

    • Fix authentication and sync issues in Alpha (#124, #125)
    • Improve Map ref handling in React Native
    • Improve support for deployment at non-root URL
    • Stand-alone PropertyTable component
  • Changes in Beta 1.3 beta

03 May 05:23
Choose a tag to compare 1.3.0b1 is the beta release of the next version of, as part of the wq 1.3 beta. This release brings a number of bug fixes & improvements to the @wq/react + @wq/material renderer introduced in 1.3 alpha. Be sure to check out the new documentation site which includes live demos of many of the components in @wq/material.

Breaking Change

While most of the changes below extend and enhance existing behavior, note that there is a backwards-incompatible change in @wq/map. Map bounds coordinates must now be specified using the standard [lng, lat] order, rather than the Leaflet-style [lat, lng] supported in older versions of wq (b11bcd3). If you are upgrading from 1.3.0a1 or older, you will need to update your setting. This applies even if you are using the legacy @wq/jquery-mobile renderer.

Core Modules


  • Restore support for file uploads (wq/wq#50)
  • Option to keep spinner open while prefetching data (#61, #103)
  • Improve parsing of nested objects and arrays (0fcea4d, 001394b)
  • Support anonymous top-level fieldset (001394b)



  • Update document.title during render (e5626bd)


UI Plugins


Component Improvements

New & Improved Hooks


Form Input Improvements

New & Improved Components

Map Plugins


  • Breaking change: Change map bounds coordinates from the Leaflet-style [lat, lng] to the more standard [lng, lat] (b11bcd3). If you are upgrading from 1.2 or older, you will need to update your setting.
  • StickyMap component to preserve map state when offscreen (0fd7177)
  • Additional tools for adding/removing highlighted features to map state (0fd7177)
  • Improve Geo input component:
    • Replace wq/locate.js plugin with built-in geolocation support (#126)
    • Ensure hints and field errors are shown (e3de0e5)
    • Customizable help text for draw tools (540bfad)
    • Option to render within a FlatFieldset instead of the default Fieldset (e.g. when already within a nested form)


  • Renamed from @wq/mapbox to @wq/map-gl to make it easier to switch out map libraries in the future (#128).
  • Don't show trash tool if geometry field is required (540bfad)
  • Basemap "components" now have an asBasemapStyle() function to facilitate the Map-level style prop while maintaining the logic within the component source. (6f5f1c4)

wq.js bundle

  • Generate to document the vendored third-party modules in the build (da4f7d5)
  • Re-export select third-party modules for integration with @wq/rollup-plugin
  • Preserve function names for components and hooks in minified build (d06b814)
  • Improve compatibility with (modern) browsers (5363e07)

CLI Changes

As part of the changes to the build system, the following commands are are deprecated. They will be removed in 2.0, together with the entire source tree:

  • wq appcache
  • wq babel
  • wq build
  • wq init
  • wq mustache
  • wq optimize
  • wq phonegap
  • wq scss

The following commands are not deprecated, but the implementations have moved from to (3f773a1).

The deprecated commands are not needed for newer projects, so the associated dependencies are are now optional (e6f279b). Use pip install[compat] if you have a fresh install of 1.3.0 and need to use the old commands. (Users upgrading from an older version of should already have the required dependencies installed.) 1.3 alpha 2

23 Oct 07:02
Choose a tag to compare 1.3 alpha 2 Pre-release
Pre-release 1.3 alpha 2 brings a number of bug fixes & improvements to the @wq/react + @wq/material renderer introduced in 1.3 alpha.

  • Ensure can_add, can_change & can_delete flags are correctly applied from auth state (#124)
  • Fix handling of field-level errors when opening outbox entry (#125)
  • Improve handling of Map & Camera refs when running @wq/mapbox in react-native
  • Improve handling of non-root-URL deployments in wq serviceworker and <Breadcrumbs/>
  • Move <PropertyTable/> out of <DefaultDetail/> to a standalone component 1.3 alpha

29 Sep 13:54
Choose a tag to compare 1.3 alpha Pre-release
Pre-release 1.3 alpha is a preview of the next version of, as part of the wq 1.3 alpha release. This is perhaps the most ambitious version of to date, bringing a brand-new UI renderer based on React and Material Design, while maintaining backwards compatibility with jQuery Mobile-based projects (for now).

This release achieves the third goal in the roadmap for 2.0. In addition to the tasks listed in that goal, the map engine and app install mechanisms have seen significant overhauls. In all, the following replacements have been made:

Deprecated Replacement
AMD / RequireJS ES Modules
jQuery Mobile + Mustache React + Material UI
Leaflet Mapbox GL
Application Cache Service Worker
PhoneGap Build Installable PWA and/or React Native + Expo

The main PRs for this release are #115 and #122.

ES Modules

Projects created with wq 1.3 now use ESM syntax, even when not using npm.

When was created, there was no standard JavaScript module format. instead leveraged RequireJS and AMD, which combined (some of) the customization capabilities of the npm ecosystem, together with (some of) the simplicity of using a plain <script> tag. Since then, ECMAScript modules (import/export syntax) have become the standard solution for both web and npm. 1.3 leverages ESM to provide users a choice between all of the customizability of npm, or all of the simplicity of a script tag. The old RequireJS build system has been deprecated and replaced with ... no build system at all!

Instead, 1.3 provides a pre-compiled ESM build, wq.js, which contains wq's core modules, the new UI renderer, the new map engine, and the third party dependencies for all of the above. This script can be leveraged via a single <script type=module> tag, or with the small number of configuration modules provided by the new wq start template.

Upgrade Notes 1.3 still provides the old RequireJS/AMD build scripts and related commands (wq init, wq optimize, wq babel, etc.) for compatibility with older projects. However, this support will be dropped in wq 2.0. Thus, it may be good to start migrating to an ESM format sooner rather than later.

Switch to npm

The most natural route is likely to switch to using wq start --with-npm, because that provides the option to install @wq/jquery-mobile and (temporarily) defer the need to rewrite the UI layer. In addition, projects with heavily customized r.js configurations will more likely want to leverage the full capabilities of npm. In particular, you will want to use npm if you need to transpile and optimize ES6 code using babel (#83), for example to support Internet Explorer.

Switch to pre-built ESM

On the other hand, if your project contains minimal customization, you may find it easiest to switch directly to the new wq.js and its built-in UI, plugging in the configuration generated by wq.db and then making minor adjustments as needed. Note that the new setup leverages Django's staticfiles app, which means that:

  1. The development server will automatically serve the latest contents of the app/ folder (see wq/wq-django-template#21).
  2. ./ collectstatic will deploy the app/ folder to the production directory htdocs/static/app/ (see wq/wq-django-template#6).

As of 1.3, the wq build command can automatically detect the project type by examining wq.yml for an optimize section, and by checking for the existence of package.json (see #119). Projects without either of these are assumed to be using the pre-built ESM.

React + Material UI

@wq/react + @wq/material is the new default UI renderer. initially used jQuery Mobile, together with a customized Mustache template engine, to provide offline rendering capability. However, the jQuery Mobile project has not released any update for several years. In addition, the need to generate and compile dozens of Mustache templates into a JSON fixture made wq unecessarily complicated to use, even though the process was partially automated. 1.3 instead provides a flexible render based on React, Material UI and React Native Paper. It is enabled by default for new projects, and includes default React components for all @wq/app route types. This means that for simple projects, it is not necessary to explicitly define any UI screens, except to customize the defaults.

To facilitate both rendering modes, the UI is now configured by registering a renderer plugin with @wq/app:

module description
@wq/react+@wq/material New Material Design renderer based on React and [React Native]
@wq/jquery-mobile Legacy renderer based on jQuery Mobile and Mustache.js

Upgrade Notes

Continue using jQuery Mobile

If you are upgrading from an older version of wq with npm, you will need to to explicitly install and register the @wq/jquery-mobile renderer:

import app from '@wq/app';
import jqmrenderer from '@wq/jquery-mobile';

If you are upgrading from an older RequireJS/AMD template, wq/jquery-mobile.js will be imported automatically in wq/app.js. However, note again that RequireJS support will be dropped in wq 2.0. The wq maketemplates, wq scss, and wq mustache commands are also deprecated and will be removed in 2.0.

Note that wq/template.js, wq/patterns.js, and wq/photos.js are now contained within @wq/jquery-mobile and do not need to be registered separately.

Switch to @wq/react + @wq/material

@wq/react + @wq/material presents a radical departure from the old rendering system, and there is little that can be directly ported. That said, it should be relatively easy to plug your existing wq.db configuration into the new renderer, and obtain a usable default interface to iterate on. Two main things to keep in mind are:

  1. Mustache rendering is no longer used, so templates/, master_templates/ and associated tooling is no longer necessary. In addition, it is no longer necessary to define the UI for the entire application, just for the parts where you want to override the defaults.
  2. The old run($page, routeInfo) plugin hook is no longer available, as it relied on the jQuery Mobile-specific $.mobile.activePage object.

In both cases, the new way to provide custom functionality is by registering one or more custom components with @wq/app. Custom components can override individual inputs or entire views.

Mapbox GL

@wq/mapbox is the new default map engine. 1.3 provides the option to use Mapbox GL for the map engine. Key advantages over Leaflet include support for vector tiles, and native SDKs for Android and iOS. Leaflet-specific code in the old @wq/map has moved to @wq/leaflet, while the new Mapbox GL renderer is available as @wq/mapbox. Both depend on the @wq/map plugin, which now just handles the map configuration and state.

module description
@wq/map+@wq/mapbox Mapbox GL JS integration for web and Mapbox Maps SDK for Android & iOS.
@wq/map+@wq/leaflet Leaflet integration (web only).

Upgrade Notes

Continue using Leaflet

If you are upgrading from an older version of wq with npm, install and import @wq/leaflet instead of @wq/map. If you are upgrading from an older RequireJS/AMD template, then wq/map.js is actually an alias for @wq/leaflet and should work the same as before. However, note again that RequireJS support will be dropped in wq 2.0.

Switch to @wq/mapbox

@wq/map's layer configuration syntax is designed to be engine-agnostic, so switching from @wq/leaflet to @wq/mapbox will generally just work. However, you will likely want to take advantage of Mapbox GL's vector tile support. To do so, you will need to find a vector tile provider online or host the tiles yourself. Providers known to work with @wq/mapbox include Mapbox (obviously), ESRI, and MapTiler Cloud.

Service Worker

Browsers are removing support for Application Cache, which has been superseded by Service Worker.

The Application Cache standard is being deprecated by browser vendors, and for good r... 1.2.0

22 Jan 07:14
Choose a tag to compare 1.2.0 is the first stable release of the 1.2 series. The biggest improvement is the integration of the Redux ecosystem for the outbox and model store (#105). This achieves the second goal in the 2019 roadmap for 1.3 will bring full integration with React and Material UI - see #115 for a preview.

In addition to the Redux integration, a number of nonessential and deprecated AMD modules have been removed from 1.2.

module status
wq/autocomplete.js removed
wq/chart.js moved to Django REST Pandas
wq/chartapp.js moved to Django REST Pandas
wq/console.js removed
wq/json.js removed
wq/markdown.js moved to separate repository
wq/pandas.js moved to Django REST Pandas
wq/progress.js moved to Django Data Wizard

Changes since 1.2 beta

Other changes since 1.1.2

  • Changes in Alpha

    • @wq/app

      • The first page is automatically re-rendered on startup and after auth changes, so jQuery events and other workarounds are no longer needed (#79).
      • app.go() has been removed in favor of app.nav()
      • app.sync(true) has been renamed to app.retryAll(). In general, sync is managed by @wq/outbox and Redux Offline (see below).
    • @wq/store is now a wrapper around Redux and Redux Persist.

      • New dispatch(), getState(), and subscribe() methods correspond to Redux equivalents.
      • Enables Redux Logger when config.debug is true
      • @wq/app plugins that define name, reducer() and actions:{} will get their own state in the store.
      • jsonp and parseData options are replaced with the ajax() plugin hook
      • ds.storageUsage() has been removed.
    • @wq/router is now a wrapper around Redux-First Router.

      • Routes are defined as Redux action types that map to the template name.
      • Thunks can be defined as pathless non-rendered routes (as per Redux-First Router). @wq/app plugins that define thunks: {} will be auto-registered.
      • router.register() has completely changed. The callback is now optional and only needs to supply a context for use with router.go(). router.go() no longer can/should be invoked indirectly.
      • router.addRoute() is deprecated in favor of run() plugin hooks.
      • Route info is now provided only through the template context (and not as
    • @wq/model is now a wrapper around Redux-ORM.

      • A name is now required for all model instances. (@wq/app provides this automatically)
      • The Redux-ORM queryset is available via [model].objects.all().
      • [model].filter() now wraps objects.filter(), which supports predicate functions and better indexing. Note that objects.filter() uses strict equality when comparing object attributes.
      • find(), update(), fetchUpdate() and remove() no longer support specifying an id column. Instead, define idCol when configuring/initializing the model.
      • @wq/model now supports (de)normalization for nested models returned from server APIs (#114)
    • @wq/outbox is now a wrapper around Redux Offline.

      • Fix various offline state and syncing issues (e.g. #33, #94/#95, and #102).
      • Several new methods to control syncing: waitForItem(), waitForAll(), retryItem(), retryAll(), pause(), resume(), and empty(). Use these instead of sendItem(), sendAll(), and the noSend option for save(), all of which have been removed.
      • Batch sync support (#110) via Django Batch Requests
      • applyState configuration option for form submissions (#85, #86):
        • "ON_SUCCESS" (default): update local model after sync.
        • "IMMEDIATE": optimistically update local model before sync
        • "LOCAL_ONLY": update local model without syncing
      • outbox.model.load() is removed in favor of outbox.loadItems()
      • parseBatchResult(), applyResult() and updateModels() are no longer available.
    • Other Changes

      • @wq/map: copy layer config in case it is modified by function (440dc9b)
      • @wq/map: don't update sticky bounds when map is off-screen (5952fe6)
      • removeattachment action in @wq/app:patterns plugin (d5372ff)
      • Sourcemaps for wq/* AMD modules (43222ff)
      • Remove compatibility versions of wq/autocomplete.js, wq/console.js, wq/json.js, and wq/progress.js, which were deprecated in 1.1.2.
  • Changes in Beta
    • Automatically navigate to permanent URL once new items are synced (#98, #99)
    • filter_fields and filter_ignore options for @wq/model (#88).
    • Preserve URL params during pagination (778631c, c2b5ab0)
    • onsync(item) plugin hook (#96)
    • Remove several hooks and events in favor of newer options:
      • Removed Hooks: onsave(), saveerror(), showOutboxErrors(), postsave(), presync(), postsync()
      • Removed Events: "login", "logout"
      • Removed Config:
    • Various bug fixes 1.2 beta

07 Oct 07:57
Choose a tag to compare 1.2 beta Pre-release
Pre-release 1.2.0b1 is the beta version of the upcoming 1.2 release. In addition to the major changes introduced in 1.2 alpha, 1.2 beta includes the following updates:

New Features

Thanks to @tomaszn for feedback on the design of many of these features.

  • If the current URL contains the temporary ID of an unsynced record (e.g. "outbox-123"), automatically navigate to the new URL once synced (#98, #99)
  • New filter_fields and filter_ignore configuration options for @wq/model. If a URL parameter is not found inform, functions, or filter_fields, it will be ignored when filtering list views (#88).
  • Simplified onsync(item) plugin hook, called after each outbox item is synced to the server (#96)
  • Better management of URL params during pagination (778631c, c2b5ab0)

Removed Features

To clean up the API and prepare for a future migration away from jQuery Mobile (#111), this release removes several older hooks and events, as noted in the updated @wq/app documentation and below.

name type suggested migration path
onsave(item, result) Plugin Hook Use an onsync() hook instead. The server result will be available as item.result.
saveerror(item, reason, $form) Config Hook Use an onsync() hook instead. The error will be available as item.error.
showOutboxErrors() Config Hook Use an onsync() and/or run() plugin hook instead.
postsave() Config Hook Use a postsaveurl() plugin hook instead.
presync() / postsync() Config Hook Use the template context as needed for UI customizations. Pages displaying outbox contents are automatically re-rendered after each sync.
"login", "logout" jQuery events Use the template context as needed for UI customizations. As of 1.2, all pages (including server-rendered pages) are automatically re-rendered on the client if the login state changes. jQuery Mobile transition This was a configurable transition and has no effect in 1.2. The default and dialog transitions remain configurable, but it is recommended to leave them as "none".

In addition to the above, note that the ui option passed to jQuery Mobile navigation events is no longer used, as Redux First Router now handles all navigation. Among other things, this means that setting data-transition or data-direction on an <a href> no longer has any effect.

Bug Fixes

  • Confirm rare sync timing issue no longer exists in @wq/outbox (#102)
  • Fix issues with refresh logic (c738019) and sync navigation logic (b42d152)
  • Bind this to plugin for reducer() and render() plugin hooks (e94ebd6) 1.2 alpha

08 Aug 03:57
Choose a tag to compare 1.2 alpha Pre-release
Pre-release 1.2 alpha is a preview of the next version of The primary change is the integration of Redux and related libraries as part of a comprehensive overhaul of the data model layer (#105).

This release achieves the second goal in the 2019 roadmap for


New Features

Redux Integration (#105, #113)

  • @wq/store now provides dispatch(), getState(), and subscribe() methods, which directly wrap the corresponding Redux store methods.
  • The following @wq/app plugin hooks are now available:
    • reducer() and actions for plugin-specific Redux state (@wq/store)
    • thunks and render() for more complex Redux actions and rendering (@wq/router)
  • When debug is active, @wq/store will log all Redux events and state changes (including page navigation and rendering events) to the console via Redux Logger.
  • @wq/router routes are now named, with Redux action types that generally match the template name.
  • @wq/model's [model].filter() is now a wrapper for Redux-ORM's filter(), which provides additional features such as predicate function filters and better indexing.
  • Direct access to the Redux-ORM queryset is also available via [model].objects.all().
  • @wq/outbox supports several new methods to control syncing: waitForItem(), waitForAll(), retryItem(), retryAll(), pause(), resume(), and empty().

Other Improvements

  • The first loaded page is now always re-rendered by the client during application startup, as well as after authentication changes (#79)
  • New applyState configuration option to control when updates are applied to the local model (#85, #86). A different set of Redux actions will be applied for form submission/success/error depending on this setting. The available options are:
    • "ON_SUCCESS" (default): form submissions will not be reflected in the local model state until after the form is successfully synced to the server.
    • "IMMEDIATE": form submissions are optimistically reflected in the local model state before they are sent to the server.
    • "LOCAL_ONLY": form submissions are not synced to the server at all. In this case, nothing is stored in the outbox, so the only reason to use is to maintain API consistency with other forms.
  • Support syncing multiple items in a single fetch() (#110), by leveraging @tomaszn's fork of Django Batch Requests.
  • Support registering a top-level model and also having it as an attachment (nested record) for another model (#114). The records will be normalized for local storage and denormalized for the API.
  • Add removeattachment action to @wq/app:patterns plugin (d5372ff)
  • Generate sourcemaps for wq/* AMD modules (43222ff)

Bug Fixes

  • The integration of Redux Offline addresses a number of issues with offline state and syncing, particulary #33, #94/#95, and #102.
  • @wq/map:
    • Copy layer config in case it is modified by function (440dc9b)
    • Don't update sticky bounds when map is off-screen (5952fe6)

Breaking Changes

This release necessarily changes a lot of the underlying data model, while keeping the UI layer mostly the same. If you are only using the high-level API, only the changes to @wq/app should affect you. If you are using app.models or the lower level modules directly, you may want to review the other changes below.


  • app.go() has been removed. You can generally use app.nav() instead, with a context() plugin for cases where you need a custom context.
  • app.sync(true) has been renamed to app.retryAll()
  • app.sync() and config.backgroundSync are no longer available. The timing of syncing (other than manual retries) is now handled by @wq/outbox and Redux Offline.
  • Login/logout events are now dispatched as Redux actions rather than as jQuery events. Pages are re-rendered after auth changes, so any updates to the UI should happen in the template and context rather than in a jQuery event handler.
  • The first page is always re-rendered by the client during application startup.


  • The jsonp and parseData configuration options no longer exist. To customize how data is retrieved and parsed, use an ajax() plugin hook instead.
  • The promise returned by ds.set() no longer waits until the data has been fully persisted to offline storage before resolving.
  • ds.storageUsage() has been removed.
  • ds.reset() no longer has the capability of clearing out persisted storage for stores other than the current one.


  • Route info is now provided only through the template context (and not as
  • With the exeption of path, the arguments to router.register() have completely changed, though they serve a similar function. With 1.1 and earlier, a callback function was required, and needed to explicitly call router.go() with the generated context. Starting in 1.2, the callback function is optional, and only needs to return a new context object.
  • router.go() is now called automatically whenever the Redux state changes. So, it is not necessary (or possible) to call it directly.
  • The arguments to router.addRoute() have also changed somewhat, and the function is deprecated in favor of run() plugin hooks anyway.


  • A name is now required for all model instances. (@wq/app provides this automatically)
  • find(), update(), fetchUpdate() and remove() no longer accept a custom id column as the second argument. If the primary key is not "id", specify idCol when defining the model.
  • filter() is now based on Redux-ORM's filter(), which uses strict equality when comparing object attributes. In 1.1 and earlier, {'type_id': '3'} and {'type_id': 3} returned the same result, whereas in 1.2 they are different.


  • The Promise returned by is now resolved before the record is synced. If you need to wait for the sync result, call outbox.waitForItem() after calling Relatedly, no longer accepts a third noSend argument. If you would like to save an item to the outbox without triggering an immediate sync attempt, call outbox.pause() before
  • outbox.sendItem() and outbox.sendAll() have been removed. Similar functionality is provided by outbox.waitForItem(), outbox.waitForAll(), and outbox.retryAll().
  • @wq/outbox no longer uses an internal @wq/model instance for managing unsynced records. Instead, the underlying Redux Offline outbox state is wrapped with a model-like API. If you have code relying on outbox.model.load(), change it to use outbox.loadItems() instead which provides an equivalent structure.
  • batchService should be specified as a URL path relative to the service root (rather than relative to the domain)
  • parseBatchResult(), applyResult() and updateModels() are no longer available as configuration options. The first two can be replaced with a custom ajax() plugin hook, while updateModels() is now implemented via Redux actions.