OLD | NEW |
1 --- | 1 --- |
2 layout: default | 2 layout: default |
3 title: "Use IndexedDB" | 3 title: "Use IndexedDB" |
4 description: "Use IndexedDB for persistence and offline capability for your app.
" | 4 description: "Use IndexedDB for persistence and offline capability for your app.
" |
5 has-permalinks: true | 5 has-permalinks: true |
6 tutorial: | 6 tutorial: |
7 id: indexeddb | 7 id: indexeddb |
8 next: | 8 next: |
9 next-title: "A Game of Darts" | 9 next-title: "Home" |
10 prev: forms/ | 10 prev: forms/ |
11 prev-title: "Get Input from a Form" | 11 prev-title: "Get Input from a Form" |
12 --- | 12 --- |
13 | 13 |
14 {% capture whats_the_point %} | 14 {% capture whats_the_point %} |
15 | 15 |
16 * IndexedDB is a new standard for client-side storage in modern web browsers. | 16 * IndexedDB is a new standard for client-side storage in modern web browsers. |
17 * Client-side storage provides persistence, offline capability, | 17 * Client-side storage provides persistence, offline capability, |
18 and other advantages. | 18 and other advantages. |
19 * IndexedDB lets you store significant amounts of structured data. | 19 * IndexedDB lets you store significant amounts of structured data. |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
56 such as images, arrays, maps, and objects using IndexedDB. | 56 such as images, arrays, maps, and objects using IndexedDB. |
57 The standard does not specify size limits for | 57 The standard does not specify size limits for |
58 individual data items or for the database itself, | 58 individual data items or for the database itself, |
59 but browsers may impose storage limits. | 59 but browsers may impose storage limits. |
60 | 60 |
61 IndexedDB provides several advantages. | 61 IndexedDB provides several advantages. |
62 Your apps | 62 Your apps |
63 | 63 |
64 * can have full functionality even if a network connection is not available. | 64 * can have full functionality even if a network connection is not available. |
65 * can cache data and restore state between invocations. | 65 * can cache data and restore state between invocations. |
66 * won't lose data if the network connected is interrupted. | 66 * won't lose data if the network connection is interrupted. |
67 * generate less network traffic. | 67 * generate less network traffic. |
68 * perform better because data management happens on the local computer | 68 * perform better because data management happens on the local computer |
69 rather than over the Internet. | 69 rather than over the Internet. |
70 | 70 |
71 <aside class="alert" markdown="1"> | 71 <aside class="alert alert-info" markdown="1"> |
72 <strong>Note:</strong> | 72 <strong>Note:</strong> |
73 Some browsers don't yet support IndexedDB. | 73 Some browsers don't yet support IndexedDB. |
74 Check | 74 Check |
75 <a href="http://caniuse.com/#feat=indexeddb" | 75 <a href="http://caniuse.com/#feat=indexeddb" |
76 target="_blank">caniuse.com</a> | 76 target="_blank">caniuse.com</a> |
77 for up-to-date information. | 77 for up-to-date information. |
78 Your app can check programmatically | 78 Your app can check programmatically |
79 if the current platform supports IndexedDB | 79 if the current platform supports IndexedDB |
80 and adjust accordingly. | 80 and adjust accordingly. |
81 </aside> | 81 </aside> |
(...skipping 10 matching lines...) Expand all Loading... |
92 * [Checking for IndexedDB support](#checking-indexeddb) | 92 * [Checking for IndexedDB support](#checking-indexeddb) |
93 * [Creating and opening a database](#opening-indexeddb) | 93 * [Creating and opening a database](#opening-indexeddb) |
94 * [Creating an object store](#creating-object-store) | 94 * [Creating an object store](#creating-object-store) |
95 * [Using a name index](#using-a-name-index) | 95 * [Using a name index](#using-a-name-index) |
96 * [Using transactions](#using-transactions) | 96 * [Using transactions](#using-transactions) |
97 * [Adding data](#adding-data) | 97 * [Adding data](#adding-data) |
98 * [Removing data](#removing-data) | 98 * [Removing data](#removing-data) |
99 * [Clearing all data](#clearing-all-data) | 99 * [Clearing all data](#clearing-all-data) |
100 * [Using a cursor to get all the records](#getting-data) | 100 * [Using a cursor to get all the records](#getting-data) |
101 * [Other resources](#other-resources) | 101 * [Other resources](#other-resources) |
| 102 * [What next?](#what-next) |
102 | 103 |
103 ##Run the app {#run-the-app} | 104 ##Run the app {#run-the-app} |
104 | 105 |
105 The `count_down` app below maintains a list of milestones | 106 The `count_down` app below maintains a list of milestones |
106 and displays a countdown timer for each one. | 107 and displays a countdown timer for each one. |
107 | 108 |
108 **Try it!** | 109 **Try it!** |
109 Enter the name, date, and time of a milestone—your | 110 Enter the name, date, and time of a milestone—your |
110 birthday, for example—and click the plus (**+**) button. | 111 birthday, for example—and click the plus (**+**) button. |
111 The app shows the milestone name briefly, | 112 The app starts a countdown timer |
112 starts a countdown timer, | 113 and displays the amount of time remaining until the milestone occurs. |
113 and then displays the amount of time remaining until the milestone occurs. | |
114 The app updates the display every second. | 114 The app updates the display every second. |
115 | 115 |
116 Close this browser window and reload | 116 Close this browser window and reload |
117 <a href="index.html#run-the-app">this page</a>. | 117 <a href="index.html#run-the-app">this page</a>. |
118 The milestone you created still exists | 118 The milestone you created still exists |
119 because the app stored it in an IndexedDB in the browser. | 119 because the app stored it in an IndexedDB in the browser. |
120 | 120 |
121 Use the minus (**-**) button to the right of a milestone | 121 Use the minus (**-**) button to the right of a milestone |
122 to delete that milestone. | 122 to delete that milestone. |
123 Use the **Clear** button to delete all the milestones. | 123 Use the **Clear** button to delete all the milestones. |
(...skipping 27 matching lines...) Expand all Loading... |
151 ##About the app: The basics {#the-basics} | 151 ##About the app: The basics {#the-basics} |
152 | 152 |
153 The count_down app uses a Model, View, View-model (MVVM) structure. | 153 The count_down app uses a Model, View, View-model (MVVM) structure. |
154 | 154 |
155  | 155  |
156 | 156 |
157 * The **View-model**, in the center of the diagram, | 157 * The **View-model**, in the center of the diagram, |
158 connects the View and the Model, | 158 connects the View and the Model, |
159 using UI and Timer events | 159 using UI and Timer events |
160 to make changes to the Model. | 160 to make changes to the Model. |
161 The MilestoneApp class is primary class | 161 The MilestoneApp class is the primary class |
162 that implements the View-Model—it | 162 that implements the View-Model—it |
163 manages the timer, | 163 manages the timer, |
164 and implements the app's business logic, | 164 and implements the app's business logic, |
165 which manages the information exchange between the Model and the View. | 165 which manages the information exchange between the Model and the View. |
166 | 166 |
167 * The **View** provides the user interface for the app. | 167 * The **View** provides the user interface for the app. |
168 Two custom components implement the View in the count_down app: | 168 Two custom elements implement the View in the count_down app: |
169 CountDownComponent describes the user interface for the app as a whole, | 169 CountDownComponent describes the user interface for the app as a whole, |
170 and MilestoneComponent describes the UI for an individual milestone. | 170 and MilestoneComponent describes the UI for an individual milestone. |
171 These components inform the View-model of UI events. | 171 These components inform the View-model of UI events. |
172 | 172 |
173 * The **Model** contains and manages the data. | 173 * The **Model** contains and manages the data. |
174 The Model, | 174 The Model, |
175 implemented by the MilestoneStore class, | 175 implemented by the MilestoneStore class, |
176 manages a list of Milestone objects in memory | 176 manages a list of Milestone objects in memory |
177 and keeps an IndexedDB in sync with the list, | 177 and keeps an IndexedDB in sync with the list, |
178 saving the milestone data persistently. | 178 saving the milestone data persistently. |
179 The View-model queries the Model upon initialization | 179 The View-model queries the Model upon initialization |
180 and uses Polymer data-bindings to keep the View in sync. | 180 and uses Polymer data-bindings to keep the View in sync. |
181 Also, it uses Timer events to trigger updates in the Model. | 181 Also, it uses Timer events to trigger updates in the Model. |
182 | 182 |
183 ###The libraries used by the count_down app | 183 ###The libraries used by the count_down app |
184 | 184 |
185 The count_down app uses the following libraries: | 185 The count_down app uses the following libraries: |
186 | 186 |
187 | Library | Description | | 187 | Library | Description | |
188 |---|---| | 188 |---|---| |
189 | <a href="https://api.dartlang.org/dart_indexed_db.html" target="_blank">dart:i
ndexed_db</a> | Save data into an indexed database for persistence and offline c
apability | | 189 | <a href="https://api.dartlang.org/dart_indexed_db.html" target="_blank">dart:i
ndexed_db</a> | Save data into an indexed database for persistence and offline c
apability | |
190 | <a href="https://api.dartlang.org/dart_async.html" target="_blank">dart:async<
/a> | Perform tasks asynchronously | | 190 | <a href="https://api.dartlang.org/dart_async.html" target="_blank">dart:async<
/a> | Perform tasks asynchronously | |
191 | <a href="https://api.dartlang.org/dart_core.html" target="_blank">dart:core</a
> | Use DateTime and Duration to manage time-related tasks | | 191 | <a href="https://api.dartlang.org/dart_core.html" target="_blank">dart:core</a
> | Use DateTime and Duration to manage time-related tasks | |
192 | <a href="https://api.dartlang.org/polymer.html" target="_blank">Polymer</a> |
Create UIs with custom elements and data binding. | | 192 | <a href="https://api.dartlang.org/polymer.html" target="_blank">Polymer</a> |
Create UIs with custom elements and data binding. | |
193 {: .table } | 193 {: .table } |
194 | 194 |
195 This tutorial explains the Dart API for IndexedDB used by the count_down app. | 195 This tutorial explains the Dart API for IndexedDB used by the count_down app. |
196 In addition, this tutorial covers some interesting | |
197 API related to dates, times, and timers. | |
198 | 196 |
199 <aside class="alert" markdown="1"> | 197 <aside class="alert alert-info" markdown="1"> |
200 <strong>Note:</strong> | 198 <strong>Note:</strong> |
201 This tutorial does not cover Futures or Polymer. | 199 This tutorial does not cover Futures or Polymer. |
202 For information about Futures, | 200 For information about Futures, |
203 see | 201 see |
204 <a href="/articles/using-future-based-apis/">Using Future Based APIs</a> | 202 <a href="/articles/using-future-based-apis/">Using Future Based APIs</a> |
205 and | 203 and |
206 <a href="/articles/futures-and-error-handling/">Futures and Error Handling</a>. | 204 <a href="/articles/futures-and-error-handling/">Futures and Error Handling</a>. |
207 For information about Polymer, | 205 For information about Polymer, |
208 refer to <a href="/docs/tutorials/polymer-intro/">Define a Custom Element</a>. | 206 refer to <a href="/docs/tutorials/polymer-intro/">Define a Custom Element</a>. |
209 | 207 |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
333 The first two parameters indicate the name and version of the | 331 The first two parameters indicate the name and version of the |
334 database to open. | 332 database to open. |
335 The first time the count_down app runs from a particular origin, | 333 The first time the count_down app runs from a particular origin, |
336 `milestoneDB` version 1 gets created and opened. | 334 `milestoneDB` version 1 gets created and opened. |
337 The next time the app runs from that same origin, | 335 The next time the app runs from that same origin, |
338 the database is simply opened. | 336 the database is simply opened. |
339 | 337 |
340 The third parameter, `onUpgradeNeeded`, | 338 The third parameter, `onUpgradeNeeded`, |
341 provides a callback function that gets called | 339 provides a callback function that gets called |
342 when an upgrade needed event is fired, | 340 when an upgrade needed event is fired, |
343 which happens when a new database | 341 which happens when a new database is created |
344 or the version of a database is updated. | 342 or the version of a database is updated. |
345 This gives your app an opportunity to create an object store. | 343 This gives your app an opportunity to create an object store. |
346 The only place you can create an object store | 344 The only place you can create an object store |
347 is within an upgrade needed event. | 345 is within an upgrade needed event. |
348 You _must_ have an object store to add records to the database. | 346 You _must_ have an object store to add records to the database. |
349 The next section covers how to create an object store. | 347 The next section covers how to create an object store. |
350 | 348 |
351 The following flow chart describes the logic of the | 349 The following flow chart describes the logic of the |
352 `window.indexedDB.open()` function. | 350 `window.indexedDB.open()` function. |
353 | 351 |
354  | 352  |
355 | 353 |
356 Because creating and opening a database can take time, | 354 Because creating and opening a database can take time, |
357 `window.indexedDB.open()` returns a Future object, | 355 `window.indexedDB.open()` returns a Future object, |
358 which runs asynchronously and returns a value sometime in the future. | 356 which runs asynchronously and returns a value, the database object, |
359 The value is returned to a callback function | 357 sometime in the future. |
| 358 The database object is returned to a callback function |
360 registered with `then()`. | 359 registered with `then()`. |
361 In this example, | 360 In this example, |
362 the callback function is called `_loadFromDB()`. | 361 the callback function is called `_loadFromDB()`. |
363 Using cursors, | 362 Using cursors, |
364 `_loadFromDB()` reads all the milestones | 363 `_loadFromDB()` reads all the milestones |
365 from the database and populates the app. | 364 from the database and populates the app. |
366 The details are covered in | 365 The details are covered in |
367 [Using a cursor to get all the records](#getting-data). | 366 [Using a cursor to get all the records](#getting-data). |
368 | 367 |
369 ##Creating an object store {#creating-object-store} | 368 ##Creating an object store {#creating-object-store} |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
403 Use the Database object's `createObjectStore()` method | 402 Use the Database object's `createObjectStore()` method |
404 to create a new object store with the given name. | 403 to create a new object store with the given name. |
405 Each object store must have a unique name. | 404 Each object store must have a unique name. |
406 The count_down app uses one object store called `milestoneStore`. | 405 The count_down app uses one object store called `milestoneStore`. |
407 All the countdown milestones are stored and retrieved | 406 All the countdown milestones are stored and retrieved |
408 in this object store. | 407 in this object store. |
409 | 408 |
410 The code sets `autoIncrement` on the object store to true. | 409 The code sets `autoIncrement` on the object store to true. |
411 When autoIncrement is true, | 410 When autoIncrement is true, |
412 the database generates unique, primary keys for you, | 411 the database generates unique, primary keys for you, |
413 which saves you the trouble of doing so. | 412 which saves you the trouble of ensuring unique keys. |
414 | 413 |
415 Finally, `_initializeDatabase` creates an index. | 414 Finally, `_initializeDatabase` creates a name index. |
416 | 415 |
417 ##Using a name index | 416 ##Using a name index |
418 | 417 |
419 An index provides a lookup table. | 418 An index provides a lookup table. |
420 You can associate a primary key with a field in the stored objects. | 419 You can associate a primary key with a field in the stored objects. |
421 In the example, | 420 In the example, |
422 the index associates a primary key with the milestoneName field. | 421 the index associates a primary key with the milestoneName field. |
423 | 422 |
424  | 423  |
425 | 424 |
(...skipping 23 matching lines...) Expand all Loading... |
449 In the count_down app, | 448 In the count_down app, |
450 if you try to add a milestone with the same name as another, | 449 if you try to add a milestone with the same name as another, |
451 it is this index that causes the add() to fail. | 450 it is this index that causes the add() to fail. |
452 | 451 |
453 ##Using transactions {#using-transactions} | 452 ##Using transactions {#using-transactions} |
454 | 453 |
455 All database operations must be performed | 454 All database operations must be performed |
456 within a | 455 within a |
457 <a href="https://api.dartlang.org/dart_indexedDb/Transaction.html" target="_blan
k">Transaction</a>. | 456 <a href="https://api.dartlang.org/dart_indexedDb/Transaction.html" target="_blan
k">Transaction</a>. |
458 | 457 |
459 <aside class="alert" markdown="1"> | 458 <aside class="alert alert-info" markdown="1"> |
460 <strong>Important: About the life-cycle of a transaction</strong> | 459 <strong>Important: About the life-cycle of a transaction</strong> |
461 | 460 |
462 The life-cycle of a transaction is as follows: | 461 The life-cycle of a transaction is as follows: |
463 | 462 |
464 * Open a transaction. | 463 * Open a transaction. |
465 * Place requests on the transaction and register callbacks. | 464 * Place requests on the transaction and register callbacks. |
466 * When there are no more requests | 465 * When there are no more requests |
467 and the last callback finishes, the transaction completes. | 466 and the last callback finishes, the transaction completes. |
468 | 467 |
469 So, a transaction remains alive until all requests are complete and | 468 So, a transaction remains alive until all requests are complete and |
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
703 <a href="/articles/futures-and-error-handling/">Futures and Error Handling</a>
. | 702 <a href="/articles/futures-and-error-handling/">Futures and Error Handling</a>
. |
704 </li> | 703 </li> |
705 <li> | 704 <li> |
706 For information about Polymer, | 705 For information about Polymer, |
707 read <a href="/docs/tutorials/polymer-intro">Define a Custom Element</a>. | 706 read <a href="/docs/tutorials/polymer-intro">Define a Custom Element</a>. |
708 </li> | 707 </li> |
709 </ul> | 708 </ul> |
710 | 709 |
711 ###What next? | 710 ###What next? |
712 | 711 |
713 Check out our | 712 You've completed the tutorials! |
714 <a href="/codelabs/web-ui-writer/index.html" target="_blank"><i class="icon-beak
er"> </i>Codelab</a>; | 713 Check out the Dart |
715 it uses LocalStorage instead of IndexedDB to store data in the client. | 714 [code samples](/samples/) and [articles](/articles/). |
716 Try converting it to use IndexedDB. | |
717 | 715 |
718 {% endcapture %} | 716 {% endcapture %} |
719 | 717 |
720 {% include tutorial.html %} | 718 {% include tutorial.html %} |
OLD | NEW |