{"id":19813832,"url":"https://github.com/azer0s/nativescript-calculator-demo","last_synced_at":"2026-05-19T14:39:33.950Z","repository":{"id":136692976,"uuid":"159333175","full_name":"Azer0s/NativeScript-Calculator-Demo","owner":"Azer0s","description":"A NativeScript with Angular demo project/tutorial","archived":false,"fork":false,"pushed_at":"2018-11-27T12:40:27.000Z","size":2613,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-07-23T03:32:44.546Z","etag":null,"topics":["calculator","nativescript","nativescript-angular","tutorial"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"unlicense","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Azer0s.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-11-27T12:37:35.000Z","updated_at":"2024-05-30T16:45:12.000Z","dependencies_parsed_at":null,"dependency_job_id":"08014ef5-ec45-4ef7-b5eb-77db797c62da","html_url":"https://github.com/Azer0s/NativeScript-Calculator-Demo","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/Azer0s/NativeScript-Calculator-Demo","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Azer0s%2FNativeScript-Calculator-Demo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Azer0s%2FNativeScript-Calculator-Demo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Azer0s%2FNativeScript-Calculator-Demo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Azer0s%2FNativeScript-Calculator-Demo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Azer0s","download_url":"https://codeload.github.com/Azer0s/NativeScript-Calculator-Demo/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Azer0s%2FNativeScript-Calculator-Demo/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":272582515,"owners_count":24959422,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-28T02:00:10.768Z","response_time":74,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["calculator","nativescript","nativescript-angular","tutorial"],"created_at":"2024-11-12T09:37:26.308Z","updated_at":"2026-05-19T14:39:33.920Z","avatar_url":"https://github.com/Azer0s.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# NativeScript: A short introduction\n\n## Intro\n\nNativeScript is a cross-platform app development framework that lets you build native iOS and Android applications using TypeScript or JavaScript code. NativeScript utilizes either Angular or Vue.js as the underlying UI technology and converts the UI (no matter what framework you write in) to native components (hence: **Native**Script).\n\n## Requirements\n\nTo install and run NativeScript you need to have both Node.js and the Android SDK installed on your development machine. \n\nOn Windows you can install these tools using Chocolatey:\n\n```bash\n#install Chocolatey\nPS C:\\WINDOWS\\system32\u003e Set-ExecutionPolicy Bypass -Scope Process -Force; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))\n#install Node.js\nPS C:\\WINDOWS\\system32\u003e choco install nodejs -y\n#install Android SDK\nPS C:\\WINDOWS\\system32\u003e choco install androidstudio -y\n```\n\nAnd on Debian based Linux distros like so:\n\n```bash\n$ sudo apt update\n#add dependency for Node.js\n$ curl -sL https://deb.nodesource.com/setup_11.x | sudo -E bash -\n#install Node.js\n$ sudo apt install -y nodejs\n#install Android SDK\n$ curl https://gist.githubusercontent.com/bmc08gt/8077443/raw/48873eed88a015956c13681548385e4a01b6acbd/setup_android_studio.sh | sudo bash\n```\n\n## Install\n\nThe NativeScript install itself is quite easy and the same no matter the operating system. I will be proceeding on a Linux system (Ubuntu 18.04 LTS 64bit to be precise) since I prefer the Linux bash an the build chain on Linux over the Windows one.\n\n```bash\n$ cd ~\n$ sudo npm i -g nativescript\n$ tns --version\n#if correctly installed, this should output the version of NativeScript CLI\n```\n\nFurthermore, you will need to install the NativeScript Playground app and the NativeScript Preview app on your smartphone. This will be needed to test, debug and run the app.\n\n## Getting started\n\nIn the following tutorial we will be writing a simple calculator application using NativeScript. I will be using Visual Studio Code with the NativeScript extension but you can use the IDE/editor of your choice.\n\n### Creating the project\n\nLets start by creating all the necessary project files and installing the npm dependencies for the project. We can do that  with the `tns create` command.\n\n```bash\n$ mkdir -p ~/workspace\n$ cd ~/workspace\n$ tns create NativeScriptCalculator --ng\n$ cd NativeScriptCalculator\n$ npm i\n$ tns preview\n```\n\nNow, switch to your phone, open the Playground app and scan the QR code on the screen.\nYou should see something similar to this:\n\n\u003cimg src=\"Screenshot_20181127-102730_Preview.jpg\"/\u003e\n\nNow that NativeScript is running, we can switch to our development environment and start programming.\n\n## Project structure\n\nWhen we open our project, we will find that the structure of the project is quite similar to that of an Angular project. Lets take a closer look at it:\n\n```bash\n$ sudo apt install -y tree\n$ tree -d ~/workspace/NativeScriptCalculator\n├── App_Resources #here, app resources are stored for each platform\n│   ├── Android\n│   └── iOS\n├── hooks #in the hooks folder you can find the NativeScript build pipeline\n├── node_modules #the node_modules folder stores our dependencies and libraries\n├── platforms #the platforms folder stores operating system specific code\n│   └── android\n└── src\n    └── app\n        └── item #the item component was generated by NativeScript\n```\n\n## The UI\n\nAs we will be writing the UI from scratch, we can just delete the `Item` component generated by the `tns create` command and write directly to the `app.component`. Our `src` folder should now look like so:\n\n\u003cimg src=\"Capture.PNG\"/\u003e\n\nOur UI code (in `app.component.html`) will look like so:\n\n```html\n\u003cGridLayout columns=\"*, *, *, *\" rows=\"auto, auto, *, *, *, *, *\" \u003e\n  \u003cLabel class=\"result\" text=\"\" colSpan=\"4\"\u003e\u003c/Label\u003e\n  \u003cLabel text=\"\" row=\"1\" colSpan=\"4\"\u003e\u003c/Label\u003e\n  \u003cButton row=\"2\" class=\"numbers\" col=\"0\" text=\"7\"\u003e\u003c/Button\u003e\n  \u003cButton row=\"2\" class=\"numbers\" col=\"1\" text=\"8\"\u003e\u003c/Button\u003e\n  \u003cButton row=\"2\" class=\"numbers\" col=\"2\" text=\"9\"\u003e\u003c/Button\u003e\n  \u003cButton row=\"2\" class=\"controls\" col=\"4\" text=\"+\"\u003e\u003c/Button\u003e\n  \u003cButton row=\"3\" class=\"numbers\" col=\"0\" text=\"4\"\u003e\u003c/Button\u003e\n  \u003cButton row=\"3\" class=\"numbers\" col=\"1\" text=\"5\"\u003e\u003c/Button\u003e\n  \u003cButton row=\"3\" class=\"numbers\" col=\"2\" text=\"6\"\u003e\u003c/Button\u003e\n  \u003cButton row=\"3\" class=\"controls\" col=\"4\" text=\"-\"\u003e\u003c/Button\u003e\n  \u003cButton row=\"4\" class=\"numbers\" col=\"0\" text=\"1\"\u003e\u003c/Button\u003e\n  \u003cButton row=\"4\" class=\"numbers\" col=\"1\" text=\"2\"\u003e\u003c/Button\u003e\n  \u003cButton row=\"4\" class=\"numbers\" col=\"2\" text=\"3\"\u003e\u003c/Button\u003e\n  \u003cButton row=\"4\" class=\"controls\" col=\"3\" text=\"X\"\u003e\u003c/Button\u003e\n  \u003cButton row=\"5\" class=\"numbers\" col=\"0\" colSpan=\"2\" text=\"0\"\u003e\u003c/Button\u003e\n  \u003cButton row=\"5\" class=\"controls\" col=\"2\" text=\".\"\u003e\u003c/Button\u003e\n  \u003cButton row=\"5\" class=\"controls\" col=\"3\" text=\"/\"\u003e\u003c/Button\u003e\n  \u003cButton row=\"6\" class=\"controls\" col=\"0\" text=\"↶\"\u003e\u003c/Button\u003e\n  \u003cButton row=\"6\" class=\"controls\" col=\"1\" text=\"⌧\"\u003e\u003c/Button\u003e\n  \u003cButton row=\"6\" class=\"controls\" col=\"2\" colSpan=\"2\" text=\"=\"\u003e\u003c/Button\u003e\n\u003c/GridLayout\u003e\n```\n\nAnd our styling (in `app.css`) like so:\n\n```css\n@import '~nativescript-theme-core/css/core.light.css';\n\nbutton, label{\n    horizontal-align: center;    \n}\n\ngridlayout{\n    background-color: black;\n}\n\nlabel {\n    font-size: 36;\n    color: white;\n}\n\nlabel.result {\n    font-size: 42;\n    horizontal-align: left;\n    color: white;\n}\n\nbutton{\n    font-size: 36;\n    width: 100%;\n}\n\n.controls{\n    background-color: rgb(255, 149, 0);\n    color: white;\n}\n\n.numbers{\n    background-color: #C0C0C0;\n    color: black;\n}\n```\n\nYour app should look like this:\n\n\u003cimg src=\"Screenshot_20181127-125010_Preview.jpg\"/\u003e\n\nAs you might have already noticed, we are not working with HTML tags. Instead, we use the Angular components exposed by the NativeScript API. The NativeScript API is the core system that makes NativeScript work. It takes Vue.js or Angular UI declarations and converts them to native components.\n\n## The logic\n\nNow that we have a nice looking UI, lets add some logic to it. Our calculator should be able to append an operation, undo operations and clear the screen. When a users clicks on the `=` button, the expression should be evaluated and the result shall be printed to the screen. \n\nSo lets take a look at our `app.component.ts`:\n\n```typescript\nimport { Component } from \"@angular/core\";\n\n@Component({\n    selector: \"calculator\",\n    moduleId: module.id,\n    templateUrl: \"./app.component.html\",\n})\nexport class AppComponent { \n    constructor() { }\n    operation: string = '';\n    result: string= '';\n\n    append(element: string){\n        this.operation += element;\n    }\n    \n    undo(){\n        if (this.operation != ''){\n            this.operation = this.operation.slice(0, -1)\n        }\n    }\n    \n    clear(){\n        this.operation = '';\n    }\n    \n    evaluate(){\n        this.result = eval(this.operation.replace(\"X\",\"*\"));\n        console.log(this.result);\n    }\n\n    ngOnInit(): void {\n    }\n}\n```\n\nNow we just need to register these events in `app.component.html`. We do that with `(tap)` (which behaves similar to `(click)` in regular Angular). We also bind the operation and result variable with the two labels at the top. Just like in regular Angular, we do that with `{{ }}`.\n\n```html\n\u003cGridLayout columns=\"*, *, *, *\" rows=\"auto, auto, *, *, *, *, *\" \u003e\n  \u003cLabel class=\"result\" text=\"{{ result }}\" colSpan=\"4\"\u003e\u003c/Label\u003e\n  \u003cLabel text=\"{{ operation }}\" row=\"1\" colSpan=\"4\"\u003e\u003c/Label\u003e\n  \u003cButton (tap)=\"append('7')\" row=\"2\" class=\"numbers\" col=\"0\" text=\"7\"\u003e\u003c/Button\u003e\n  \u003cButton (tap)=\"append('8')\" row=\"2\" class=\"numbers\" col=\"1\" text=\"8\"\u003e\u003c/Button\u003e\n  \u003cButton (tap)=\"append('9')\" row=\"2\" class=\"numbers\" col=\"2\" text=\"9\"\u003e\u003c/Button\u003e\n  \u003cButton (tap)=\"append('+')\" row=\"2\" class=\"controls\" col=\"4\" text=\"+\"\u003e\u003c/Button\u003e\n  \u003cButton (tap)=\"append('4')\" row=\"3\" class=\"numbers\" col=\"0\" text=\"4\"\u003e\u003c/Button\u003e\n  \u003cButton (tap)=\"append('5')\" row=\"3\" class=\"numbers\" col=\"1\" text=\"5\"\u003e\u003c/Button\u003e\n  \u003cButton (tap)=\"append('6')\" row=\"3\" class=\"numbers\" col=\"2\" text=\"6\"\u003e\u003c/Button\u003e\n  \u003cButton (tap)=\"append('-')\" row=\"3\" class=\"controls\" col=\"4\" text=\"-\"\u003e\u003c/Button\u003e\n  \u003cButton (tap)=\"append('1')\" row=\"4\" class=\"numbers\" col=\"0\" text=\"1\"\u003e\u003c/Button\u003e\n  \u003cButton (tap)=\"append('2')\" row=\"4\" class=\"numbers\" col=\"1\" text=\"2\"\u003e\u003c/Button\u003e\n  \u003cButton (tap)=\"append('3')\" row=\"4\" class=\"numbers\" col=\"2\" text=\"3\"\u003e\u003c/Button\u003e\n  \u003cButton (tap)=\"append('X')\" row=\"4\" class=\"controls\" col=\"3\" text=\"X\"\u003e\u003c/Button\u003e\n  \u003cButton (tap)=\"append('0')\" row=\"5\" class=\"numbers\" col=\"0\" colSpan=\"2\" text=\"0\"\u003e\u003c/Button\u003e\n  \u003cButton (tap)=\"append('.')\" row=\"5\" class=\"controls\" col=\"2\" text=\".\"\u003e\u003c/Button\u003e\n  \u003cButton (tap)=\"append('/')\" row=\"5\" class=\"controls\" col=\"3\" text=\"/\"\u003e\u003c/Button\u003e\n  \u003cButton (tap)=\"undo()\" row=\"6\" class=\"controls\" col=\"0\" text=\"↶\"\u003e\u003c/Button\u003e\n  \u003cButton (tap)=\"clear()\" row=\"6\" class=\"controls\" col=\"1\" text=\"⌧\"\u003e\u003c/Button\u003e\n  \u003cButton (tap)=\"evaluate()\" row=\"6\" class=\"controls\" col=\"2\" colSpan=\"2\" text=\"=\"\u003e\u003c/Button\u003e\n\u003c/GridLayout\u003e\n```\n\nAnd now we can do some calculations! The app should look like so:\n\n\u003cimg src=\"Screenshot_20181127-125046_Preview.jpg\"/\u003e\n\n## Adding error handling\n\nSo now that we have all the functionality in our app, lets add some error handling to prevent the application to crash when the calculation doesn't evaluate. When the calculation fails, we want a dialog to pop up and an error information to appear in the log.\n\nFirst, we need to import the dialog module in `app.component.ts`:\n\n```typescript\nimport dialogs = require(\"ui/dialogs\");\n```\n\nNext, lets add a try/catch block in our `evaluate` method:\n\n```typescript\nevaluate(){\n    try{\n        this.result = eval(this.operation.replace(\"X\",\"*\"));\n        console.log(this.result);\n    }catch(e){\n        console.error(\"Cannot evaluate expression!\");\n        dialogs.alert({title: 'Error', message: 'Cannot evaluate expression!', okButtonText: 'OK'});\n    }\n}\n```\n\nLets test this out. The dialog should look like so:\n\n\u003cimg src=\"Screenshot_20181127-125028_Preview.jpg\"/\u003e\n\n## Conclusion\n\nAnd Voila! There we have our own little calculator written in NativeScript! In conclusion I can say that NativeScript with Angular is definitely a nice framework which makes cross-platform development way easier than doing it the old-fashioned way (that is having a native application for each platform) but it's immaturity and small community make it quite a lot harder to use than other well-established cross-platform SDKs like React Native, Flutter or Ionic. Give NativeScript a couple more months, a more engaged and better integrated community and you have yourself the perfect cross-platform toolkit.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fazer0s%2Fnativescript-calculator-demo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fazer0s%2Fnativescript-calculator-demo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fazer0s%2Fnativescript-calculator-demo/lists"}