| 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: index.html | 8 next: /docs/tutorials/ |
| 9 next-title: "A Game of Darts" | 9 next-title: "A Game of Darts" |
| 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. |
| 20 * Indices allow for high performance searches. | 20 * Indices allow for high performance searches. |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 78 Check | 78 Check |
| 79 <a href="http://caniuse.com/#feat=indexeddb" | 79 <a href="http://caniuse.com/#feat=indexeddb" |
| 80 target="_blank">caniuse.com</a> | 80 target="_blank">caniuse.com</a> |
| 81 for up-to-date information. | 81 for up-to-date information. |
| 82 Your app can check programmatically | 82 Your app can check programmatically |
| 83 if the current platform supports IndexedDB | 83 if the current platform supports IndexedDB |
| 84 and adjust accordingly. | 84 and adjust accordingly. |
| 85 </aside> | 85 </aside> |
| 86 | 86 |
| 87 This target shows you how to use | 87 This target shows you how to use |
| 88 <a href="http://api.dartlang.org/dart_indexed_db.html" | 88 <a href="https://api.dartlang.org/dart_indexed_db.html" |
| 89 target="_blank">dart:indexed_db</a> | 89 target="_blank">dart:indexed_db</a> |
| 90 to store data to and retrieve data from the browser's IndexedDB. | 90 to store data to and retrieve data from the browser's IndexedDB. |
| 91 | 91 |
| 92 * [Run the app](#run-the-app) | 92 * [Run the app](#run-the-app) |
| 93 * [About the app: The basics](#the-basics) | 93 * [About the app: The basics](#the-basics) |
| 94 * [Details about IndexedDB](#details-about-indexeddb) | 94 * [Details about IndexedDB](#details-about-indexeddb) |
| 95 * [Importing the IndexedDB library](#import-indexeddb) | 95 * [Importing the IndexedDB library](#import-indexeddb) |
| 96 * [Checking for IndexedDB support](#checking-indexeddb) | 96 * [Checking for IndexedDB support](#checking-indexeddb) |
| 97 * [Creating and opening a database](#opening-indexeddb) | 97 * [Creating and opening a database](#opening-indexeddb) |
| 98 * [Creating an object store](#creating-object-store) | 98 * [Creating an object store](#creating-object-store) |
| (...skipping 22 matching lines...) Expand all Loading... |
| 121 <a href="index.html#run-the-app">this page</a>. | 121 <a href="index.html#run-the-app">this page</a>. |
| 122 The milestone you created still exists | 122 The milestone you created still exists |
| 123 because the app stored it in an IndexedDB in the browser. | 123 because the app stored it in an IndexedDB in the browser. |
| 124 | 124 |
| 125 Use the minus (**-**) button to the right of a milestone | 125 Use the minus (**-**) button to the right of a milestone |
| 126 to delete that milestone. | 126 to delete that milestone. |
| 127 Use the **Clear** button to delete all the milestones. | 127 Use the **Clear** button to delete all the milestones. |
| 128 | 128 |
| 129 <iframe class="running-app-frame" | 129 <iframe class="running-app-frame" |
| 130 style="height:400px;width:600px;" | 130 style="height:400px;width:600px;" |
| 131 src="http://dart-lang.github.com/dart-tutorials-samples/web/target11/cou
nt_down/web/out/count_down.html"> | 131 src="http://dart-lang.github.io/dart-tutorials-samples/web/target11/coun
t_down/web/out/count_down.html"> |
| 132 </iframe> | 132 </iframe> |
| 133 | 133 |
| 134 You can find the complete source code for this sample on github at | 134 You can find the complete source code for this sample on github at |
| 135 <a href="https://github.com/dart-lang/dart-tutorials-samples/tree/master/web/tar
get11/count_down" target="_blank">count_down</a>. | 135 <a href="https://github.com/dart-lang/dart-tutorials-samples/tree/master/web/tar
get11/count_down" target="_blank">count_down</a>. |
| 136 | 136 |
| 137 ###Using developer tools to look at the database | 137 ###Using developer tools to look at the database |
| 138 | 138 |
| 139 You can use the browser's developer tools | 139 You can use the browser's developer tools |
| 140 to explore the IndexedDB databases used by your apps. | 140 to explore the IndexedDB databases used by your apps. |
| 141 In Chrome, select **View > Developer > Developer Tools**, | 141 In Chrome, select **View > Developer > Developer Tools**, |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 183 The View-model queries the Model upon initialization | 183 The View-model queries the Model upon initialization |
| 184 and uses Web UI data-bindings to keep the View in sync. | 184 and uses Web UI data-bindings to keep the View in sync. |
| 185 Also, it uses Timer events to trigger updates in the Model. | 185 Also, it uses Timer events to trigger updates in the Model. |
| 186 | 186 |
| 187 ###The libraries used by the count_down app | 187 ###The libraries used by the count_down app |
| 188 | 188 |
| 189 The count_down app uses the following libraries: | 189 The count_down app uses the following libraries: |
| 190 | 190 |
| 191 | Library | Description | | 191 | Library | Description | |
| 192 |---|---| | 192 |---|---| |
| 193 | <a href="http://api.dartlang.org/dart_indexed_db.html" target="_blank">dart:in
dexed_db</a> | Save data into an indexed database for persistence and offline ca
pability | | 193 | <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 | |
| 194 | <a href="http://api.dartlang.org/dart_async.html" target="_blank">dart:async</
a> | Perform tasks asynchronously | | 194 | <a href="https://api.dartlang.org/dart_async.html" target="_blank">dart:async<
/a> | Perform tasks asynchronously | |
| 195 | <a href="http://api.dartlang.org/dart_core.html" target="_blank">dart:core</a>
| Use DateTime and Duration to manage time-related tasks | | 195 | <a href="https://api.dartlang.org/dart_core.html" target="_blank">dart:core</a
> | Use DateTime and Duration to manage time-related tasks | |
| 196 | <a href="http://pub.dartlang.org/packages/web_ui" target="_blank">package:web_
ui</a> | Create UIs with data-binding and web components. | | 196 | <a href="https://pub.dartlang.org/packages/web_ui" target="_blank">package:web
_ui</a> | Create UIs with data-binding and web components. | |
| 197 {: .table } | 197 {: .table } |
| 198 | 198 |
| 199 This target explains the Dart API for IndexedDB used by the count_down app. | 199 This target explains the Dart API for IndexedDB used by the count_down app. |
| 200 In addition, this target covers some interesting | 200 In addition, this target covers some interesting |
| 201 API related to dates, times, and timers. | 201 API related to dates, times, and timers. |
| 202 | 202 |
| 203 <aside class="alert" markdown="1"> | 203 <aside class="alert" markdown="1"> |
| 204 <strong>Note:</strong> | 204 <strong>Note:</strong> |
| 205 This target does not cover Futures or Web UI. | 205 This target does not cover Futures or Web UI. |
| 206 For information about Futures, | 206 For information about Futures, |
| 207 see | 207 see |
| 208 <a href="/articles/using-future-based-apis/">Using Future Based APIs</a> | 208 <a href="/articles/using-future-based-apis/">Using Future Based APIs</a> |
| 209 and | 209 and |
| 210 <a href="/articles/futures-and-error-handling/">Futures and Error Handling</a>. | 210 <a href="/articles/futures-and-error-handling/">Futures and Error Handling</a>. |
| 211 For information about Web UI, | 211 For information about Web UI, |
| 212 check out the relevant recipes in the | 212 check out the relevant recipes in the |
| 213 <a href="/docs/cookbook/"> | 213 <a href="/docs/cookbook/"> |
| 214 <i class="icon-food"> </i> Dart Cookbook</a> | 214 <i class="icon-food"> </i> Dart Cookbook</a> |
| 215 or read the Web UI tutorials in | 215 or read the Web UI tutorials in |
| 216 Targets <a href="/docs/tutorials/web-ui">6</a>, | 216 Targets <a href="/docs/tutorials/web-ui/">6</a>, |
| 217 <a href="/docs/tutorials/templates">7</a>, | 217 <a href="/docs/tutorials/templates/">7</a>, |
| 218 <a href="/docs/tutorials/custom-elements">8</a>. | 218 <a href="/docs/tutorials/custom-elements/">8</a>. |
| 219 | 219 |
| 220 </aside> | 220 </aside> |
| 221 | 221 |
| 222 ##Details about IndexedDB | 222 ##Details about IndexedDB |
| 223 | 223 |
| 224 Some important facts you need to know about IndexedDB: | 224 Some important facts you need to know about IndexedDB: |
| 225 | 225 |
| 226 * Each origin (host, protocol, and port) has its own set of databases. | 226 * Each origin (host, protocol, and port) has its own set of databases. |
| 227 A unique name identifies each database within an origin. | 227 A unique name identifies each database within an origin. |
| 228 IndexedDB has a same-origin policy, | 228 IndexedDB has a same-origin policy, |
| (...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 417 All the countdown milestones are stored and retrieved | 417 All the countdown milestones are stored and retrieved |
| 418 in this object store. | 418 in this object store. |
| 419 | 419 |
| 420 The code sets `autoIncrement` on the object store to true. | 420 The code sets `autoIncrement` on the object store to true. |
| 421 When autoIncrement is true, | 421 When autoIncrement is true, |
| 422 the database generates unique, primary keys for you, | 422 the database generates unique, primary keys for you, |
| 423 which saves you the trouble of doing so. | 423 which saves you the trouble of doing so. |
| 424 | 424 |
| 425 Finally, `_initializeDatabase` creates an index. | 425 Finally, `_initializeDatabase` creates an index. |
| 426 | 426 |
| 427 ##Using an index | 427 ##Using a name index |
| 428 | 428 |
| 429 An index provides a lookup table. | 429 An index provides a lookup table. |
| 430 You can associate a primary key with a field in the stored objects. | 430 You can associate a primary key with a field in the stored objects. |
| 431 In the example, | 431 In the example, |
| 432 the index associates a primary key with the milestoneName field. | 432 the index associates a primary key with the milestoneName field. |
| 433 | 433 |
| 434  | 434  |
| 435 | 435 |
| 436 Using an index provides two benefits: | 436 Using an index provides two benefits: |
| 437 | 437 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 457 * unique, a boolean value. | 457 * unique, a boolean value. |
| 458 When true, the index ensures that the milestone name is unique. | 458 When true, the index ensures that the milestone name is unique. |
| 459 In the count_down app, | 459 In the count_down app, |
| 460 if you try to add a milestone with the same name as another, | 460 if you try to add a milestone with the same name as another, |
| 461 it is this index that causes the add() to fail. | 461 it is this index that causes the add() to fail. |
| 462 | 462 |
| 463 ##Using transactions {#using-transactions} | 463 ##Using transactions {#using-transactions} |
| 464 | 464 |
| 465 All database operations must be performed | 465 All database operations must be performed |
| 466 within a | 466 within a |
| 467 <a href="http://api.dartlang.org/dart_indexedDb/Transaction.html" target="_blank
">Transaction</a>. | 467 <a href="https://api.dartlang.org/dart_indexedDb/Transaction.html" target="_blan
k">Transaction</a>. |
| 468 | 468 |
| 469 <aside class="alert" markdown="1"> | 469 <aside class="alert" markdown="1"> |
| 470 <strong>Important: About the life-cycle of a transaction</strong> | 470 <strong>Important: About the life-cycle of a transaction</strong> |
| 471 | 471 |
| 472 The life-cycle of a transaction is as follows: | 472 The life-cycle of a transaction is as follows: |
| 473 | 473 |
| 474 * Open a transaction. | 474 * Open a transaction. |
| 475 * Place requests on the transaction and register callbacks. | 475 * Place requests on the transaction and register callbacks. |
| 476 * When there are no more requests | 476 * When there are no more requests |
| 477 and the last callback finishes, the transaction completes. | 477 and the last callback finishes, the transaction completes. |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 657 return cursors.length.then((_) { | 657 return cursors.length.then((_) { |
| 658 return milestones.length; | 658 return milestones.length; |
| 659 }); | 659 }); |
| 660 } | 660 } |
| 661 {% endprettify %} | 661 {% endprettify %} |
| 662 | 662 |
| 663 Because getting records does not modify the database, | 663 Because getting records does not modify the database, |
| 664 this transaction is readonly. | 664 this transaction is readonly. |
| 665 | 665 |
| 666 You can use a | 666 You can use a |
| 667 <a href="http://api.dartlang.org/dart_indexedDb/Cursor.html" target="_blank">Cur
sor</a> | 667 <a href="https://api.dartlang.org/dart_indexedDb/Cursor.html" target="_blank">Cu
rsor</a> |
| 668 object to step through the records in the database one by one, | 668 object to step through the records in the database one by one, |
| 669 creating a Milestone object for each. | 669 creating a Milestone object for each. |
| 670 The object store uses a stream to fire an event for each record | 670 The object store uses a stream to fire an event for each record |
| 671 retrieved from the database. | 671 retrieved from the database. |
| 672 By listening on the stream, | 672 By listening on the stream, |
| 673 your code can be notified for each record read. | 673 your code can be notified for each record read. |
| 674 The count_down app creates a corresponding Milestone object | 674 The count_down app creates a corresponding Milestone object |
| 675 in the internal list in memory for each database record retrieved. | 675 in the internal list in memory for each database record retrieved. |
| 676 | 676 |
| 677 Open a cursor on a transaction's object store with `openCursor`. | 677 Open a cursor on a transaction's object store with `openCursor`. |
| (...skipping 11 matching lines...) Expand all Loading... |
| 689 | 689 |
| 690 The openCursor() method returns a stream on which you can listen for events. | 690 The openCursor() method returns a stream on which you can listen for events. |
| 691 Here, | 691 Here, |
| 692 the stream is a broadcast stream, | 692 the stream is a broadcast stream, |
| 693 so the app can listen both for read events | 693 so the app can listen both for read events |
| 694 and for a final count of records retrieved. | 694 and for a final count of records retrieved. |
| 695 | 695 |
| 696 For each record retrieved from the database, | 696 For each record retrieved from the database, |
| 697 an event fires and the callback function is called. | 697 an event fires and the callback function is called. |
| 698 A | 698 A |
| 699 <a href="http://api.dartlang.org/dart_indexedDb/CursorWithValue.html" target="_b
lank">CursorWithValue</a> | 699 <a href="https://api.dartlang.org/dart_indexedDb/CursorWithValue.html" target="_
blank">CursorWithValue</a> |
| 700 object, named `cursor` in this example, | 700 object, named `cursor` in this example, |
| 701 is passed to the callback function. | 701 is passed to the callback function. |
| 702 Use `cursor.key` to get the key for the record just retrieved. | 702 Use `cursor.key` to get the key for the record just retrieved. |
| 703 Use `cursor.value` to get the value for that record. | 703 Use `cursor.value` to get the value for that record. |
| 704 | 704 |
| 705 The _loadFromDB method returns a Future that returns the length of the stream. | 705 The _loadFromDB method returns a Future that returns the length of the stream. |
| 706 | 706 |
| 707 ##Other resources | 707 ##Other resources |
| 708 | 708 |
| 709 <ul> | 709 <ul> |
| (...skipping 16 matching lines...) Expand all Loading... |
| 726 ###What next? | 726 ###What next? |
| 727 | 727 |
| 728 Check out our | 728 Check out our |
| 729 <a href="/codelabs/web-ui-writer/index.html" target="_blank"><i class="icon-beak
er"> </i>Codelab</a>; | 729 <a href="/codelabs/web-ui-writer/index.html" target="_blank"><i class="icon-beak
er"> </i>Codelab</a>; |
| 730 it uses LocalStorage instead of IndexedDB to store data in the client. | 730 it uses LocalStorage instead of IndexedDB to store data in the client. |
| 731 Try converting it to use IndexedDB. | 731 Try converting it to use IndexedDB. |
| 732 | 732 |
| 733 {% endcapture %} | 733 {% endcapture %} |
| 734 | 734 |
| 735 {% include tutorial.html %} | 735 {% include tutorial.html %} |
| OLD | NEW |