Skip to content

Latest commit

 

History

History
357 lines (345 loc) · 12.6 KB

File metadata and controls

357 lines (345 loc) · 12.6 KB

Week 4: Your Heroes on your Phone 📱

Day 1: Go Mobile 🚏

Put your app on your phone!

  • Install the NativeScript command line interface
    sudo npm install --global nativescript
    
  • We need to perform two extra steps because NativeScript is not yet fully compatible with Angular 10 (at the time of writing)
    • Remove the first line (as below) from the files tsconfig.app.json and tsconfig.base.json
      /* To learn more about this file see: https://angular.io/config/tsconfig. */
      
    • Install the Angular 9 version of schematics
      npm install --save-dev @schematics/angular@^9
      
  • Add NativeScript to your app
    ng add @nativescript/schematics
    
  • Run your app to check that it still works as before in the web browser
  • Now we need a couple more tweaks and we're good to go
    • Install version 5 of the copy-webpack-plugin
      npm install --save copy-webpack-plugin@^5
      
    • Add the following two lines to the end of the "compilerOptions" section in tsconfig.tns.json
      "baseUrl": "./",
      "experimentalDecorators": true
      
      • You will also need to add a comma at the end of the preceding line which contains a single curly bracket
  • Build the NativeScript app
    tns preview
    
    • This will display a QR code on your screen
  • To preview your app on your phone, you need to install two companion apps on your Android/iOS device(s):
    • NativeScript Playground (Android, iOS) — used to scan a QR code provided by the NativeScript CLI
    • NativeScript Preview (Android, iOS — used to host display your app
  • Scan the QR code with the NativeScript Playground app, which will connect your project with the NativeScript Preview app
    • If everything works, you will see the following on your phone: "auto-generated works!"
  • As always commit and synchronize your changes

Day 2: Move your Heroes 💨

We want our heroes to work in the web browser and the mobile app.

  • Make sure you read and follow these instructions carefully!
  • Migrate the app navigation
    • Add a shared file with the routes configuration in src/app: app.routes.ts
      import { Routes } from '@angular/router';
      
    • Cut and paste this code block from app-routing-module.ts to app.routes.ts
      const routes: Routes = [
        ...
      ];
      
      • We also need to export the routes, so change the first line to
        export const routes: Routes = [
        
    • Also cut and paste these import statements from app-routing-module.ts to app.routes.ts
      import { DashboardComponent }   from './dashboard/dashboard.component';
      import { HeroesComponent }      from './heroes/heroes.component';
      import { HeroDetailComponent }  from './hero-detail/hero-detail.component';
      
    • Add the following import to app-routing-module.ts
      import { routes } from './app.routes';
      
      • Change this line from
        import { RouterModule, Routes } from '@angular/router';
        
      • To
        import { RouterModule } from '@angular/router';
        
    • Remove this code block from app-routing-module.tns.ts
      export const routes: Routes = [
        ...
      ];
      
    • Add the following import to app-routing-module.tns.ts
      import { routes } from './app.routes';
      
      • And remove these two
        import { Routes } from '@angular/router';
        import { AutoGeneratedComponent } from '@src/app/auto-generated/auto-generated.component';
        
  • To get rid of the warning regarding 'Experimental support for decorators'
    • Go to Preferences -> Settings in Visual Studio Code
    • Enter 'decorator' into the search box
    • Enable the option for experimentalDecorators
  • Commit and synchronize your changes
    • We won't be reminding you about this anymore
    • By now you surely noticed how useful it is to compare against the last working version in the Source Control tab of Visual Studio

Day 3: Still Moving 😅

Today we'll prepare our components for the mobile app.

  • Remove the auto-generated component
    • Delete the complete folder src/app/auto-generated in Visual Studio
    • In app.module.ts and app.module.tns.ts remove the following two lines
      import { AutoGeneratedComponent } from '@src/app/auto-generated/auto-generated.component';
      AutoGeneratedComponent,
      
  • Migrate the components
    ng g migrate-component --name=dashboard
    ng g migrate-component --name=hero-detail
    ng g migrate-component --name=heroes
    
  • If you open the file app.module.tns.ts, you will notice that all imports starting with '@src/app/..' are marked as invalid
    • This is a Visual Studio Code issue and won't affect your app
  • From the Extensions tab in Visual Studio install the NativeScript extension
  • Let's see what our mobile app looks like now
    tns preview
    
    • Scan the QR code using the NativeScript Playground app

Day 4: App User Interface :octocat:

Our web app is quite nice, but we want our mobile app to feel like an app, not a web site.

  • In main.tns.ts replace
    platformNativeScriptDynamic().bootstrapModule(AppModule);
    
    • With
      platformNativeScriptDynamic({createFrameOnBootstrap: true}).bootstrapModule(AppModule);
      
  • Replace the first line of app.component.tns.html with these
    <ActionBar title="{{title}}">
      <ActionItem text="Dashboard" (tap)="dashboard()"></ActionItem>
      <ActionItem text="Heroes" (tap)="heroes()"></ActionItem>
    </ActionBar>
    
  • In app.component.tns.ts
    • After this line
      import { Component } from '@angular/core';
      
      • Add
        import { Router } from '@angular/router';
        
    • After this line
      export class AppComponent { }
      
      • Add
        constructor(private router: Router) {
        }
        
        dashboard() {
          this.router.navigateByUrl("/dashboard");
        }
        
        heroes() {
          this.router.navigateByUrl("/heroes");
        }
        
      • Remove the closing curly bracket } from
        export class AppComponent { }
        
      • And add it on a new line after the code block you just inserted
      • Use the tab key to indent the new code block by two spaces
  • Start the mobile app
    tns preview
    
  • Replace the content of dashboard.component.tns.html with
    <StackLayout>
      <Label text="Top Heroes" class="h3" textAlignment="center"></Label>/>
      <StackLayout orientation="horizontal">
        <Button *ngFor="let hero of heroes" textAlignment="center" class="h4" text="{{hero.name}}" nsRouterLink="/detail/{{hero.id}}"></Button>
      </StackLayout>
    </StackLayout>
    
  • Restart the mobile app if necessary
  • Replace hero-detail.component.tns.html with
    <StackLayout *ngIf="hero">
      <Label text="{{hero.name | uppercase}} Details" class="h2"></Label>
      <Label text="id: {{hero.id}}"></Label>
      <Label text="name:"></Label>
      <TextField [text]="hero.name"></TextField>
    </StackLayout>
    

Day 5: Mobile List of Heroes 📜

We will use a native list view component to display your heroes on your phone.

  • Install the NativeScript ListView from the terminal
    tns plugin add nativescript-ui-listview@rc
    
    • At the time of writing we need to use the release candidate (rc) version for compatibility with Angular 10
  • Edit app.module.tns.ts
    • After this line
      import { NativeScriptModule } from '@nativescript/angular';
      
      • Add
        import { NativeScriptUIListViewModule } from "nativescript-ui-listview/angular";
        
    • After
      imports: [
        NativeScriptModule,
      
      • Add
        NativeScriptUIListViewModule,
        
  • Replace heroes.component.tns.html with
    <StackLayout>
      <Label text="My Heroes" class="h2"></Label>/>
      <ListView [items]="heroes" (itemTap)="onSelectHero($event)">
        <ng-template let-hero="item">
          <StackLayout orientation="horizontal">
            <Label textAlignment="right" [text]="hero.id"></Label>
            <Label textAlignment="left" [text]="hero.name"></Label>  
          </StackLayout>
        </ng-template>
      </ListView>
    </StackLayout>
    
  • In heroes.component.ts
    • Add the following imports
      import { Router } from '@angular/router';
      import { ItemEventData } from '@nativescript/core/ui/list-view/list-view';
      
    • Change the constructor to
      constructor(private heroService: HeroService, private router: Router) { }
      
    • After the method getHeroes() add a new method
      onSelectHero(event: ItemEventData) {
        const hero = this.heroes[event.index];
        this.router.navigateByUrl("/detail/" + hero.id);
      }
      
  • Test your mobile app and verify that everything works like in the web version

Day 6: User Experience (UX) 😍

Your app should offer a consistent user experience which is optimized for web and mobile versions.

  • Use consistent font sizes
    • We use h1 for the app title and h2 for page titles
    • Adjust dashboard.component.html to use the h2 style to display the title
    • Adjust dashboard.component.tns.html to use the h2 style to display the title
  • Alignment of the page title
    • For the web app we will align titles left, the mobile app looks better with centered titles
    • Add the following attribute to the first label in hero-detail.component.tns.html and heroes.component.tns.html
      textAlignment="center"
      
      • Add it to the Label between class="h2" and >
  • Run both the web and mobile apps
    • Notice how the titles on all pages are now displayed the same
  • Open the HERO Details page in your web browser
    • Notice these layout issues
      • id: and name: are too far to the left
      • The hero name text field is displayed right below the label name:
      • The buttons have very small text
  • Adjust the padding for the hero detail page
    • In hero-detail.component.scss after
      /* HeroDetailComponent's private CSS styles */
      
      • Add
        div {
          padding-left: .2em;
        }
        
    • Also in hero-detail.component.scss add the following for: input {
      margin-top: .2em;
      
      • On a new line before the closing curly bracket }
    • In hero-detail.component.tns.html
      • Add the following attribute for the id: and name: Labels
        class="m-x-15"
        
  • Increase size of button text for the web app
    • In styles.scss before the following line
      /* everywhere else */
      
    • Add
      button {
        font-size: 100%;
      }
      
  • Only show the back button for the hero details page in the mobile app
    • In app.component.tns.ts
    • Replace
      import { Router } from '@angular/router';
      
      • With
        import { RouterExtensions } from '@nativescript/angular/router';
        
    • Replace everything within
      export class AppComponent {
        ...
      }
      
      • With
        constructor(private routerExtensions: RouterExtensions) {
        }
        
        dashboard() {
          this.routerExtensions.navigateByUrl("/dashboard", { clearHistory: true });
        }
          
        heroes() {
          this.routerExtensions.navigateByUrl("/heroes", { clearHistory: true });
        }
        
  • If you get stuck doing the changes to a file, revert your changes to this file in the Source Control tab and start fresh
  • Run the mobile app and observe the changes

Day 7: Building Blocks 🎍

We wrote a lot of code in the last weeks. Now's the time to learn more about its structure so you can write your own code.

  • Install the Mimo app on your phone or tablet
  • Use these settings
    • Choose your personal motivation
    • No coding experience
    • Web Development path
    • Regular, 10 minutes per day
    • Enable daily notification at a convenient time
    • Create a profile
    • Skip the free trial, we only need the basic features
  • Work through the daily Mimo lesson
    • Repeat daily until you complete the Web Development path