diff --git a/._.DS_Store b/._.DS_Store new file mode 100755 index 00000000..8e82ed96 Binary files /dev/null and b/._.DS_Store differ diff --git a/.github/workflows/scrape-plugins.yml b/.github/workflows/scrape-plugins.yml old mode 100644 new mode 100755 diff --git a/.gitignore b/.gitignore old mode 100644 new mode 100755 diff --git a/.husky/.gitignore b/.husky/.gitignore old mode 100644 new mode 100755 diff --git a/.prettierignore b/.prettierignore old mode 100644 new mode 100755 diff --git a/.prettierrc b/.prettierrc old mode 100644 new mode 100755 diff --git a/.vitepress/config.js b/.vitepress/config.js old mode 100644 new mode 100755 index 46de274d..39d2d1a1 --- a/.vitepress/config.js +++ b/.vitepress/config.js @@ -68,13 +68,18 @@ module.exports = { nav: [ { - text: 'Docs', + text: 'Guides', link: '/introduction', activeMatch: '^/(?!plugins)', }, + { + text: 'Components', + link: '/components/index', + activeMatch: '^/components', + }, { text: 'API', - link: '/api-reference', + link: 'https://docs.nativescript.org/api-reference', activeMatch: '^/api-reference', target: '_blank', }, @@ -102,7 +107,7 @@ module.exports = { sidebar: { '/best-practices/': getBestPracticeSidebar(), '/plugins/': getPluginsSidebar(), - + '/components/': getComponentsSidebar(), // fallback '/': getSidebar(), }, @@ -490,6 +495,8 @@ function getSidebar() { text: 'Basics', children: [ { text: 'Introduction', link: '/introduction' }, + { text: 'Application Architecture', link: '/application-architecture' }, + { text: 'Project Structure', link: '/project-structure' }, { text: 'Environment Setup', link: '/environment-setup', @@ -509,38 +516,116 @@ function getSidebar() { ], }, { - text: 'Running & Building', + text: 'Development Workflow', children: [ { - text: 'Webpack', - link: '/webpack', + text: 'CLI Basics', + link: '/development-workflow/cli-basics', + }, + { + text: 'Debugging', + link: '/development-workflow/debugging', + }, + { + text: 'Running on Virtual Device', + link: '/development-workflow/running-on-virtual-device', + }, + { + text: 'Running on Physical Device', + link: '/development-workflow/running-on-physical-device', + }, + /*{ + text: 'HMR', + link: '/development-workflow/hmr' + },*/ + { + text: 'Testing', + link: '/development-workflow/testing', + }, + { + text: 'Using Packages', + link: '/development-workflow/using-packages', + }, + { + text: 'Updating', + link: '/development-workflow/updating', + }, + { + text: 'Choosing an Editor', + link: '/development-workflow/choosing-an-editor', }, ], }, { - text: 'UI & Styling', + text: 'App_Resources', children: [ { - text: 'App_Resources', + text: 'Understanding App_Resources', link: '/app-resources', }, - { - text: 'UI & Styling', - link: '/ui-and-styling', - }, - { text: 'Interaction', link: '/interaction' }, ], }, { - text: 'Networking', + text: '@nativescript/core', + children: [ + { text: 'Application', link: '/nativescript-core/application' }, + { + text: 'ApplicationSettings', + link: '/nativescript-core/application-settings', + }, + { text: 'Color', link: '/nativescript-core/color' }, + { text: 'Connectivity', link: '/nativescript-core/connectivity' }, + //{ text: 'Virtual Array', link: '/nativescript-core/virtual-array' }, + { text: 'FileSystem', link: '/nativescript-core/file-system' }, + { text: 'Fps Meter', link: '/nativescript-core/fps-meter' }, + { text: 'Http', link: '/nativescript-core/http' }, + { text: 'ImageSource', link: '/nativescript-core/image-source' }, + { text: 'Observable', link: '/nativescript-core/observable' }, + { + text: 'Observable Array', + link: '/nativescript-core/observable-array', + }, + { text: 'Platform', link: '/nativescript-core/platform' }, + { text: 'Trace', link: '/nativescript-core/trace' }, + { text: 'Utils', link: '/nativescript-core/utils' }, + { text: 'Xml Parser', link: '/nativescript-core/xml-parser' }, + ], + }, + { + text: '@nativescript/webpack', children: [ - { text: 'Http', link: '/http' }, { - text: 'Connectivity', - link: '/connectivity', + text: 'Overview', + link: 'webpack/overview', + }, + { + text: 'Flags & their usage', + link: 'webpack/flags-and-their-usage', + }, + + { + text: 'Using .env files', + link: 'webpack/using-dot-env-files', + }, + { + text: 'Global "magic" variables', + link: 'webpack/global-magic-variables', + }, + { + text: 'Examples of configurations', + link: 'webpack/examples-of-configurations', + }, + { + text: 'Plugin API', + link: 'webpack/plugin-api', + }, + { + text: 'Webpack API', + link: 'webpack/api', }, ], }, + // { // text: 'Performance', // children: [{ text: 'Webpack/Bundle Optimizations', link: '/performance' }], @@ -559,11 +644,40 @@ function getSidebar() { ], }, { - text: 'Advanced Concepts', + text: 'Architecture Concepts', children: [ { - text: 'Advanced Concepts', + text: 'Data Binding', + link: '/architecture-concepts/data-binding', + }, + { + text: 'Adding Objective C/Swift Code', + link: '/architecture-concepts/adding-objectivec-swift-code', + }, + { text: 'Navigation', link: '/architecture-concepts/navigation' }, + { + text: 'Marshalling', + link: '/architecture-concepts/marshalling', + }, + { + text: 'Metadata', + link: '/architecture-concepts/metadata', + }, + { + text: 'Memory Management', + link: '/architecture-concepts/memory-management', + }, + { + text: 'Custom Application and Activity', + link: '/architecture-concepts/custom-application-and-activity', + }, + /*{ + text: 'Layout Process', link: '/advanced-concepts', + },*/ + { + text: 'Property System', + link: '/architecture-concepts/property-system', }, ], }, @@ -651,3 +765,117 @@ function getBestPracticeSidebar() { }, ] } + +function getComponentsSidebar() { + return [ + { + text: 'Components', + children: [ + { + text: 'Styling', + link: '/components/styling', + }, + { + text: 'Interaction', + link: '/components/interaction', + }, + { + text: 'ActionBar', + link: '/components/actionbar', + }, + { + text: 'ActivityIndicator', + link: '/components/activityindicator', + }, + { + text: 'Button', + link: '/components/button', + }, + { + text: 'DatePicker', + link: '/components/datepicker', + }, + { + text: 'Frame', + link: '/components/frame', + }, + { + text: 'HtmlView', + link: '/components/htmlview', + }, + { + text: 'Image', + link: '/components/image', + }, + { + text: 'Label', + link: '/components/label', + }, + { + text: 'ListPicker', + link: '/components/listpicker', + }, + { + text: 'ListView', + link: '/components/listview', + }, + { + text: 'Page', + link: '/components/page', + }, + { + text: 'Placeholder', + link: '/components/placeholder', + }, + { + text: 'Progress', + link: '/components/progress', + }, + { + text: 'Repeator', + link: '/components/repeator', + }, + { + text: 'ScrollView', + link: '/components/scrollview', + }, + { + text: 'SearchBar', + link: '/components/searchbar', + }, + { + text: 'SegmentedBar', + link: '/components/segmentedbar', + }, + { + text: 'Slider', + link: '/components/slider', + }, + { + text: 'Switch', + link: '/components/switch', + }, + { + text: 'TabView', + link: '/components/tabview', + }, + { + text: 'TextField', + link: '/components/textfield', + }, + { + text: 'TextView', + link: '/components/textview', + }, + { + text: 'TimePicker', + link: '/components/timepicker', + }, + { + text: 'WebView', + link: '/components/webview', + }, + ], + }, + ] +} diff --git a/.vitepress/theme/index.js b/.vitepress/theme/index.js old mode 100644 new mode 100755 diff --git a/.vitepress/theme/nativescript-theme/index.js b/.vitepress/theme/nativescript-theme/index.js old mode 100644 new mode 100755 index bfbd26b0..f738034e --- a/.vitepress/theme/nativescript-theme/index.js +++ b/.vitepress/theme/nativescript-theme/index.js @@ -689,7 +689,6 @@ function H(e, t, n, r, o, i, a, c, u) { g && (f.__E = f.__ = null), (f.__e = !1) } else t.__e = M(n.__e, t, n, r, o, i, a, u) - ;(l = s.diffed) && l(t) } catch (e) { s.__e(e, t, n) @@ -8988,7 +8987,6 @@ var script = defineComponent({ }) watch(currentTab, function (next, prev) { var _tabContainer$value, _tabContainer$value2 - ;(_tabContainer$value = tabContainer.value) === null || _tabContainer$value === void 0 ? void 0 diff --git a/.vitepress/theme/nativescript-theme/plugins/code-blocks.js b/.vitepress/theme/nativescript-theme/plugins/code-blocks.js old mode 100644 new mode 100755 diff --git a/.vitepress/theme/nativescript-theme/plugins/device-frame.js b/.vitepress/theme/nativescript-theme/plugins/device-frame.js old mode 100644 new mode 100755 diff --git a/.vitepress/theme/nativescript-theme/plugins/flavor-container.js b/.vitepress/theme/nativescript-theme/plugins/flavor-container.js old mode 100644 new mode 100755 diff --git a/.vitepress/theme/nativescript-theme/plugins/index.js b/.vitepress/theme/nativescript-theme/plugins/index.js old mode 100644 new mode 100755 diff --git a/.vitepress/theme/nativescript-theme/plugins/prism-lang-cli.js b/.vitepress/theme/nativescript-theme/plugins/prism-lang-cli.js old mode 100644 new mode 100755 diff --git a/.vitepress/theme/nativescript-theme/styles.css b/.vitepress/theme/nativescript-theme/styles.css old mode 100644 new mode 100755 diff --git a/README.md b/README.md old mode 100644 new mode 100755 index 591097a6..f87635a1 --- a/README.md +++ b/README.md @@ -6,13 +6,13 @@ npm i npm start ``` - ## Important Note about Plugin Docs Plugins docs are automatically synced every night via cron job with various plugin workspace repos, for example: -* https://github.com/NativeScript/firebase -* https://github.com/NativeScript/plugins -* https://github.com/NativeScript/payments + +- https://github.com/NativeScript/firebase +- https://github.com/NativeScript/plugins +- https://github.com/NativeScript/payments Each plugin workspace can manage it's own README's for documentation and this main central docs will keep itself in sync with them every night. If you are wanting to modify any plugin documentation, you can do via their plugin workspaces as listed above. diff --git a/advanced-concepts.md b/advanced-concepts.md old mode 100644 new mode 100755 diff --git a/app-resources.md b/app-resources.md old mode 100644 new mode 100755 diff --git a/application-architecture.md b/application-architecture.md new file mode 100755 index 00000000..f79c5c4c --- /dev/null +++ b/application-architecture.md @@ -0,0 +1,241 @@ +--- +title: Application Architecture +--- + +## Application Architecture + +In this article we are going to review the architecture of a NativeScript application built with the Core Framework. It will cover the entry point of the app, the decomposition into modules, styling the application and data binding. + +### Entry Point + +The entry point for a core NativeScript application is declared in the app root folder's package.json file under the property main. This is usually declared as app.js or app.ts in case you have created a TypeScript project. You can use this file to perform app-level initializations, but the primary purpose of the file is to pass control to the app's root module. To do this, you need to call the `Application.run()` method and pass a `NavigationEntry` with the desired `moduleName` as the path to the root module relative to your /app folder. + +```js +import { Application } from '@nativescript/core' +Application.run({ moduleName: 'app-root' }) +``` + +```ts +import { Application } from '@nativescript/core' +Application.run({ moduleName: 'app-root' }) +``` + +:::tip Note +**Important:** Do not place any code after the Application.run() method call as it will not be executed on iOS. + +**Important:** Prior to NativeScript 4.0.0 the start() method automatically created an underlying root Frame instance that wrapped your pages. The new run() method will set up the root element of the provided module as the application root element. This effectively means that apart from [Page](/ui/components.md#page) you can now have other roots of your app like [TabView](/ui/components.md#page) and [SideDrawer](/introduction.md#drawer). The start() method is now marked as deprecated. +::: + +### Application Modules + +The core NativeScript framework is separated in modules. As a minimum a module is represented by a markup `.xml` file holding the UI markup. From there, you can also add backend `.js`or `.ts` file for executing business logic, a styling `.css` file. The important thing for these additional files is to share the same name with the `.xml` file. For example, the following files make a module: + +- `home-page.xml` +- `home-page.js` or `home-page.ts` +- `home-page.css` + +All functions that are exported by the business logic file are available for binding to the template. The business logic file is a good place to handle events or bind context to the UI, for example below the `loaded` event is bound to a [Page](/ui/components.md#page) component: + +```xml + + + + + +``` + +```js +// home-page.js +export function onPageLoaded(args) { + console.log('Page Loaded') +} +``` + +```ts +// home-page.ts +import { EventData } from '@nativescript/core' + +export function onPageLoaded(args: EventData): void { + console.log('Page Loaded') +} +``` + + + +```css +/* home-page.css */ +.page { + background-color: teal; +} +``` + +:::tip Note +Note that we have put a naming convention in place for modules. Their file names can end in either -root or -page, marking the type of the module. The naming convention isn't mandatory. It is put in place for easier and effortless webpack bundling. +::: + +### Root Modules + +These modules are used as the root for UI containers. Currently, there are only two types of UI containers in a NativeScript app: + +- The app container - it is only one. You set its root module by passing it to the `Application.run()` method. +- Modal view containers - You can have a lot of these. You set a modal view's root module by passing it to the `showModal()` method of any UI component. + +A root module can have only one component at the root of its content. You can put virtually any UI component as a root, but the most commonly used components are the one that can have children - the [layouts](/ui/components.md#layout-containers), [TabView](/ui/components.md#tabview), SideDrawer or [Frame](/ui/components.md#frame). The `Frame` component can't have children, but it can display and navigate between page modules. + +Note that the root module will be loaded regardless of navigations until its UI container disappears. This basically means that the app root module will always be loaded. A modal view root module will be unloaded when the modal view is closed. + +Here is an example of an app root module: + +```xml + + +``` + +```js +// app-root.js +export function onFrameLoaded(args) { + console.log('Frame Loaded') +} +``` + +```ts +// app-root.ts +import { EventData } from '@nativescript/core' + +export function onFrameLoaded(args: EventData): void { + console.log('Frame Loaded') +} +``` + +### Page Modules + +These modules represent pages and are used by the Frame component to implement forward and backward navigation. You can pass these modules to the `Frame` in one of the two ways: + +- The `defaultPage` attribute - the page module set in this attribute will be initially shown by the Frame. +- The `navigate()` method - this method forces the `Frame` to hide the currently navigated page module and to show the page module passed as parameter. + +Navigation is covered in detail in the [navigation](/architecture-concepts/navigation.md) article. + +Page modules must always have the `Page` component at the root of their content. Below is a code sample of a page module: + +```xml + + + + + +``` + +```js +// home-page.js +export function onPageLoaded(args) { + console.log('Page Loaded') +} +``` + +```ts +// home-page.ts +import { EventData } from '@nativescript/core' + +export function onPageLoaded(args: EventData): void { + console.log('Page Loaded') +} +``` + +### Global App Styling + +The NativeScript Core framework also provides a way to set application-wide styling. The default place to do that is in the `app.css` file in the app root folder. All css rules that are declared in this file will be applied to all application modules. + +You can change the name of the file from which the application-wide CSS is loaded. You need to do the change before the `Application.run()` method is called as shown below: + +```js +import { Application } from '@nativescript/core' +Application.setCssFileName('style.css') + +Application.run({ moduleName: 'main-page' }) +``` + +Styling is covered in detail in the [styling](/ui/styling.md) article. + +### Supporting Multiple Screens + +Mobile applications are running on different devices with different screen sizes and form factors. NativeScript provides a way to define different files (`.js`, `.css`, `.xml`, etc.) to be loaded based on the **screen's size**, **platform**, and **orientation** of the current device. The approach is somewhat similar to [multi screen support in Android](http://developer.android.com/guide/practices/screens_support.html). There is a set of _qualifiers_ that can be added inside the file that will be respected when the file is loaded. Here is how the file should look: + +_\[.\]\*.\_ + +In the next section, we will go through the list of supported qualifiers. + +### Screen Size Qualifiers + +All the values in screen size qualifiers are in `density independent pixels (DP)` — meaning it corresponds to the physical dimensions of the screen. The assumptions are that there are \~160 DP per inch. For example, according to Android guidelines, if the device's smaller dimension is more than 600 dp (~3.75 inches), it is probably a tablet. + +- `minWH` - The smaller dimension (width or height) should be at least X dp.# +- `minW` - Width should be at least `X` dp. +- `minH` - Height should be at least `X` dp. + +Example (separate XML file for tablet and phone): + +- `main-page.minWH600.xml` - XML file to be used for tablet devices. +- `main-page.xml` - XML to be used for phones. + +### Platform Qualifiers + +- `android` – Android platform +- `ios` – iOS platform + +Example (platform specific files): + +- `app.android.css` - CSS styles for Android. +- `app.ios.css` - CSS styles for iOS. + The platform qualifiers are executed **during build time**, while the others are executed **during runtime**. + For example, the `app.ios.css` file will not be taken into consideration when building for the Android platform. On the contrary, the **screen size** qualifiers will be considered just after the application runs on a device with specific screen size. + +### Orientation Qualifiers + +- `land` - orientation is in landscape mode. +- `port` - orientation is in portrait mode. + :::tip Note + qualifiers are taken into account when the page is loading. However, changing the device orientation will not trigger a page reload and will not change the current page. + ::: + +### Data Binding + +Data binding is the process of connecting application user interface (UI) to a data object (code). In NativeScript each UI component can be bound to what is called a binding source. You can set a binding source to each UI component through its `bindingContext` property. However, this is not the best way to implement binding. +The `bindingContext` property is inheritable across the visual tree. This means that you can set `bindingContext` to the root component of your module and it will be available to all child components. The binding is then described in the XML using the mustache syntax. + +In the following example we set the **bindingContext** of the [Page](/ui/components.md#page) in its `loaded` event handler and then bind the property to the [Label](/ui/components.md#label) text. + +```xml + + + + + +``` + +```js +// home-page.js +import { fromObject } from '@nativescript/core' + +export function onPageLoaded(args) { + const page = args.object + const source = fromObject({ text: 'Hooray! Home Page loaded!' }) + page.bindingContext = source +} +``` + +```ts +// home-page.ts +import { Page, EventData, fromObject } from '@nativescript/core' + +export function onPageLoaded(args: EventData): void { + const page: Page = args.object + const source = fromObject({ text: 'Hooray! Home Page loaded!' }) + page.bindingContext = source +} +``` + +Binding is covered in detail in the [data binding](/architecture-concepts/data-binding.md) article. diff --git a/architecture-concepts/adding-objectivec-swift-code.md b/architecture-concepts/adding-objectivec-swift-code.md new file mode 100755 index 00000000..9207bd92 --- /dev/null +++ b/architecture-concepts/adding-objectivec-swift-code.md @@ -0,0 +1,110 @@ +--- +title: Adding ObjectiveC/Swift Code +--- + +## Adding ObjectiveC/Swift Code + +For the Objective-C/Swift symbols to be accessible by the Nativescript runtimes the following criteria should be met: + +**1)** They need to be compiled and linked + +**2)** Metadata needs to be generated for them + +The first task is done by the NativeScript CLI by adding the source files to the generated _.xcodeproj_. For the second one the Metadata Generator needs to find a [module.modulemap](https://clang.llvm.org/docs/Modules.html) of the compiled modules. + +::: warning Note +For _.swift_ files _module.modulemap_ is not required. +::: + +In order to satisfy the above constraints the developer has to: + +**1)** Place the source files in _App_Resources/iOS/src/_ + +**2)** Create a modulemap for the Objective-C files + +::: warning Note +Swift classes need to be accessible from the Objective-C runtime in order to be used from NativeScript. This can be done by using the _@objc_ attribute or by inheriting _NSObject_. +::: + +For a detailed walkthrough on how to use native iOS source code in NativeScript [here](https://blog.nativescript.org/adding-objective-c-code-to-a-nativescript-app/). + +### Objective C Example + +A minimal example for adding native Objective C source code to your NativeScript application: + +1. Create ExampleCrypto.m file with the following content: + +```objc +// import required header files +#import +#import +#import "ExampleCrypto.h" + +@implementation ExampleCrypto + ++ (NSString *)generateHMACWithApiKey:(NSString *) apiKey andApiSecret:(NSString *) apiSecret { + NSString *hmacData = [NSString stringWithFormat:@"%@%@%@%@%@",apiKey]; + + // Make sure the HMAC hash is in hex + unsigned char outputHMAC[CC_SHA256_DIGEST_LENGTH]; + const char* keyChar = [apiSecret cStringUsingEncoding:NSUTF8StringEncoding]; + const char* dataChar = [hmacData cStringUsingEncoding:NSUTF8StringEncoding]; + CCHmac(kCCHmacAlgSHA256, keyChar, strlen(keyChar), dataChar, strlen(dataChar), outputHMAC); + NSData* hmacHash = [[NSData alloc] initWithBytes:outputHMAC length:sizeof(outputHMAC)]; + + NSString* hmacHashHexString = [[hmacHash description] stringByReplacingOccurrencesOfString:@" " withString:@""]; + + // Authorization : base64 of hmac hash --> + NSString* authorization = [[hmacHashHexString dataUsingEncoding:NSUTF8StringEncoding] base64EncodedStringWithOptions:0]; + + return authorization; +} + +@end +``` + +2. Create ExampleCrypto.h file with the following content: + +```objc +#import + +@interface ExampleCrypto : NSObject + ++ (NSString *)generateHMACWithApiKey:(NSString *)apiKey andApiSecret:(NSString *)apiSecret; + +@end +``` + +3. Create the module.modulemap file with the following content: + +```objc +module ExampleCrypto { + header "ExampleCrypto.h" + export * +} +``` + +4. Call the static method from the ObjectiveC source code just added somewhere in your application. + +```typescript +function generateNativeIOSHMAC() { + // This if check ensures the following code is only executed on iOS. + if (global.isIOS) { + const apiKey = '9292skksd88172alekdd782939ssa' + const apiSecret = 'f82828282828f992f' + + const base64encryptedKey = ExampleCrypto.generateHMACWithApiKeyandApiSecret( + apiKey, + apiSecret + ) + console.log('base64encryptedKey', base64encryptedKey) + } +} +``` + +5. Build your NativeScript application by running the following and you should see the base64encryptedKey print in your terminal. + +```cli +ns clean +ns run ios --no-hmr +``` diff --git a/architecture-concepts/custom-application-and-activity.md b/architecture-concepts/custom-application-and-activity.md new file mode 100755 index 00000000..a7e13e92 --- /dev/null +++ b/architecture-concepts/custom-application-and-activity.md @@ -0,0 +1,303 @@ +--- +title: Custom Application and Activity +--- + +## Custom Application and Activity + +NativeScript provides a way to create custom `android.app.Application` and `android.app.Activity` implementations. + +### Extending the Android Application + +1. Create a new TypeScript file in the root of your project folder - name it `application.android.ts` or `application.android.js` if you are using plain JS. + ::: tip Note + Note the \*.android suffix - we want this file packaged for Android only. + ::: + +2. Copy the following code for TypeScript file: + +```ts +// the `JavaProxy` decorator specifies the package and the name for the native *.JAVA file generated. +@NativeClass() +@JavaProxy('org.myApp.Application') +class Application extends android.app.Application { + public onCreate(): void { + super.onCreate() + + // At this point modules have already been initialized + + // Enter custom initialization code here + } + + public attachBaseContext(baseContext: android.content.Context) { + super.attachBaseContext(baseContext) + + // This code enables MultiDex support for the application (if needed) + // androidx.multidex.MultiDex.install(this); + } +} +``` + +Copy the following code for the JavaScript file: + +```js +const superProto = android.app.Application.prototype + +// the first parameter of the `extend` call defines the package and the name for the native *.JAVA file generated. +android.app.Application.extend('org.myApp.Application', { + onCreate: function () { + superProto.onCreate.call(this) + + // At this point modules have already been initialized + + // Enter custom initialization code here + }, + attachBaseContext: function (base) { + superProto.attachBaseContext.call(this, base) + // This code enables MultiDex support for the application (if needed compile androidx.multidex:multidex) + // androidx.multidex.MultiDex.install(this); + } +}) +``` + +3. Modify the application entry within the AndroidManifest.xml file found in the `/App_Resources/Android/` folder: + +```xml + +``` + +::: tip Note +This modification is required by the native platform; it tells Android that your custom Application class will be used as the main entry point of the application. +::: + +4. In order to build the app, the extended Android application should be added to the webpack.config.js file. + +```js +const webpack = require('@nativescript/webpack') + +module.exports = env => { + webpack.init(env) + + webpack.chainWebpack(config => { + if (webpack.Utils.platform.getPlatformName() === 'android') { + // make sure the path to the applicatioon.android.(js|ts) + // is relative to the webpack.config.js + // you may need to use `./app/application.android if + // your app source is located inside the ./app folder. + config.entry('application').add('./application.android') + } + }) + + return webpack.resolveConfig() +} +``` + +The source code of `application.android.ts` is bundled separately as `application.js` file which is loaded from the native Application.java class on launch. + +The `bundle.js` and `vendor.js` files are not loaded early enough in the application launch. That's why the logic in `application.android.ts` is needed to be bundled separately in order to be loaded as early as needed in the application lifecycle. + +::: warning Note +This approach will not work if application.android.ts requires external modules. +::: + +### Extending Android Activity + +NativeScript Core ships with a default `androidx.appcompat.app.AppCompatActivity` implementation, that bootstraps the NativeScript application, without forcing users to declare their custom Activity in every project. In some cases you may need to implement a custom Android Activity. In this section we'll look at how to do that! + +Create a new `activity.android.ts` or `activity.android.js` when using plain JS. + +::: tip Note +Note the `.android.(js|ts)` suffix - we only want this file on Android. +::: + +A basic Activity looks as follows: + +```ts +import { + Frame, + Application, + setActivityCallbacks, + AndroidActivityCallbacks +} from '@nativescript/core' + +@NativeClass() +@JavaProxy('org.myApp.MainActivity') +class Activity extends androidx.appcompat.app.AppCompatActivity { + public isNativeScriptActivity + + private _callbacks: AndroidActivityCallbacks + + public onCreate(savedInstanceState: android.os.Bundle): void { + Application.android.init(this.getApplication()) + // Set the isNativeScriptActivity in onCreate (as done in the original NativeScript activity code) + // The JS constructor might not be called because the activity is created from Android. + this.isNativeScriptActivity = true + if (!this._callbacks) { + setActivityCallbacks(this) + } + + this._callbacks.onCreate(this, savedInstanceState, this.getIntent(), super.onCreate) + } + + public onNewIntent(intent: android.content.Intent): void { + this._callbacks.onNewIntent(this, intent, super.setIntent, super.onNewIntent) + } + + public onSaveInstanceState(outState: android.os.Bundle): void { + this._callbacks.onSaveInstanceState(this, outState, super.onSaveInstanceState) + } + + public onStart(): void { + this._callbacks.onStart(this, super.onStart) + } + + public onStop(): void { + this._callbacks.onStop(this, super.onStop) + } + + public onDestroy(): void { + this._callbacks.onDestroy(this, super.onDestroy) + } + + public onPostResume(): void { + this._callbacks.onPostResume(this, super.onPostResume) + } + + public onBackPressed(): void { + this._callbacks.onBackPressed(this, super.onBackPressed) + } + + public onRequestPermissionsResult( + requestCode: number, + permissions: Array, + grantResults: Array + ): void { + this._callbacks.onRequestPermissionsResult( + this, + requestCode, + permissions, + grantResults, + undefined /*TODO: Enable if needed*/ + ) + } + + public onActivityResult( + requestCode: number, + resultCode: number, + data: android.content.Intent + ): void { + this._callbacks.onActivityResult( + this, + requestCode, + resultCode, + data, + super.onActivityResult + ) + } +} +``` + +```js +import { Frame, Application, setActivityCallbacks } from '@nativescript/core' + +const superProto = androidx.appcompat.app.AppCompatActivity.prototype +androidx.appcompat.app.AppCompatActivity.extend('org.myApp.MainActivity', { + onCreate: function (savedInstanceState) { + // Used to make sure the App is inited in case onCreate is called before the rest of the framework + Application.android.init(this.getApplication()) + + // Set the isNativeScriptActivity in onCreate (as done in the original NativeScript activity code) + // The JS constructor might not be called because the activity is created from Android. + this.isNativeScriptActivity = true + if (!this._callbacks) { + setActivityCallbacks(this) + } + // Modules will take care of calling super.onCreate, do not call it here + this._callbacks.onCreate( + this, + savedInstanceState, + this.getIntent(), + superProto.onCreate + ) + + // Add custom initialization logic here + }, + onNewIntent: function (intent) { + this._callbacks.onNewIntent( + this, + intent, + superProto.setIntent, + superProto.onNewIntent + ) + }, + onSaveInstanceState: function (outState) { + this._callbacks.onSaveInstanceState(this, outState, superProto.onSaveInstanceState) + }, + onStart: function () { + this._callbacks.onStart(this, superProto.onStart) + }, + onStop: function () { + this._callbacks.onStop(this, superProto.onStop) + }, + onDestroy: function () { + this._callbacks.onDestroy(this, superProto.onDestroy) + }, + onPostResume: function () { + this._callbacks.onPostResume(this, superProto.onPostResume) + }, + onBackPressed: function () { + this._callbacks.onBackPressed(this, superProto.onBackPressed) + }, + onRequestPermissionsResult: function (requestCode, permissions, grantResults) { + this._callbacks.onRequestPermissionsResult( + this, + requestCode, + permissions, + grantResults, + undefined + ) + }, + onActivityResult: function (requestCode, resultCode, data) { + this._callbacks.onActivityResult( + this, + requestCode, + resultCode, + data, + superProto.onActivityResult + ) + } + /* Add any other events you need to capture */ +}) +``` + +:::warning Note +The `this._callbacks` property is automatically assigned to your extended class by the `frame.setActivityCallbacks` method. It implements the [AndroidActivityCallbacks interface](https://docs.nativescript.org/core-concepts/application-lifecycle#android-activity-events) and allows the core modules to get notified for important Activity events. It is **important** to use these callbacks, as many parts of NativeScript rely on them! +::: + + + +Next, modify the activity in `App_Resources/Android/src/main/AndroidManifest.xml` + +```xml + +``` + +To include the new Activity in the build, it has to be added to the webpack compilation by editing the `webpack.config.js`: + +```js +const webpack = require('@nativescript/webpack') + +module.exports = env => { + env.appComponents = (env.appComponents || []).concat(['./src/activity.android']) + webpack.init(env) + + return webpack.resolveConfig() +} +``` diff --git a/architecture-concepts/data-binding.md b/architecture-concepts/data-binding.md new file mode 100755 index 00000000..3687fd78 --- /dev/null +++ b/architecture-concepts/data-binding.md @@ -0,0 +1,397 @@ +--- +title: Data Binding +--- + +## Data Binding + +The purpose of this article is to explain what Data Binding is and how it works in NativeScript. + +Data binding is the process of connecting application user interface (UI) to a data object (code). It enables changes propagation by reflecting UI modifications in the code and vice versa. + +::: tip Note + +1. In this article `source` is used as any object in the code and `target` as any UI control (like [TextField](/ui/components.html#textfield)). + +2. The article uses StackBlitz IDE + Nativescript Preview app to show different examples of data binding in Nativescript. Use these tools to try out the code snippets provided throughout the article. + ::: + +### Data flow direction + +Part of the data binding settings deals with how the data flows between the UI and the data object. NativeScript data binding supports the following data transmissions: + +- **One-Way**: This is the default setting, which ensures that the target property updates when a change in the source property occurs. However, UI modification will not update the source property. +- **Two-Way**: This setting ensures the reflection of changes in both directions — from target to source and source to target. You can use two-way data binding when you need to handle user input. + +## Two-way binding + +### Binding in code + +The example below consists of a Label, TextField and a source property to which the UI controls are bound. First, the **source** object is created with a **textSource** property, initially set to an empty string and then the source object is bound to both the `TextField` and `Label` elements. + +Then when the user inputs new string into the `TextField`, the **two-way** binding will update the TextField's text property. Since the Label is bound to the same property, its text property will also be updated. For the Label the data flow is **one-way**,as the changes only propagate from the code to the UI. For a constant flow of changes propagation from the source property to the Label, the source property has to raise a **propertyChange** event in order to notify the Label of the changes. To raise this event, a built-in class is used, which provides this functionality - [Observable](/nativescript-core/observable.md). + + + +### Binding in XML + +To create a binding in XML, a source object is needed, which will be created the same way, as in the example above. Then the binding is created in the XML using a mustache(`{{ }}`) syntax. With an XML declaration, only the names of the properties are set - for the target: text, and for source: textSource. The interesting thing here is that the source of the binding is not specified explicitly. + +```xml + + + + + +``` + +::: tip Note +When creating UI elements with an XML declaration, the data binding is two-way by default. +::: + +### Binding to a property + +An important part of the data binding is setting the source object. For a continuous flow of data changes, the source property needs to emit a **propertyChange** event. NativeScript data binding works with any object that emits this event. Adding a binding source happens by passing it as a second parameter in the method `bind(bindingOptions, source)`. This parameter is optional and could be omitted, in which case a property named **bindingContext** of the `View` class is used as the source. What is special about this property is that it is inheritable across the visual tree. This means that a UI control can use the **bindingContext** of the first of its parent elements, which has an explicitly set **bindingContext**. See [Parent Binding](/architecture-concepts/data-binding.md#parent-binding) In the example from [Binding in Code](/architecture-concepts/data-binding.md#binding-in-code), the **bindingContext** can be set either on a [Page](/ui/components.md#page) instance or a [StackLayout](/ui/components.md#stacklayout) instance and the [TextField](/ui/components.md#textfield) will inherit it as a proper source for the binding of its "text" property. + +```js +page.bindingContext = source +//or +stackLayout.bindingContext = source +``` + +```ts +page.bindingContext = source +//or +stackLayout.bindingContext = source +``` + +### Parent Binding + +Another common case in working with bindings is requesting access to the parent binding context. This is because a parent UI element and a child UI element can have different binding contexts and the child UI might need to bind its property to a source property in its parent's **bindingContext**. + +Generally, the binding context is inheritable, but not when the elements (items) are created dynamically based on some data source. For example, [ListView](/ui/components.md#listview) creates its child items based on an itemТemplate, which describes what the ListView element will look like. When this element is added to the visual tree, it gets for binding context an element from a ListView items array (with the corresponding index). This process creates a new binding context chain for the child item and its inner UI elements. So, the inner UI element cannot access the binding context of the ListView. In order to solve this problem, NativeScript binding infrastructure has two special keywords: `$parent` and `$parents`. While the first one denotes the binding context of the direct parent visual element, the second one can be used as an array (with a number or string index). This gives you the option to choose either N levels of UI nesting or get a parent UI element with a given type. Let's see how this works with an example. + + + +::: tip Note +If the value of the `items` property of the `ListView` is an array of plain elements(numbers,string, dates) as in the preceeding example, you use the `$value` variable to access the current item of the array. + +If it is an array of objects,you use the current object property name as the variable name. +::: + +### Binding to an event in XML + +There is an option to bind a function to execute on a specific event. This option is available only through an XML declaration. To implement such a functionality, the source object should have an event handler function. The following is an example of binding a function on a button `tap` event. + + + +```html + + + + + +``` + +/// + +/// flavor plain + +```html + + + + + + + + + + + + +``` + +```ts +import { Button, EventData } from '@nativescript/core' + +onTap(args: EventData) { + const button = args.object as Button + // execute your custom logic here... +} +``` + +/// + +/// flavor vue + +```html + +``` + +#### Native component + +| Android | iOS | +| --------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- | +| [`android.widget.Button`](https://developer.android.com/reference/android/widget/Button.html) | [`UIButton`](https://developer.apple.com/documentation/uikit/uibutton) | diff --git a/components/datepicker.md b/components/datepicker.md new file mode 100755 index 00000000..b82cca15 --- /dev/null +++ b/components/datepicker.md @@ -0,0 +1,184 @@ +--- +title: DatePicker +--- + +## Date Picker + +`` is a UI component that lets users select a date from a pre-configured range. + +See also: [TimePicker](/ui-and-styling.html#timepicker). + +--- + +/// flavor plain + +```xml + +``` + +```ts +import { DatePicker, EventData, Observable, Page } from '@nativescript/core' + +export function onNavigatingTo(args: EventData) { + const page = args.object as Page + const vm = new Observable() + + // in the following example the DatePicker properties are binded via Observableproperties + vm.set('minDate', new Date(1975, 0, 29)) // the binded minDate property accepts Date object + vm.set('maxDate', new Date(2045, 4, 12)) // the binded maxDate property accepts Date object + + page.bindingContext = vm +} + +export function onDatePickerLoaded(data: EventData) { + const datePicker = data.object as DatePicker + datePicker.on('dateChange', args => { + console.dir(args) + }) + datePicker.on('dayChange', args => { + console.dir(args) + }) + datePicker.on('monthChange', args => { + console.dir(args) + }) + datePicker.on('yearChange', args => { + console.dir(args) + }) +} +``` + +/// + +/// flavor angular + +```html + + +``` + +```typescript +import { Component } from '@angular/core' +import { DatePicker } from '@nativescript/core' + +@Component({ + moduleId: module.id, + templateUrl: './usage.component.html' +}) +export class DatePickerUsageComponent { + minDate: Date = new Date(1975, 0, 29) + maxDate: Date = new Date(2045, 4, 12) + + onDatePickerLoaded(args) { + // const datePicker = args.object as DatePicker; + } + + onDateChanged(args) { + console.log('Date New value: ' + args.value) + console.log('Date value: ' + args.oldValue) + } + + onDayChanged(args) { + console.log('Day New value: ' + args.value) + console.log('Day Old value: ' + args.oldValue) + } + + onMonthChanged(args) { + console.log('Month New value: ' + args.value) + console.log('Month Old value: ' + args.oldValue) + } + + onYearChanged(args) { + console.log('Year New value: ' + args.value) + console.log('Year Old value: ' + args.oldValue) + } +} +``` + +/// + +/// flavor vue + +```html + +``` + +`` provides two-way data binding using `v-model`. + +```html + +``` + +/// + +/// flavor react + +```tsx +import { EventData } from '@nativescript/core' +; { + const datePicker = args.object + }} +/> +``` + +/// + +/// flavor svelte + +```html + +``` + +`` provides two-way data binding using `bind`. + +```html + +``` + +/// + +### Props + +| Name | Type | Description | +| ----------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `date` | `Date` | Gets or sets the complete date. | +| `minDate` | `Date` | Gets or sets the earliest possible date to select. | +| `maxDate` | `Date` | Gets or sets the latest possible date to select. | +| `day` | `Number` | Gets or sets the day. | +| `month` | `Number` | Gets or sets the month. | +| `year` | `Number` | Gets or sets the year. | +| `iosPreferredDatePickerStyle` | `number` | Gets or set the UIDatePickerStyle of the date picker in iOS 13.4+. Defaults to 0.
Valid values are numbers:

`0 = automatic`: system picks the concrete style based on the current platform and date picker mode
`1 = wheels`: the date picker displays as a wheel picker
`2 = compact` : the date picker displays as a label that when tapped displays a calendar-style editor
`3 = inline` : the date pickers displays as an inline, editable field | +| `...Inherited` | `Inherited` | Additional inherited properties not shown. Refer to the [API Reference](https://docs.nativescript.org/api-reference/classes/datepicker) | + +### Events + +| Name | Description | +| ------------ | --------------------------------------- | +| `dateChange` | Emitted when the selected date changes. | + +### Native component + +| Android | iOS | +| ----------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------ | +| [`android.widget.DatePicker`](https://developer.android.com/reference/android/widget/DatePicker.html) | [`UIDatePicker`](https://developer.apple.com/documentation/uikit/uidatepicker) | diff --git a/components/frame.md b/components/frame.md new file mode 100755 index 00000000..7355f225 --- /dev/null +++ b/components/frame.md @@ -0,0 +1,226 @@ +--- +title: Frame +--- + +## Frame + +`` is a UI component used to display [``](/ui-and-styling.html#page) elements. Every app needs at least a single `` element, usually set as the root element. + +--- + +### A single root Frame + +/// flavor + +```js +new Vue({ + render: h => h('Frame', [h(HomePageComponent)]) +}) +``` + +/// + +### Multiple Frames + +If you need to create multiple frames, you can do so by wrapping them in a Layout, for example if you want to have 2 frames side-by-side + +/// flavor vue + +```html + + + + +``` + +/// + +/// flavor react + +```tsx + + + + +``` + +/// + +/// flavor svelte + +```html + + + + +``` + +/// + +#### Example: A frame with a default page + +/// flavor vue + +```html + + + + + + + +``` + +/// + +/// flavor react + +```tsx + + + + + + + +``` + +/// + +/// flavor svelte + +```html + + + + + + + +``` + +/// + +#### Example: A frame with a default page from an external component + +/// flavor vue + +```html + + + + + +``` + +```js +import Home from './Home' + +export default { + components: { + Home + } +} +``` + +/// + +/// flavor svelte + +```html + + + +``` + +```js +import Home from './Home.svelte' +``` + +/// + +/// flavor react + +```tsx +import HomePage from './HomePage' + +function AppContainer() { + return ( + + + + ) +} +``` + +/// + +### Static Props + +| Name | Type | Description | +| --------------------------- | ---------------------- | ---------------------------------------------------------------------------- | +| `defaultAnimatedNavigation` | `boolean` | Gets or sets if navigation transitions should be animated globally. | +| `defaultTransition` | `NavigationTransition` | Gets or sets the default NavigationTransition for all frames across the app. | + +### Props + +| Name | Type | Description | +| --------------------- | ------------------------------- | --------------------------------------------------------------------------------------- | +| `backStack` | `Array` | Gets the back stack of this instance. | +| `currentPage` | `Page` | Gets the Page instance the Frame is currently navigated to. | +| `currentEntry` | `NavigationEntry` | Gets the NavigationEntry instance the Frame is currently navigated to. | +| `animated` | `boolean` | Gets or sets if navigation transitions should be animated. | +| `transition` | `NavigationTransition` | Gets or sets the default navigation transition for this frame. | +| `actionBarVisibility` | `'auto' \| 'never' \| 'always'` | Used to control the visibility the Navigation Bar in iOS and the Action Bar in Android. | + +### Static Methods + +| Name | Return Type | Description | +| -------------------------- | ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `getFrameById(id: string)` | `Frame` | Gets a frame by id. | +| `topmost()` | `Frame` | Gets the topmost frame in the frames stack. An application will typically has one frame instance. Multiple frames handle nested (hierarchical) navigation scenarios. | +| `goBack()` | | Navigates back using the navigation hierarchy (if any). Updates the Frame stack as needed. This method will start from the topmost Frame and will recursively search for an instance that has the canGoBack operation available. | + +### Instance Methods + +| Name | Type | Description | +| ---------------------------------- | --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `goBack(to?: BackstackEntry)` | | Navigates to the previous entry (if any) in the back stack. | +| `canGoBack()` | `boolean` | Checks whether the goBack operation is available. | +| `navigate(pageModuleName: string)` | | Navigates to a Page instance as described by the module name. This method will require the module and will check for a Page property in the exports of the module.
`pageModuleName:` The name of the module to require starting from the application root. For example if you want to navigate to page called "myPage.js" in a folder called "subFolder" and your root folder is "app" you can call navigate method like this:
`import { Frame }"@nativescript/core"; Frame.topmost().navigate("app/subFolder/myPage");` | +| `navigate(create: () => Page)` | | Creates a new Page instance using the provided callback and navigates to that Page.
`create:` The function to be used to create the new Page instance. | +| `navigate(entry: NavigationEntry)` | | Creates a new Page instance using the provided callback and navigates to that Page.
Since there are a couple of ways to specify a Page instance through an entry, there is a resolution priority:
`1.` entry.moduleName
`2.` entry.create()
`entry`: The NavigationEntry instance. | + +### Other function(s) + +| Name | Return Type | Description | +| ------------------------------ | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `setFragmentClass(class: any)` | `void` | Sets the extended `androidx.fragment.app.Fragment` class to the Frame and navigation routine. An instance of this class will be created to represent the Page currently visible on the srceen. This method is available only for the Android platform. | + +| + +### NavigationEntry interface + +| Name | Return Type | Description | +| ------------------- | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `moduleName` | `string` | The name of the module containing the View instance to load. | +| `create()` | `View` | A function used to create the View instance. | +| `context` | `any` | An object passed to the onNavigatedTo callback of the Page. Typically this is used to pass some data among pages. | +| `bindingContext` | `any` | An object to become the binding context of the page navigating to. Optional. | +| `animated` | `boolean` | True to navigate to the new Page using animated transitions, false otherwise. | +| `transition` | `NavigationTransition` | Specifies an optional navigation transition for all platforms. If not specified, the default platform transition will be used. | +| `transitionAndroid` | `NavigationTransition` | Specifies an optional navigation transition for Android. If not specified, the default platform transition will be used. | +| `transitioniOS` | `NavigationTransition` | Specifies an optional navigation transition for iOS. If not specified, the default platform transition will be used. | +| `backstackVisible` | `boolean` | True to record the navigation in the backstack, false otherwise. If the parameter is set to false then the Page will be displayed but once navigated from it will not be able to be navigated back to. | +| `clearHistory` | `boolean` | True to clear the navigation history, false otherwise. Very useful when navigating away from login pages. | + +| + +### Native component + +| Android | iOS | +| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------- | +| [`org.nativescript.widgets.ContentLayout`](https://github.com/NativeScript/NativeScript/blob/master/packages/ui-mobile-base/android/widgets/src/main/java/org/nativescript/widgets/ContentLayout.java) | [`UINavigationController`](https://developer.apple.com/documentation/uikit/uinavigationcontroller) | diff --git a/components/htmlview.md b/components/htmlview.md new file mode 100755 index 00000000..c9696f87 --- /dev/null +++ b/components/htmlview.md @@ -0,0 +1,93 @@ +--- +title: HtmlView +--- + +## HtmlView + +`` is a UI component that lets you show static HTML content. + +See also: [WebView](#webview). + +--- + +/// flavor plain + +```xml + +``` + +```ts +import { HtmlView } from '@nativescript/core' + +export function onHtmlLoaded(args) { + const myHtmlView = args.object as HtmlView + myHtmlView.html = ` +

NativeScript HtmlView


+

This component accept simple HTML strings

` +} +``` + +/// + +/// flavor angular + +```html + +``` + +```ts +import { Component } from '@angular/core' + +@Component({ + moduleId: module.id, + templateUrl: './usage.component.html' +}) +export class HtmlViewUsageComponent { + htmlString: string + + constructor() { + this.htmlString = ` +

HtmlView demo in NativeScript App

+
` + } +} +``` + +/// + +/// flavor vue + +```html + +``` + +/// + +/// flavor react + +```tsx + +``` + +/// + +/// flavor svelte + +```html + +``` + +/// + +### Props + +| Name | Type | Description | +| -------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------------- | +| `html` | `String` | The HTML content to be shown. | +| `...Inherited` | `Inherited` | Additional inherited properties not shown. Refer to the [API Reference](https://docs.nativescript.org/api-reference/classes/htmlview) | + +### Native component + +| Android | iOS | +| ------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------- | +| [`android.widget.TextView`](https://developer.android.com/reference/android/widget/TextView.html) | [`UITextView`](https://developer.apple.com/documentation/uikit/uitextview) | diff --git a/components/image.md b/components/image.md new file mode 100755 index 00000000..ec086b42 --- /dev/null +++ b/components/image.md @@ -0,0 +1,272 @@ +--- +title: Image +--- + +## Image + +`` is a UI component that shows an image from an [ImageSource](https://docs.nativescript.org/api-reference/classes/imagesource) or from a URL. + + + +::: tip Tip +When working with images following [the best practices](/performance.html#image-optimizations) is a must. +::: + +--- + +#### Example: Displaying an image from `App_Resources` + +/// flavor plain + +```xml + +``` + +/// + +/// flavor angular + +```html + +``` + +/// + +/// flavor react + +```tsx + +``` + +/// + +/// flavor vue + +```html + +``` + +/// + +/// flavor svelte + +```html + +``` + +/// + +#### Example: Displaying an image relative to the `app` directory + +/// flavor plain + +```xml + +``` + +/// + +/// flavor angular + +```html + +``` + +/// + +/// flavor react + +```tsx + +``` + +/// + +/// flavor vue + +```html + +``` + +/// + +/// flavor svelte + +```html + +``` + +/// + +#### Example: Displaying an image from a URL + +:::tip Note + +Setting `loadMode` to `async` will prevent freezing the UI on Android when loading photos async (e.g. from online API) + +::: + +/// flavor plain + +```xml + +``` + +/// + +/// flavor angular + +```html + + +``` + +/// + +/// flavor react + +```tsx + +``` + +/// + +/// flavor vue + +```html + +``` + +/// + +/// flavor svelte + +```html + +``` + +/// + +#### Example: Displaying a `base64`-encoded image + +/// flavor plain + +```xml + +``` + +/// + +/// flavor angular + +```html + +``` + +/// + +/// flavor react + +```tsx + +``` + +/// + +/// flavor vue + +```html + +``` + +/// + +/// flavor svelte + +```html + +``` + +/// + +#### Example: Image with CSS and an icon fonts + +/// flavor plain + +```xml + +``` + +/// + +/// flavor angular + +```html + +``` + +/// + +/// flavor react + +```tsx + +``` + +/// + +/// flavor vue + +```html + +``` + +:::warning Note + +In NativeScript-Vue, `.decode` is required for parsing properties that have HTML entities in them. + +::: + +/// + +/// flavor svelte + +```html + +``` + +/// + +### Props + +| Name | Type | Description | +| -------------- | -------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `src` | `String` or [`ImageSource`](https://docs.nativescript.org/api-reference/classes/imagesource) | Gets or sets the source of the image as a URL or an image source. If you use the new font:// icon protocol in {N} 6.2, make sure you add .decode to the name of the property - e.g. `src.decode="font://"` | +| `imageSource` | [`ImageSource`](https://docs.nativescript.org/api-reference/classes/imagesource) | Gets or sets the image source of the image. | +| `tintColor` | `Color` | (Style property) Sets a color to tint template images. | +| `stretch` | `ImageStretch` | (Style property) Gets or sets the way the image is resized to fill its allocated space.
Valid values: `none`, `aspectFill`, `aspectFit`, or `fill`.
For more information, see [ImageStretch](https://docs.nativescript.org/api-reference/modules/coretypes.imagestretch). | +| `loadMode` | | Gets or sets the loading strategy for the images on the local file system.
Valid values: `sync` or `async`.
Default value: `async`.
For more information, see [loadMode](https://docs.nativescript.org/api-reference/classes/image#loadmode). | +| `...Inherited` | `Inherited` | Additional inherited properties not shown. Refer to the [API Reference](https://docs.nativescript.org/api-reference/classes/image) | + + + +### Native component + +| Android | iOS | +| ---------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------- | +| [`android.widget.ImageView`](https://developer.android.com/reference/android/widget/ImageView) | [`UIImageView`](https://developer.apple.com/documentation/uikit/uiimageview) | diff --git a/components/index.md b/components/index.md new file mode 100755 index 00000000..870360bc --- /dev/null +++ b/components/index.md @@ -0,0 +1,782 @@ +--- +title: Components +--- + +### Layout Properties + +#### Margins + +The four margin properties (`marginTop`, `marginRight`, `marginBottom` and `marginLeft`) describe the distance between a view and its parent. + +When you set margins through XML, you can choose between the following approaches. + +- **Set one value**: Provide a single value that will be applied on all sides of the view. +- **Set two values**: Provide two values. The first value is applied to the top side, the second value is applied to the right side. Next, the first value is applied to the bottom and the second value to the left side (in that order). +- **Set four values**: Provide four values for each margin. The first value is applied to the top, the second value is applied to the right, the third value is applied to the bottom and the fourth value is applied to the left side (in that order). + +#### Paddings + +The four padding properties (`paddingTop`, `paddingRight`, `paddingBottom` and `paddingLeft`) describe the distance between the layout container and its children. + +When you set paddings through XML, you can choose between the following approaches. + +- **Set one value**: Provide a single value that will be applied on all sides of the view. +- **Set two values**: Provide two values. The first value is applied to the top side, the second value is applied to the right side. Next, the first value is applied to the bottom and the second value to the left side (in that order). +- **Set four values**: Provide four values for each padding. The first value is applied to the top, the second value is applied to the right, the third value is applied to the bottom and the fourth value is applied to the left side (in that order). + +#### Alignments + +Layout applies horizontal and vertical alignment only when an element is allocated more size than it needs. + +The following table shows the valid values of `horizontalAlignment`. + +| Member | Description | +| ------- | ------------------------------------------------------------------------------------------------------ | +| left | The view is aligned to the left of the layout slot of the parent element. | +| center | The view is aligned to the center of the layout slot of the parent element. | +| right | The view is aligned to the right of the layout slot of the parent element. | +| stretch | The view is stretched to fill the layout slot of the parent element; `width` takes precedence, if set. | + +The following table shows the valid values of `verticalAlignment`. + +| Member | Description | +| ------- | ------------------------------------------------------------------------------------------------------- | +| top | The view is aligned to the top of the layout slot of the parent element. | +| center | The view is aligned to the center of the layout slot of the parent element. | +| bottom | The view is aligned to the bottom of the layout slot of the parent element. | +| stretch | The view is stretched to fill the layout slot of the parent element; `height` takes precedence, if set. | + +### Percentage Support + +NativeScript supports percentage values for `width`, `height` and `margin`. When a layout pass begins, first the percent values are calculated based on parent available size. This means that on vertical `StackLayout` if you place two `Buttons` with `height='50%'` they will get all the available height (e.g., they will fill the `StackLayout` vertically.). The same applies for margin properties. For example, if you set `marginLeft='5%'`, the element will have a margin that corresponds to 5% of the parent's available width. + +### iOS Safe Area Support + +The iOS `Safe Area` is a term that Apple introduced in iOS 11. It is the area of the screen that is free to use and won’t be obstructed by hardware and software parts of the system. The safe area is not a constant. It is affected by the notch, the rounded corners of the screen, the status bar and the home indicator, but also from parts of your application like the action bar and the tab bar. To get a better understanding refer to the [Apple docs](https://developer.apple.com/design/human-interface-guidelines/ios/visual-design/adaptivity-and-layout/). + +Since version 5.0 NativeScript provides a default handling mechanism for the iOS `Safe Area`. The default behavior is that certain container `View` components (these that can have children) overflow the safe area and are laid out to the edges of the screen. These container components are: + +- Layouts +- ListView +- ScrollView +- WebView +- Repeater + +Internally, the workflow is as follows: + +1. Measure pass - all components are measured in the safe area portion of the screen. +2. Layout pass - all components are laid out in full screen, but are inset to the safe area boundaries. +3. Layout pass - if the component borders the safe area, it is adjusted and expanded to the edges of the screen. + +::: tip +The above workflow can lead to containers being laid out with a bigger size than initially declared in the markup. You can prevent this behavior by setting the `iosOverflowSafeArea` property below to `false`. +::: + +#### iosOverflowSafeArea Property + +The above default behavior should provide good UX out of the box. Additionally, NativeScript 5.0 exposes a property `iosOverflowSafeArea` that can control how components handle the iOS `Safe Area`. Set this property value to `true` if you want the component to expand to the edges of the screen when it borders the safe area. Set it to `false` to explicitly prevent this behavior. The default value for container components is `true`. All other components are considered content that should be constrained to the safe area and default to `false`. + +## Layout Containers + +### AbsoluteLayout + +The `` container is the simplest layout container in NativeScript. + +`` has the following behavior: + +- Uses a pair of absolute left/top coordinates to position its children. +- Doesn't enforce any layout constraints on its children. +- Doesn't resize its children at runtime when its size changes. + +#### Example: a grid-like layout + +The following example creates a simple grid. For more information about creating grid layouts, see [GridLayout](/ui-and-styling.html#gridlayout). + +```html + + +``` + + + +#### Example: Overlapping elements + +The following example creates a group of overlapping items. + +```html + + +``` + + + +#### Props + +| Name | Type | Description | +| -------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------- | +| `N/A` | `N/A` | None. | +| `...Inherited` | `Inherited` | Additional inherited properties not shown. Refer to the [API Reference](https://docs.nativescript.org/api-reference/classes/absolutelayout) | + +#### Additional children props + +When an element is a direct child of ``, you can set the following additional properties. + +| Name | Type | Description | +| ------ | -------- | --------------------------------------------------------------------------------------------------------- | +| `top` | `Number` | Gets or sets the distance, in pixels, between the top edge of the child and the top edge of its parent. | +| `left` | `Number` | Gets or sets the distance, in pixels, between the left edge of the child and the left edge of its parent. | + +### DockLayout + +`` is a layout container that lets you dock child elements to the sides or the center of the layout. + +`` has the following behavior: + +- Uses the `dock` property to dock its children to the `left`, `right`, `top`, `bottom` or center of the layout.
To dock a child element to the center, it must be the **last child** of the container and you must set the `stretchLastChild` property of the parent to `true`. +- Enforces layout constraints to its children. +- Resizes its children at runtime when its size changes. + +#### Example: Dock to every side without stretching the last child + +The following example creates a frame-like layout consisting of 4 elements, position at the 4 edges of the screen. + +```html + + +``` + + + +#### Example: Dock to every side and stretch the last child + +The following example shows how `stretchLastChild` affects the positioning of child elements in a `DockLayout` container. The last child (`bottom`) is stretched to take up all the remaining space after positioning the first three elements. + +```html + + +``` + + + +#### Example: Dock to every side and the center + +The following example creates a `` of 5 elements. The first four wrap the center element in a frame. + +```html + + +``` + + + +#### Example: Dock multiple children to the same side + +The following example creates a single line of 4 elements that stretch across the entire height and width of the screen. + +```html + + +``` + + + +#### Props + +| Name | Type | Description | +| ------------------ | ----------- | --------------------------------------------------------------------------------------------------------------------------------------- | +| `stretchLastChild` | `Boolean` | Enables or disables stretching the last child to fit the remaining space. | +| `...Inherited` | `Inherited` | Additional inherited properties not shown. Refer to the [API Reference](https://docs.nativescript.org/api-reference/classes/docklayout) | + + + +#### Additional children props + +When an element is a direct child of ``, you can set the following additional properties. + +| Name | Type | Description | +| ------ | -------- | --------------------------------------------------------------------------------------------------- | +| `dock` | `String` | Specifies which side to dock the element to.
Valid values: `top`, `right`, `bottom`, or `left`. | + +### GridLayout + +`` is a layout container that lets you arrange its child elements in a table-like manner. + +The grid consists of rows, columns, and cells. A cell can span one or more rows and one or more columns. It can contain multiple child elements which can span over multiple rows and columns, and even overlap each other. + +By default, `` has one column and one row. You can add columns and rows by configuring the `columns` and the `rows` properties. In these properties, you need to set the number of columns and rows and their width and height. You set the number of columns by listing their widths, separated by a comma. You set the number of rows by listing their heights, separated by a comma. + +You can set a fixed size for column width and row height or you can create them in a responsive manner: + +- **An absolute number:** Indicates a fixed size. +- **auto:** Makes the column as wide as its widest child or makes the row as tall as its tallest child. +- **\*:** Takes as much space as available after filling all auto and fixed size columns or rows. + +See **Props** for more information. + +#### Example: Grid layout with fixed sizing + +The following example creates a simple 2-by-2 grid with fixed column widths and row heights. + +```html + + +``` + + + +#### Example: Grid layout with star sizing + +The following example creates a grid with responsive design, where space is allotted proportionally to child elements. + +```html + + +``` + + + +#### Example: Grid layout with fixed and auto sizing + +The following example create a grid with one auto-sized column and one column with fixed size. Rows have a fixed height. + +```html + + +``` + + + +#### Example: Grid layout with mixed sizing and merged cells + +The following example creates a complex grid with responsive design, mixed width and height settings, and some merged cells. + +```html + + +``` + + + +#### Props + +| Name | Type | Description | +| -------------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `columns` | `String` | A string value representing column widths delimited with commas.
Valid values: an absolute number, `auto`, or `*`.
A number indicates an absolute column width. `auto` makes the column as wide as its widest child. `*` makes the column occupy all available horizontal space. The space is proportionally divided over all star-sized columns. You can set values such as `3*` and `5*` to indicate a ratio of 3:5 in sizes. | +| `rows` | `String` | A string value representing row heights delimited with commas.
Valid values: an absolute number, `auto`, or `*`.
A number indicates an absolute row height. `auto` makes the row as tall as its tallest child. `*` makes the row occupy all available vertical space. The space is proportionally divided over all star-sized rows. You can set values such as `3*` and `5*` to indicate a ratio of 3:5 in sizes. | +| `...Inherited` | `Inherited` | Additional inherited properties not shown. Refer to the [API Reference](https://docs.nativescript.org/api-reference/classes/gridlayout) | + +#### Additional children props + +When an element is a direct child of ``, you can work with the following additional properties. + +| Name | Type | Description | +| --------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `row` | `Number` | Specifies the row for this element. Combined with a `col` property, specifies the cell coordinates of the element.
The first row is indicated by `0`. | +| `col` | `Number` | Specifies the column for the element. Combined with a `row` property, specifies the cell coordinates of the element.
The first column is indicated by `0`. | +| `rowSpan` | `Number` | Specifies the number of rows which this element spans across. | +| `colSpan` | `Number` | Specifies the number of columns which this element spans across. | + +### StackLayout + +`` is a layout container that lets you stack the child elements vertically (default) or horizontally. + +::: danger Important +Try not to nest too many `` in your markup. If you find yourself nesting a lot of `` +you will likely get better performance by switching to a `` or ``. +See [Layout Nesting](/common-pitfalls.html#layout-nesting) for more information. +::: + +#### Example: Default stacking + +The following example creates a vertical stack of 3 equally-sized elements. Items are stretched to cover the entire width of the screen. Items are placed in the order they were declared in. + +```html + + +``` + + + +#### Example: Horizontal stacking + +The following example creates a horizontal stack of 3 equally-sized elements. Items are stretched to cover the entire height of the screen. Items are placed in the order they were declared in. + +```html + + +``` + + + +#### Example: Stack layout with horizontally aligned children + +The following example creates a diagonal stack of items with responsive sizes. Items are vertically stacked. + +```html + + +``` + + + +#### Example: Horizontal stack layout with vertically aligned children + +The following example creates a diagonal stack of items with responsive sizes. Items are horizontally stacked. + +```html + + +``` + + + +#### Props + +| Name | Type | Description | +| -------------- | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------- | +| `orientation` | `String` | Specifies the stacking direction.
Valid values: `vertical` and `horizontal`.
Default value: `vertical`. | +| `...Inherited` | `Inherited` | Additional inherited properties not shown. Refer to the [API Reference](https://docs.nativescript.org/api-reference/classes/stacklayout) | + +#### Additional children props + +None. + +### RootLayout + +`` is a layout container designed to be used as the primary root layout container for your app with a built in api to easily control dynamic view layers. It extends a GridLayout so has all the features of a grid but enhanced with additional apis. + +It's api can be observed here: + +```ts +export class RootLayout extends GridLayout { + open(view: View, options?: RootLayoutOptions): Promise + close(view: View, exitTo?: TransitionAnimation): Promise + bringToFront(view: View, animated?: boolean): Promise + closeAll(): Promise + getShadeCover(): View +} + +export function getRootLayout(): RootLayout + +export interface RootLayoutOptions { + shadeCover?: ShadeCoverOptions + animation?: { + enterFrom?: TransitionAnimation + exitTo?: TransitionAnimation + } +} + +export interface ShadeCoverOptions { + opacity?: number + color?: string + tapToClose?: boolean + animation?: { + enterFrom?: TransitionAnimation // only applied if first one to be opened + exitTo?: TransitionAnimation // only applied if last one to be closed + } + ignoreShadeRestore?: boolean +} + +export interface TransitionAnimation { + translateX?: number + translateY?: number + scaleX?: number + scaleY?: number + rotate?: number // in degrees + opacity?: number + duration?: number // in milliseconds + curve?: any // CoreTypes.AnimationCurve (string, cubicBezier, etc.) +} +``` + +You can use `getRootLayout()` to get a reference to the root layout in your app from anywhere. + +#### Example: RootLayout setup + +Sample layout: + +```html + + + + + +``` + +Sample api usage: + +```ts +// Open a dynamic popup +const view = this.getPopup('#EA5936', 110, -30) +getRootLayout() + .open(view, { + shadeCover: { + color: '#000', + opacity: 0.7, + tapToClose: true + }, + animation: { + enterFrom: { + opacity: 0, + translateY: 500, + duration: 500 + }, + exitTo: { + opacity: 0, + duration: 300 + } + } + }) + .catch(ex => console.error(ex)) + +// Close the dynamic popup +getRootLayout() + .close(view, { + opacity: 0, + translate: { x: 0, y: -500 } + }) + .catch(ex => console.error(ex)) + +function getPopup(color: string, size: number, offset: number): View { + const layout = new StackLayout() + layout.height = size + layout.width = size + layout.marginTop = offset + layout.marginLeft = offset + layout.backgroundColor = color + layout.borderRadius = 10 + return layout +} +``` + +You can play with [the toolbox app here](https://github.com/NativeScript/NativeScript/tree/master/apps/toolbox/src/pages/root-layout.ts) + +You can also find a more [thorough example in this sample repo](https://github.com/williamjuan027/nativescript-rootlayout-demo) + +### WrapLayout + +`` is a layout container that lets you position items in rows or columns, based on the `orientation` property. When the space is filled, the container automatically wraps items onto a new row or column. + +#### Example: Default wrap layout + +The following example creates a row of equally-sized items. When the row runs out of space, the container wraps the last item to a new row. + +```html + + +``` + + + +#### Example: Vertical wrap layout + +The following example creates a column of equally-sized items. When the row runs out of space, the container wraps the last item to a new column. + +```html + + +``` + + + +#### Props + +| Name | Type | Description | +| -------------- | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `orientation` | `String` | Specifies the stacking direction.
Valid values: `horizontal` (arranges items in rows) and `vertical` (arranges items in columns).
Default value: `horizontal`. | +| `itemWidth` | `Number` | Sets the width used to measure and layout each child.
Default value: `Number.NaN`, which does not restrict children. | +| `itemHeight` | `Number` | Sets the height used to measure and layout each child.
Default value is `Number.NaN`, which does not restrict children. | +| `...Inherited` | `Inherited` | Additional inherited properties not shown. Refer to the [API Reference](https://docs.nativescript.org/api-reference/classes/wraplayout) | + +#### Additional children props + +None. + +### FlexboxLayout + +`` is a layout container that provides a non-exact implementation of the [CSS Flexbox layout](https://developer.mozilla.org/en-US/docs/Learn/CSS/CSS_layout/Flexbox). This layout lets you arrange child components both horizontally and vertically. + +#### Example: Default flex layout + +The following example creates a row of three equally-sized elements that span across the entire height of the screen. + +```html + + +``` + + + +#### Example: Column flex layout + +The following example creates a column of three equally-sized elements that span across the entire width of the screen. + +```html + + +``` + + + +#### Example: Row flex layout with items aligned to `flex-start` + +The following example creates a row of three items placed at the top of the screen. Items are placed in the order they were declared in. + +```html + + +``` + + + +#### Example: Row flex layout with custom order + +The following example creates a row of three items placed at the top of the screen. Items are placed in a customized order. + +```html + + +``` + + + +#### Example: Row flex layout with wrapping + +The following example creates four items with enabled line wrapping. When the row runs out of space, the container wraps the last item on a new line. + +```html + + +``` + + + +#### Example: Column flex layout with reverse order and items with a different `alignSelf` + +The following example shows how to use: + +- `flexDirection` to place items in a column, starting from the bottom. +- `justifyContent` to create equal spacing between the vertically placed items. +- `alignSelf` to modify the position of items across the main axis. + +```html + + +``` + + + +#### Props + +| Name | Type | Description | +| ---------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `flexDirection` | `String` | Sets the direction for placing child elements in the flexbox container.
Valid values:
`row` (horizontal, left to right),
`row-reverse` (horizontal, right to left),
`column` (vertical, top to bottom), and
`column-reverse` (vertical, bottom to top).
Default value: `row`. | +| `flexWrap` | `String` | Sets whether child elements are forced in a single line or can flow into multiple lines. If set to multiple lines, also defines the cross axis which determines the direction new lines are stacked in.
Valid values:
`nowrap` (single line which may cause the container to overflow),
`wrap` (multiple lines, direction is defined by `flexDirection`),and
`wrap-reverse` (multiple lines, opposite to the direction defined by `flexDirection`).
Default value: `nowrap`. | +| `justifyContent` | `String` | Sets the alignment of child elements along the main axis. You can use it to distribute leftover space when all the child elements on a line are inflexible or are flexible but have reached their maximum size. You can also use it to control the alignment of items when they overflow the line.
Valid values:
`flex-start` (items are packed toward the start line),
`flex-end` (items are packed toward the end line),
`center` (items are centered along the line),
`space-between` (items are evenly distributed on the line; first item is on the start line, last item on the end line), and
`space-around` (items are evenly distributed on the line with equal space around them).
Default value: `flex-start`. | +| `alignItems` | `String` | (Android-only) Sets the alignment of child elements along the cross axis on the current line. Acts as `justifyContent` for the cross axis.
Valid values:
`flex-start` (cross-start margin edge of the items is placed on the cross-start line),
`flex-end` (cross-end margin edge of the items is placed on the cross-end line),
`center` (items are centered оn the cross axis),
`baseline` (the item baselines are aligned), and
`stretch` (items are stretched to fill the container but respect `min-width` and `max-width`).
Default value: `stretch`. | +| `alignContent` | `String` | Sets how lines are aligned in the flex container on the cross axis, similar to how `justifyContent` aligns individual items within the main axis.
This property has no effect when the flex container has only one line.
Valid values:
`flex-start` (lines are packed to the start of the container),
`flex-end` (lines are packed to the end of the container),
`center` (lines are packed to the center of the container),
`space-between` (lines are evenly distributed; the first line is at the start of the container while the last one is at the end),
`space-around` (lines are evenly distributed with equal space between them), and
`stretch` (lines are stretched to take up the remaining space).
Default value: `stretch`. | +| `...Inherited` | `Inherited` | Additional inherited properties not shown. Refer to the [API Reference](https://docs.nativescript.org/api-reference/classes/flexboxlayout) | + +#### Additional children props + +When an element is a direct child of ``, you can work with the following additional properties. + +| Name | Type | Description | +| ---------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `order` | `Number` | Sets the order in which child element appear in relation to one another. | +| `flexGrow` | `Number` | Indicates that the child should grow in size, if necessary. Sets how much the child will grow in proportion to the rest of the child elements in the flex container. | +| `flexShrink` | `Number` | Indicates that the child should shrink when the row runs out of space. Sets how much the flex item will shrink in proportion to the rest of the child elements in the flex container. When not specified, its value is set to `1`. | +| `alignSelf` | `String` | (Android-only) Overrides the `alignItems` value for the child.
Valid values:
`flex-start` (cross-start margin edge of the item is placed on the cross-start line),
`flex-end` (cross-end margin edge of the item is placed on the cross-end line),
`center` (item is centered on the cross axis),
`baseline` (the item baselines are aligned), and
`stretch` (items is stretched to fill the container but respects `min-width` and `max-width`).
Default value: `stretch`. | +| `flexWrapBefore` | `Boolean` | When `true`, forces the item to wrap onto a new line. This property is not part of the official Flexbox specification.
Default value: `false`. | diff --git a/interaction.md b/components/interaction.md old mode 100644 new mode 100755 similarity index 93% rename from interaction.md rename to components/interaction.md index a879d8d9..5c46d0b9 --- a/interaction.md +++ b/components/interaction.md @@ -136,7 +136,7 @@ You can [read more about how this feature came to be here](https://blog.nativesc ### Animations with code -The easiest way to animate a **single** [`View`](/api-reference/classes/view.html) is by using the `View.animate` method which accepts an [`AnimationDefinition`](/api-reference/interfaces/animationdefinition.html), immediately starts the animation and then returns its finished promise. +The easiest way to animate a **single** [`View`](https://docs.nativescript.org/api-reference/classes/view.html) is by using the `View.animate` method which accepts an [`AnimationDefinition`](https://docs.nativescript.org/api-reference/interfaces/animationdefinition.html), immediately starts the animation and then returns its finished promise. **Example 20: How to execute animation on single view.** @@ -158,13 +158,13 @@ view.animate({ :::tip Note -You should create an [`Animation`](/api-reference/classes/animation.html) class in order to be able to **cancel** the animation. This is demonstrated below. +You should create an [`Animation`](https://docs.nativescript.org/api-reference/classes/animation.html) class in order to be able to **cancel** the animation. This is demonstrated below. ::: ### The AnimationDefinition interface -The [`AnimationDefinition`](/api-reference/interfaces/animationdefinition.html) interface is central for defining an animation for **one or more properties** of a **single** [`View`](/api-reference/classes/view.html). The animatable properties are: +The [`AnimationDefinition`](https://docs.nativescript.org/api-reference/interfaces/animationdefinition.html) interface is central for defining an animation for **one or more properties** of a **single** [`View`](https://docs.nativescript.org/api-reference/classes/view.html). The animatable properties are: - **opacity** - **backgroundColor** @@ -173,7 +173,7 @@ The [`AnimationDefinition`](/api-reference/interfaces/animationdefinition.html) - **rotate** - **width** and **height** -The [`AnimationDefinition`](/api-reference/interfaces/animationdefinition.html) interface has the following members: +The [`AnimationDefinition`](https://docs.nativescript.org/api-reference/interfaces/animationdefinition.html) interface has the following members: - **target**: The view whose property is to be animated. - **opacity**: Animates the opacity of the view. Value should be a number between 0.0 and 1.0. @@ -184,18 +184,18 @@ The [`AnimationDefinition`](/api-reference/interfaces/animationdefinition.html) - **duration**: The length of the animation in milliseconds. The default duration is 300 milliseconds. - **delay**: The amount of time, in milliseconds, to delay starting the animation. - **iterations**: Specifies how many times the animation should be played. Default is 1. iOS animations support fractional iterations, i.e., 1.5. To repeat an animation infinitely, use `Number.POSITIVE_INFINITY`. -- **curve**: An optional animation curve. Possible values are contained in the [AnimationCurve](/api-reference/modules/coretypes.animationcurve.html). Alternatively, you can pass an instance of type [`UIViewAnimationCurve`](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIView_Class/#//apple_ref/c/tdef/UIViewAnimationCurve) for iOS or [`android.animation.TimeInterpolator`](http://developer.android.com/reference/android/animation/TimeInterpolator.html) for Android. +- **curve**: An optional animation curve. Possible values are contained in the [AnimationCurve](https://docs.nativescript.org/api-reference/modules/coretypes.animationcurve.html). Alternatively, you can pass an instance of type [`UIViewAnimationCurve`](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIView_Class/#//apple_ref/c/tdef/UIViewAnimationCurve) for iOS or [`android.animation.TimeInterpolator`](http://developer.android.com/reference/android/animation/TimeInterpolator.html) for Android. - **width**: Animates view's width. - **height**: Animates view's height. All members of the interface are **optional** and have default values with the following exceptions: -- target is only optional when calling the `animate` method of a [`View`](/api-reference/classes/view.html) instance since it is set automatically for you. +- target is only optional when calling the `animate` method of a [`View`](https://docs.nativescript.org/api-reference/classes/view.html) instance since it is set automatically for you. - You must specify at least one property from this list: opacity, backgroundColor, scale, rotate or translate. ### The Animation class -The [`Animation`](/api-reference/classes/animation.html) class represents a **set** of one or more [`AnimationDefinitions`](/api-reference/interfaces/animationdefinition.html) that can be played either **simultaneously or sequentially**. **This class is typically used when you need to animate several views together**. The constructor of the [`Animation`](/api-reference/classes/animation.html) class accepts an array of [`AnimationDefinitions`](/api-reference/interfaces/animationdefinition.html) and a boolean parameter indicating whether to play the animations sequentially. Creating an instance of the [`Animation`](/api-reference/classes/animation.html) class does not start the animation playback. The class has four members: +The [`Animation`](https://docs.nativescript.org/api-reference/classes/animation.html) class represents a **set** of one or more [`AnimationDefinitions`](https://docs.nativescript.org/api-reference/interfaces/animationdefinition.html) that can be played either **simultaneously or sequentially**. **This class is typically used when you need to animate several views together**. The constructor of the [`Animation`](https://docs.nativescript.org/api-reference/classes/animation.html) class accepts an array of [`AnimationDefinitions`](https://docs.nativescript.org/api-reference/interfaces/animationdefinition.html) and a boolean parameter indicating whether to play the animations sequentially. Creating an instance of the [`Animation`](https://docs.nativescript.org/api-reference/classes/animation.html) class does not start the animation playback. The class has four members: - **play**: A method that starts the animation and returns the instance it was called on for fluent animation chaining. - **cancel**: A void method that stops the animation. @@ -953,7 +953,7 @@ More detailed examples are available on the [Animation Examples](#animation-exam ### Rotation using originX and originY -To create more complex animations, we might need to change the origin point around which the selected view will be transformed. This can be achieved using [`originX`](/api-reference/classes/view.html#originx) and [`originY`](/api-reference/classes/view.html#originy) properties of `View`. +To create more complex animations, we might need to change the origin point around which the selected view will be transformed. This can be achieved using [`originX`](https://docs.nativescript.org/api-reference/classes/view.html#originx) and [`originY`](https://docs.nativescript.org/api-reference/classes/view.html#originy) properties of `View`. **Example 5: Rotating a view around its center. Center of view is changed via `originX` and `originY` properties.** @@ -981,7 +981,7 @@ The properties `originX` and `originY` are JavaScript properties and can be assi ### Limitations -- `Span` and `FormattedString` can not be animated. `Span` and `FormattedString` elements are not extending the [`View`](/api-reference/classes/view.html) class, but only [`ViewBase`](/api-reference/classes/viewbase.html). Because of this, neither `Span` nor `FormattedString` are ui elements, making it impossible to animate them and causing a crash on iOS. +- `Span` and `FormattedString` can not be animated. `Span` and `FormattedString` elements are not extending the [`View`](https://docs.nativescript.org/api-reference/classes/view.html) class, but only [`ViewBase`](https://docs.nativescript.org/api-reference/classes/viewbase.html). Because of this, neither `Span` nor `FormattedString` are ui elements, making it impossible to animate them and causing a crash on iOS. ### Animation examples @@ -1799,20 +1799,20 @@ The result are received in the dialog resolved promise after the user closes or ### API References -| Name | Type | -| ----------------------------------------------------------------- | ----------- | -| [@nativescript/core/dialogs](/api-reference/modules.html#dialogs) | `Module` | -| [action](/api-reference/modules.html#dialogs) | `function` | -| [ActionOptions](/api-reference/modules.html#dialogs) | `interface` | -| [alert](/api-reference/modules.html#dialogs) | `function` | -| [AlertOptions](/api-reference/modules.html#dialogs) | `interface` | -| [confirm](/api-reference/modules.html#dialogs) | `function` | -| [ConfirmOptions](/api-reference/modules.html#dialogs) | `interface` | -| [login](/api-reference/modules.html#dialogs) | `function` | -| [LoginOptions](/api-reference/modules.html#dialogs) | `interface` | -| [LoginResults](/api-reference/modules.html#dialogs) | `interface` | -| [prompt](/api-reference/modules.html#dialogs) | `function` | -| [PromptOptions](/api-reference/modules.html#dialogs) | `interface` | +| Name | Type | +| ---------------------------------------------------------------------------------------------- | ----------- | +| [@nativescript/core/dialogs](https://docs.nativescript.org/api-reference/modules.html#dialogs) | `Module` | +| [action](https://docs.nativescript.org/api-reference/modules.html#dialogs) | `function` | +| [ActionOptions](https://docs.nativescript.org/api-reference/modules.html#dialogs) | `interface` | +| [alert](https://docs.nativescript.org/api-reference/modules.html#dialogs) | `function` | +| [AlertOptions](https://docs.nativescript.org/api-reference/modules.html#dialogs) | `interface` | +| [confirm](https://docs.nativescript.org/api-reference/modules.html#dialogs) | `function` | +| [ConfirmOptions](https://docs.nativescript.org/api-reference/modules.html#dialogs) | `interface` | +| [login](https://docs.nativescript.org/api-reference/modules.html#dialogs) | `function` | +| [LoginOptions](https://docs.nativescript.org/api-reference/modules.html#dialogs) | `interface` | +| [LoginResults](https://docs.nativescript.org/api-reference/modules.html#dialogs) | `interface` | +| [prompt](https://docs.nativescript.org/api-reference/modules.html#dialogs) | `function` | +| [PromptOptions](https://docs.nativescript.org/api-reference/modules.html#dialogs) | `interface` | ### Native Component diff --git a/components/label.md b/components/label.md new file mode 100755 index 00000000..0ca88781 --- /dev/null +++ b/components/label.md @@ -0,0 +1,170 @@ +--- +title: Label +--- + +## Label + +`
+``` + +```css +.tvElevation { + android-elevation: 5; +} +``` + +::: warning Note +Since NativeScript 5.4, the buttons on Android have default elevation (shadow) of 2, to provide Material Design elevation support. Removing the shadow will allow you to create a transparent button. To explicitly remove the elevation, set the android-elevation property to `0` as shown below: + +```css +.btn-no-elevation { + android-elevation: 0; +} +``` + +::: + +#### Using the `androidDynamicElevationOffset` property on Android + +Another property introduced with {N} 5.4 is androidDynamicElevationOffset. This property allows setting an elevation, which will be shown when an action was performed. Those actions can be, for example, tap, touch etc. + +Example: + +```html + + + + +``` + +```css +.sampleButton2 { + background-color: lightcyan; + android-elevation: 7; + android-dynamic-elevation-offset: 7; +} +``` + +### Supported Selectors + +::: warning Note +Currently the CSS support is limited only to the selectors and properties listed in the current documentation. +::: + +NativeScript supports a subset of the [CSS selector syntax](http://www.w3schools.com/cssref/css_selectors.asp). Here is how to use the supported selectors: + +- [Type selector](#type-selector) +- [Class selector](#class-selector) +- [ID selector](#id-selector) +- [Hierarchical selector](#hierarchical-selector-css-combinators) +- [Attribute selector](#attribute-selector) +- [Pseudo selector](#pseudo-selector) + +#### Type Selector + +Like [CSS element selectors](http://www.w3schools.com/cssref/sel_element.asp), type selectors in NativeScript select all views of a given type. Type selectors are case insensitive, so you can use both `button` and `Button`. + +```CSS +button { background-color: gray } +``` + +#### Class Selector + +[Class selectors](http://www.w3schools.com/cssref/sel_class.asp) select all views with a given class. +The class is set using the `className` property of the view. + +::: warning Note +To use `className` in JS/TS to add a class to an element, the class rule must be in a CSS file that is higher up the component tree than the element, such as `app.css`. +::: + +```html + +``` + +```css +.title { + font-size: 32; +} +``` + +```ts +import { Label } from '@nativescript/core' +const label = new Label() +label.className = 'title' +``` + +#### ID Selector + +[Id selectors](http://www.w3schools.com/cssref/sel_id.asp) select all views with a given id. The `id` is set using the `id` property of the view. + +```html + +``` + +```css +#login-button { + background-color: blue; +} +``` + +```ts +import { Button } from '@nativescript/core' +const btn = new Button() +btn.id = 'login-button' +``` + +#### Attribute Selector + +```html + +``` + +```css +button[testAttr] { + background-color: blue; +} +``` + +This selector will select all buttons that have the attribute `testAttr` with some value. + +Also, some more advanced scenarios are supported: + +- button[testAttr='flower'] {...} - Will apply CSS on every button that has the `testAttr` property set exactly to the value `flower`. +- button[testAttr~='flower'] {...} - Selects all buttons with a `testAttr` property that contains a space-separated list of words, one of which is "flower". +- button[testAttr|='flower'] {...} - Selects all buttons with a `testAttr` property value that begins with "flower". The value has to be a whole word, either alone like `btn['testAttr'] = 'flower'`, or followed by hyphen (-), like `btn['testAttr'] = 'flower-house'`. +- button[testAttr^='flower'] {...} - Selects all buttons with a `testAttr` property value that begins with "flower". The value does not have to be a whole word. +- button[testAttr$='flower'] {...} - Selects all buttons with a `testAttr` property value that ends with "flower". The value does not have to be a whole word. +- button[testAttr*='flo'] {...} - Selects all buttons with a `testAttr` property value that contains "flo". The value does not have to be a whole word. + +Attribute selectors could be used alone or could be combined with all type of CSS selectors. + +```html + + +``` + +```css +#login-button[testAttr='flower'] { + background-color: blue; +} +[testAttr] { + color: white; +} +``` + +#### Pseudo Selector + +A pseudo-selector or also pseudo-class is used to define a special state of an element. Currently, NativeScript supports only :highlighted pseudo-selector. + +```html + +``` + +```css +button:highlighted { + background-color: red; + color: gray; +} +``` + +#### Hierarchical Selector (CSS Combinators) + +A CSS selector could contain more than one simple selector, and between selectors a combinator symbol could be included. + +- (space) - Descendant selector. For example, the following code will select all buttons inside StackLayouts (no matter) at which level. + +```css +StackLayout Button { + background-color: blue; +} +``` + +- (>) - A direct child selector. Using the previous example, if the CSS is changed to: + +```css +StackLayout > Button { + background-color: blue; +} +``` + +The background-color rule will not be applied. In order to apply the selector, the WrapLayout element would need to be removed so that the Button is a direct child of the StackLayout. + +- (+) - An adjacent sibling selector, allows to select all elements, which are siblings of a specified element. + +##### Direct Sibling Test by Class + +```html + + + + + +``` + +```css +.layout-class .test-child + .test-child-2 { + background-color: green; +} +``` + +##### Direct Sibling Test by ID + +```html + + + + + +``` + +```css +.layout-class #test-child + #test-child-2 { + background-color: green; +} +``` + +##### Direct Sibling by Type + +```html + + + + + + + + + +``` + +```css +StackLayout Button + Label { + background-color: green; + color: white; +} +``` + +### CSS Overview + +--- + +#### Applying CSS Styles + +The CSS styles can be set on 3 different levels: + +- [Application-wide CSS](#application-wide-css): Applies to every application page +- [Page-specific CSS](#page-specific-css): Applies to the page's UI views +- [Component-specific CSS](#component-specific-css): Applies for component only +- [Inline CSS](#inline-css): Applies directly to a UI view + +If there is CSS declared on different levels—all will be applied. The inline CSS will have the highest priority and the application CSS will have the lowest priority. + +It is also possible to apply [platform-specific CSS](#platform-specific-css). + +#### Application Wide CSS + +When the application starts, NativeScript checks if the file app.css exists. If it does, any CSS styles that it contains are loaded and used across all application pages. This file is a convenient place to store styles that will be used on multiple pages. + +You can change the name of the file from which the application-wide CSS is loaded. You need to do the change before the application is started, usually in the app.js or app.ts file as shown below: + +/// flavor plain + +```ts +import { Application } from '@nativescript/core' +Application.setCssFileName('style.css') + +Application.run({ moduleName: 'main-page' }) +``` + +/// + +/// flavor angular + +```ts +platformNativeScriptDynamic({ bootInExistingPage: false, cssFile: 'style.css' }) +``` + +/// + +::: tip Note +The path to the CSS file is relative to the application root folder. +::: + +You could also check the name of the application-wide CSS file by using getCssFileName() method as shown below: + +```ts +import { Application } from '@nativescript/core' +const fileName = Application.getCssFileName() +console.log(`fileName ${fileName}`) +``` + +/// flavor plain + +#### Page Specific CSS + +When the page's XML declaration file is loaded, NativeScript looks for a CSS file with the same name (if such exists), reads any CSS styles that it finds, and automatically loads and applies them to the page. For example, a page named mypage.xml will automatically load any CSS in mypage.css. The CSS file must exist in the same folder as the XML file to be automatically applied. + +If you import any custom components on your page, the CSS from those components will be applied to the page, too. As a best practice, scope the CSS of custom components so that component styles do not "leak" on to pages. + +```xml + + +``` + +```css +/* GOOD: This will ONLY apply to the custom component */ +.mywidget .label { + color: blue; +} + +/* BAD: This will apply to the custom component AND potentially to the page where the component is used */ +.label { + color: blue; +} +``` + +You can also override CSS styles specified in the file by using the page's css property: + +```ts +page.css = 'button { color: red }' +``` + +/// + +/// flavor angular + +#### Component Specific CSS + +In an Angular application everything is a component, therefore, it is a very common task to add some CSS code that should only apply to one component. Adding component-specific CSS in a NativeScript-Angular app involves using a component’s styles or styleUrls property. + +```ts +@Component({ + selector: 'list-test', + styleUrls: ['style.css'], + template: ... + +// Or + +@Component({ + selector: 'list-test', + styles: ['.third { background-color: lime; }'], + template: ... +``` + +/// + +#### Adding CSS String + +This snippet adds a new style to the current set of styles. This is quite useful when you need to add a small CSS chunk to an element (for example, for testing purposes): + +```ts +page.addCss('button {background-color: blue}') +``` + +#### Adding CSS File + +This snippet adds new CSS styles to the current set. However, this method reads them from a file. It is useful for organizing styles in files and reusing them across multiple pages. + +```ts +page.addCssFile(cssFileName) +``` + +#### Inline CSS + +Similarly to HTML, CSS can be defined inline for a UI view in the XML markup: + +```html + +``` + +#### Platform-specific CSS + +NativeScript conventions make it easy to apply platform-specific CSS, either via separate stylesheets or via in-line declarations. For an overview of NativeScript's convention-based file name rules for targeting files at specific platforms and screen sizes, refer to this article in the docs. + +There are 4 primary ways to target styles at iOS or Android: + +/// flavor plain + +1. Platform-specific stylesheets (`styles.ios.css`, `styles.android.css`) +2. Platform-specific markup blocks (` ... `, ` ... `) +3. Platform-specific attributes (`