Dreampie
Dreampie

Reputation: 1331

Using relative path for templateUrl in Angular2+Webpack

import {Component} from 'angular2/core';

@Component({
  selector: 'app',
  styleUrls: ['./app.component.less'],
  templateUrl: './app.component.html'
})
export class AppComponent {
  name:string = 'Demo'
}

When using the relative path for templateUrl and styleUrls, I get: error 404, file not found:

zone.js: 101 GET http://localhost/app.component.html 404 (Not Found)

code: https://github.com/Dreampie/angular2-demo

I think this is not good design,because under different circumstances may build directory is not the same, can I change it to relative current path?

raw-loader can resolve this,but html-loader,less-loader not work for template,styles,it only work in string,so why not suport them?

import {Component} from 'angular2/core';

@Component({
  selector: 'app',
  styles: [require('./app.component.less')],
  template: require('./app.component.html')
})
export class AppComponent {
  name:string = 'Demo'
}

get other error:

browser_adapter.js:77 EXCEPTION: Error during instantiation of Token Promise<ComponentRef>!.BrowserDomAdapter.logError
browser_adapter.js:77 ORIGINAL EXCEPTION: Expected 'styles' to be an array of strings.

Upvotes: 6

Views: 8226

Answers (7)

Leo Lanese
Leo Lanese

Reputation: 496

WebPack2 do not require this moduleId anymore

Upvotes: -1

Valdermeyder Hussar
Valdermeyder Hussar

Reputation: 169

I have noticed the same error in my case. The reason of

Expected 'styles' to be an array of strings

in my case was css-loader which was used for loading CSS files and piped to angular2-template-loader.

What I understood from debugging that css-loader has some "smart" detection of changes in CSS files and if nothing were changed CSS file just wasn't exported as a string by webpack module.

As it was just hello word app my solution was very simple: replace css-loader by raw-loader. It is my version of loaders:

loaders: [
    {
        include: [srcPath],
        test: /\.js$/,
        loader: 'babel',
        query: {
            presets: ['es2015']
        }
    },
    {
        include: [srcPath],
        test: /\.js$/,
        loader: 'angular2-template-loader',
        query: {
            keepUrl: true
        }
    },
    {
        include: [srcPath],
        test: /\.(html|css)$/,
        loader: 'raw',
        query: {
            minimize: true
        }
    }
]

Upvotes: 0

Michail Michailidis
Michail Michailidis

Reputation: 12201

If you are using SystemJS for example, see my answer here: https://stackoverflow.com/a/40694657/986160

You can use model.id and convert it from your build path (that with the js) to the one with ts,css and html. That way you can use relative paths for your templates and styles in Angular 2 no problem

@Component({
   moduleId: module.id.replace("/dist/", "/"),
...
});

Upvotes: 0

Tim
Tim

Reputation: 129

Set the moduleId property to module.id for module-relative loading, so that urls are relative to the component.

@Component({
  moduleId: module.id,
  selector: 'app',
  styleUrls: ['app.component.less'],
  templateUrl: 'app.component.html'
})

Upvotes: 0

Eugene Fedotov
Eugene Fedotov

Reputation: 34

You need to try

@Component({
  selector: 'app',
  template: require('./app.component.html'),
  styles: [
    require('./app.component.less').toString()
      or
    String(require('./app.component.less'))
      or
    add css-to-string in your webpack conf ({test: /\.css$/, loaders: ['css-to-string', 'style', 'css']})
})

Upvotes: 0

Rose Nettoyeur
Rose Nettoyeur

Reputation: 919

Let me add some more information.

Why can't Angular calculate the HTML and CSS URLs from the component file's location?

Unfortunately, that location is not readily known. Angular apps can be loaded in many ways: from individual files, from SystemJS bundles, or from CommonJS bundles, to name a few. With this diversity of load strategies, it's not easy to tell at runtime where these files actually reside.

The only location Angular can be sure of is the URL of the index.html home page. So by default it resolves template and style paths relative to the URL of index.html. That's why we previously wrote our CSS file URLs with an app/ base path prefix.

Official Angular Docu

Upvotes: 3

Ankit Singh
Ankit Singh

Reputation: 24945

The ./ (single dot) notation works for ts paths only, it doesn't work with html or css paths.

These paths are relative to index.html, so according to your file structure, this should work

@Component({
  selector: 'app',
  styleUrls: ['app.component.less'],
  templateUrl: 'app.component.html'
})

Upvotes: 1

Related Questions