docs.sheetjs.com/docz/docs/03-demos/05-mobile/02-nativescript.md

299 lines
7.6 KiB
Markdown
Raw Normal View History

2023-01-05 23:33:49 +00:00
---
title: NativeScript
2023-02-28 11:40:44 +00:00
pagination_prev: demos/static/index
2023-01-05 23:33:49 +00:00
pagination_next: demos/desktop/index
sidebar_position: 2
sidebar_custom_props:
summary: JS + Native Elements
---
2023-04-27 09:12:19 +00:00
import current from '/version.js';
2023-05-07 13:58:36 +00:00
import CodeBlock from '@theme/CodeBlock';
2023-04-27 09:12:19 +00:00
2023-01-05 23:33:49 +00:00
The [NodeJS Module](/docs/getting-started/installation/nodejs) can be imported
from the main entrypoint or any script in the project.
2023-04-03 09:09:59 +00:00
The "Complete Example" creates an app that looks like the screenshots below:
2023-01-05 23:33:49 +00:00
2023-04-03 09:09:59 +00:00
<table><thead><tr>
<th><a href="#demo">iOS</a></th>
</tr></thead><tbody><tr><td>
2023-01-05 23:33:49 +00:00
2023-04-03 09:09:59 +00:00
![iOS screenshot](pathname:///mobile/nsios.png)
2023-01-05 23:33:49 +00:00
2023-04-03 09:09:59 +00:00
</td></tr></tbody></table>
2023-01-05 23:33:49 +00:00
## Integration Details
2023-04-03 09:09:59 +00:00
The discussion covers the NativeScript + Angular integration. Familiarity with
Angular and TypeScript is assumed.
2023-01-05 23:33:49 +00:00
The `@nativescript/core/file-system` package provides classes for file access.
2023-04-03 09:09:59 +00:00
The `File` class does not support binary data, but the file access singleton
from `@nativescript/core` does support reading and writing `ArrayBuffer`.
2023-01-05 23:33:49 +00:00
2023-04-03 09:09:59 +00:00
Reading and writing data require a URL. The following snippet searches typical
document folders for a specified filename:
2023-01-05 23:33:49 +00:00
```ts
2023-04-03 09:09:59 +00:00
import { Folder, knownFolders, path } from '@nativescript/core/file-system';
2023-01-05 23:33:49 +00:00
2023-04-03 09:09:59 +00:00
function get_url_for_filename(filename: string): string {
2023-01-05 23:33:49 +00:00
const target: Folder = knownFolders.documents() || knownFolders.ios.sharedPublic();
2023-04-03 09:09:59 +00:00
return path.normalize(target.path + "///" + filename);
2023-01-05 23:33:49 +00:00
}
```
2023-04-03 09:09:59 +00:00
#### Reading data
2023-01-05 23:33:49 +00:00
2023-04-03 09:09:59 +00:00
`getFileAccess().readBufferAsync` can read data:
2023-01-05 23:33:49 +00:00
```ts
2023-04-03 09:09:59 +00:00
import { getFileAccess } from '@nativescript/core';
/* find appropriate path */
const url = get_url_for_filename("SheetJSNS.xls");
/* get data */
const ab: ArrayBuffer = await getFileAccess().readBufferAsync(url);
2023-01-05 23:33:49 +00:00
/* read workbook */
2023-04-03 09:09:59 +00:00
const wb = read(ab);
2023-01-05 23:33:49 +00:00
```
2023-04-03 09:09:59 +00:00
#### Writing data
2023-01-05 23:33:49 +00:00
2023-04-03 09:09:59 +00:00
`getFileAccess().writeBufferAsync` can write data:
2023-01-05 23:33:49 +00:00
```ts
2023-04-03 09:09:59 +00:00
import { getFileAccess } from '@nativescript/core';
2023-01-05 23:33:49 +00:00
2023-04-03 09:09:59 +00:00
/* find appropriate path */
const url = get_url_for_filename("SheetJSNS.xls");
/* generate Uint8Array */
const u8: Uint8Array = write(wb, { bookType: 'xls', type: 'binary' });
/* attempt to save Uint8Array to file */
await getFileAccess().writeBufferAsync(url, u8);
2023-01-05 23:33:49 +00:00
```
## Demo
:::note
2023-04-03 09:09:59 +00:00
This demo was tested on an Intel Mac on 2023 April 03. NativeScript version
(as verified with `ns --version`) is `8.5.1`.
2023-01-05 23:33:49 +00:00
2023-04-03 09:09:59 +00:00
The iOS simulator runs iOS 16.2 on an iPhone 14 Pro Max.
2023-01-05 23:33:49 +00:00
2023-04-03 09:09:59 +00:00
:::
2023-01-05 23:33:49 +00:00
2023-04-03 09:09:59 +00:00
0) Follow the official Environment Setup instructions
2023-01-05 23:33:49 +00:00
1) Create a skeleton NativeScript + Angular app:
```bash
ns create SheetJSNS --ng
```
2) Launch the app in the iOS simulator to verify that the demo built properly:
```bash
cd SheetJSNS
ns run ios
```
(this may take a while)
Once the simulator launches and the test app is displayed, end the script by
selecting the terminal and entering the key sequence `CTRL + C`
3) From the project folder, install the library:
2023-05-07 13:58:36 +00:00
<CodeBlock language="bash">{`\
2023-04-27 09:12:19 +00:00
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
2023-05-07 13:58:36 +00:00
</CodeBlock>
2023-01-05 23:33:49 +00:00
4) To confirm the library was loaded, change the title to show the version. The
differences are highlighted.
2023-04-03 09:09:59 +00:00
`src/app/item/items.component.ts` should import the version string:
2023-01-05 23:33:49 +00:00
```ts title="src/app/item/items.component.ts"
// highlight-next-line
import { version } from 'xlsx';
import { Component, OnInit } from '@angular/core'
2023-04-03 09:09:59 +00:00
// ...
2023-01-05 23:33:49 +00:00
export class ItemsComponent implements OnInit {
items: Array<Item>
// highlight-next-line
version = `SheetJS - ${version}`;
constructor(private itemService: ItemService) {}
2023-04-03 09:09:59 +00:00
// ...
2023-01-05 23:33:49 +00:00
```
2023-04-03 09:09:59 +00:00
`src/app/item/items.component.html` should use the version in the title:
2023-01-05 23:33:49 +00:00
```xml title="src/app/item/items.component.html"
<!-- highlight-next-line -->
<ActionBar [title]="version"></ActionBar>
<GridLayout>
2023-04-03 09:09:59 +00:00
<!-- ... -->
2023-01-05 23:33:49 +00:00
```
Relaunch the app with `ns run ios` and the title bar should show the version.
![NativeScript Step 4](pathname:///mobile/nativescript4.png)
5) Add the Import and Export buttons to the template:
```xml title="src/app/item/items.component.html"
<ActionBar [title]="version"></ActionBar>
<!-- highlight-start -->
<StackLayout>
<StackLayout orientation="horizontal">
<Button text="Import File" (tap)="import()" style="padding: 10px"></Button>
<Button text="Export File" (tap)="export()" style="padding: 10px"></Button>
</StackLayout>
<!-- highlight-end -->
<ListView [items]="items">
2023-04-03 09:09:59 +00:00
<!-- ... -->
2023-01-05 23:33:49 +00:00
</ListView>
<!-- highlight-next-line -->
</StackLayout>
```
```ts title="src/app/item/items.component.ts"
// highlight-start
import { version, utils, read, write } from 'xlsx';
2023-04-03 09:09:59 +00:00
import { Dialogs, getFileAccess } from '@nativescript/core';
import { Folder, knownFolders, path } from '@nativescript/core/file-system';
2023-01-05 23:33:49 +00:00
// highlight-end
import { Component, OnInit } from '@angular/core'
import { Item } from './item'
import { ItemService } from './item.service'
// highlight-start
2023-04-03 09:09:59 +00:00
function get_url_for_filename(filename: string): string {
2023-01-05 23:33:49 +00:00
const target: Folder = knownFolders.documents() || knownFolders.ios.sharedPublic();
2023-04-03 09:09:59 +00:00
return path.normalize(target.path + "///" + filename);
2023-01-05 23:33:49 +00:00
}
// highlight-end
@Component({
selector: 'ns-items',
templateUrl: './items.component.html',
})
export class ItemsComponent implements OnInit {
items: Array<Item>
version: string = `SheetJS - ${version}`;
constructor(private itemService: ItemService) {}
ngOnInit(): void {
this.items = this.itemService.getItems()
}
// highlight-start
/* Import button */
async import() {
}
/* Export button */
async export() {
}
// highlight-end
}
```
Restart the app process and two buttons should show up at the top:
![NativeScript Step 5](pathname:///mobile/nativescript5.png)
2023-04-03 09:09:59 +00:00
6) Implement import and export by adding the highlighted lines:
2023-01-05 23:33:49 +00:00
```ts title="src/app/item/items.component.ts"
/* Import button */
async import() {
// highlight-start
/* find appropriate path */
2023-04-03 09:09:59 +00:00
const url = get_url_for_filename("SheetJSNS.xls");
2023-01-05 23:33:49 +00:00
try {
2023-04-03 09:09:59 +00:00
await Dialogs.alert(`Attempting to read from SheetJSNS.xls at ${url}`);
/* get data */
const ab: ArrayBuffer = await getFileAccess().readBufferAsync(url);
2023-01-05 23:33:49 +00:00
/* read workbook */
2023-04-03 09:09:59 +00:00
const wb = read(ab);
2023-01-05 23:33:49 +00:00
/* grab first sheet */
const wsname: string = wb.SheetNames[0];
const ws = wb.Sheets[wsname];
/* update table */
this.items = utils.sheet_to_json<Item>(ws);
2023-04-03 09:09:59 +00:00
} catch(e) { await Dialogs.alert(e.message); }
2023-01-05 23:33:49 +00:00
// highlight-end
}
/* Export button */
async export() {
// highlight-start
/* find appropriate path */
2023-04-03 09:09:59 +00:00
const url = get_url_for_filename("SheetJSNS.xls");
2023-01-05 23:33:49 +00:00
try {
/* create worksheet from data */
const ws = utils.json_to_sheet(this.items);
/* create workbook from worksheet */
const wb = utils.book_new();
utils.book_append_sheet(wb, ws, "Sheet1");
2023-04-03 09:09:59 +00:00
/* generate Uint8Array */
const u8: Uint8Array = write(wb, { bookType: 'xls', type: 'buffer' });
2023-01-05 23:33:49 +00:00
2023-04-03 09:09:59 +00:00
/* attempt to save Uint8Array to file */
await getFileAccess().writeBufferAsync(url, u8);
await Dialogs.alert(`Wrote to SheetJSNS.xls at ${url}`);
} catch(e) { await Dialogs.alert(e.message); }
2023-01-05 23:33:49 +00:00
// highlight-end
}
```
2023-04-03 09:09:59 +00:00
### iOS
2023-01-05 23:33:49 +00:00
2023-04-03 09:09:59 +00:00
Relaunch the app with `ns run ios`
2023-01-05 23:33:49 +00:00
The app can be tested with the following sequence in the simulator:
2023-04-03 09:09:59 +00:00
- Tap "Export File". A dialog will print where the file was written
2023-01-05 23:33:49 +00:00
2023-04-03 09:09:59 +00:00
- Open the file with a spreadsheet editor.
2023-01-05 23:33:49 +00:00
2023-04-03 09:09:59 +00:00
After the header row, insert a row with cell A2 = 0, B2 = SheetJS, C2 = Library:
2023-01-05 23:33:49 +00:00
2023-04-03 09:09:59 +00:00
```
id | name | role
0 | SheetJS | Library
1 | Ter Stegen | Goalkeeper
3 | Piqué | Defender
2023-01-05 23:33:49 +00:00
...
```
2023-04-03 09:09:59 +00:00
Restart the app after saving the file.
- Tap "Import File". A dialog will print the path of the file that was read.
2023-01-05 23:33:49 +00:00
The first item in the list will change:
![NativeScript Step 7](pathname:///mobile/nativescript7.png)