angularwebpackbarcode-scannernativescript

Strange NativeScript/Angular2 issue, app looks for templates in the wrong location


I have a very basic Nativescript/Angular2 barcode scanner app where I just started to implement routing...

I have a Home component located at app/pages/home/home.component.ts and the home component's template is located in the same folder app/home/home.component.html When I build the app everyting seems to work fine untill the app gets deployed on a genyMotion emulator. I then get the below error.

It seems like it's looking for the home component's template under app/home.component.html for some reason? Any idea why this would happen? I checked and the import statements of all modules that reference the home component is correct. Any idea how I can go about figuring out what's happening here?

My error:

An uncaught Exception occurred on "main" thread.
java.lang.RuntimeException: Unable to resume activity {org.nativescript.barcodescanner/com.tns.NativeScriptActivity}: com.tns.NativeScriptException: 
Calling js method onCreateView failed

Error: File /data/data/org.nativescript.barcodescanner/files/app/home.component.html does not exist. Resolved from: home.component.html.
File: "/data/data/org.nativescript.barcodescanner/files/app/tns_modules/nativescript-angular/resource-loader.js, line: 22, column: 12

StackTrace:

    Frame: function:'FileSystemResourceLoader.get', file:'/data/data/org.nativescript.barcodescanner/files/app/tns_modules/nativescript-angular/resource-loader.js', line: 22, column: 19
    Frame: function:'DirectiveNormalizer._fetch', file:'/data/data/org.nativescript.barcodescanner/files/app/tns_modules/@angular/compiler/bundles/compiler.umd.js', line: 13661, column: 45
    Frame: function:'DirectiveNormalizer.normalizeTemplateAsync', file:'/data/data/org.nativescript.barcodescanner/files/app/tns_modul
    
    

my home.component.ts:

import { Component,} from '@angular/core';

import { RestService } from '../../services/rest.service';
import { LocalStorageService } from '../../services/local-storage.service';

@Component({
  selector: 'home',
  templateUrl: './home.component.html' 
})
export class HomeComponent {

  constructor(private restService: RestService, private localStorageService: LocalStorageService) {

}
    

}

my app.routing.ts:

(lots commented out of this file as i'm busy converting a web app to mobile and still in the process of adding all components...)

import { AppComponent } from './app.component';
//import { ProductComponent } from './components/product/product.component';
//import { StockTransactionComponent } from './Components/stock-transaction/stock-transaction.component';
//import { CheckBarcodesComponent } from './Components/check-barcodes/check-barcodes.component';
import { HomeComponent } from "./pages/home/home.component";
//import { SettingsComponent } from './Components/settings/settings.component';

export const routes = [
    //{path: "settings", component: SettingsComponent },
//  {path: "checkBarcodes", component: CheckBarcodesComponent },    
    {path: "", component: HomeComponent}
];

export const navigatableComponents = [
HomeComponent
];

my app.module.ts:

import { NgModule, ValueProvider } from "@angular/core";
import { NativeScriptFormsModule } from "nativescript-angular/forms";
import { NativeScriptModule } from "nativescript-angular/platform";
import { NativeScriptRouterModule } from 'nativescript-angular/router'
import { NativeScriptHttpModule } from 'nativescript-angular/http';


import { BarcodeScanner } from "nativescript-barcodescanner";

import { RestService } from './services/rest.service';

import { AppComponent } from "./app.component";
import { HomeComponent } from "./pages/home/home.component";
import { routes, navigatableComponents } from './app.routing';
@NgModule({
    imports : [
    NativeScriptModule,     
    NativeScriptFormsModule ,
    NativeScriptHttpModule,
    NativeScriptRouterModule,
    NativeScriptRouterModule.forRoot(routes)
    ],
    declarations : [
    AppComponent,
    HomeComponent,
    ...navigatableComponents
    ],
    providers : [
    RestService,
    BarcodeScanner],
    bootstrap : [AppComponent]      
})
export class AppModule {}

my app.component.ts:


import { Component } from "@angular/core";



@Component({
    selector: "main",
    template : "<page-router-outlet></page-router-outlet>"
})
export class AppComponent {}

Solution

  • You can change templateUrl to template and use inline html code.

    templateUrl: './home.component.html' => template: `<!-- contents of ./home.component.html -->`
    

    The url that is used in the templateUrl is not component-relative. You should read more about componet-relative urls and how to load them with webpack from the cookbook.

    By default, we must specify the full path back to the application root. We call this an absolute path because it is absolute with respect to the application root.

    There are two problems with an absolute path:

    We have to remember the full path back to the application root.
    
    We have to update the URL when we move the component around in the application files structure.
    

    It would be much easier to write and maintain our application components if we could specify template and style locations relative to their component class file.

    Component-relative paths are not default in Angular. And you should read why.

    Appendix: why component-relative is not the default

    Webpack users may prefer an alternative approach.


    Summary:

    You can try to use component-relative or absolute urls in the templateUrl attribute, but the inline solution is simple and easy. You can also read Creating Your First Angular 2 Components tutorial for approaching with your component templates.