Stack Overflow is a community of 4.7 million programmers, just like you, helping each other.

Join them; it only takes a minute:

Sign up
Join the Stack Overflow community to:
  1. Ask programming questions
  2. Answer and help your peers
  3. Get recognized for your expertise

I'm trying to import a custom component within my app.ts, but getting the error "TS2307: Cannot find module 'MyComponent'" I've looked it over, couldn't find anything that would help me.

Some people wrote: use "moduleResolution": "classic", but if I do that then I get the TS2307 error for everything else (all angular2/...) except MyComponent.

Others wrote "run tsc --declaration MyComponent.ts" - which does generate a MyComponent.d.ts file (while throwing errors in the console, like "Cannot compile unless the --module flag is provided" - which IS provided in tsconfig as an option - or "Cannot find module 'angular2/common'" for whatever I am importing in MyComponent.ts - but it does generate a .d.ts file), but when trying to compile app.ts it still gives the same TS2307 error. Nohting I've found worked.

This is my project structure:

| /app
|     /resources
|         /dev
|             /ts
|                 app.ts
|                 MyComponent.ts
|         /dist
|             /js
|                 app.js          // transcompiled app.ts
|                 MyComponent.js  // transcompiled MyComponent.ts
|             /modules            // files copied from the /node_modules/**/ folders (because node_modules is outside versioning and also outside public root (public root is the /app folder)
|                 es6-shim.js
|                 angular2-polyfills.js
|                 system.src.js
|                 Rx.js
|                 http.dev.js
|                 angular2.dev.js
|     index.html
|
| /node_modules
|     /angular2            // 2.0.0-beta.1
|     /es6-promise         // 3.0.2
|     /es6-shim            // 0.33.3
|     /rxjs                // 5.0.0-beta.0
|     /reflect-metadata    // 0.1.2
|     /systemjs            // 0.19.6
|     /zone.js             // 0.5.10
| 

This is my tsconfig.json:

{
    "compilerOptions": {
        "target": "ES5",
        "module": "system",
        "moduleResolution": "node",
        "sourceMap": true,
        "emitDecoratorMetadata": true,
        "experimentalDecorators": true,
        "removeComments": true,
        "noImplicitAny": false,
        "outDir": "app/resources/dist/js"
    },
    "files": [
        "app/resources/dev/ts/app.ts"
    ]
}

My app.ts :

import { bootstrap } from "angular2/platform/browser";
import { Component, View } from "angular2/core";
import { HTTP_PROVIDERS, Http, Response } from "angular2/http";

//My Custom Components:
import { MyComponent } from 'MyComponent';

/**
 * APP
 */
@Component({
    selector: 'my-app'
})
@View({
    directives: [MyComponent],
    template: `
        <my-component></my-component>
        plus other html
    `
})
class MyApp {
    public whatever;

    constructor(public http: Http) {
        // initialize this.whatever
    }

    makeRequest(): void {
        this.http.request('/_http/response.json')
            .subscribe((res:Response) => {
                this.whatever = res.json();
            });
    }
}

bootstrap(MyApp, [ HTTP_PROVIDERS ]);

And here's my MyComponent.ts:

import { Component } from 'angular2/core';
import { NgFor, NgIf } from 'angular2/common';

@Component({
    selector: 'my-component',
    template: `
        <div>MY IMPORTED COMPONENT</div>
    `
})
export class MyComponent {

    constructor() {}

    doSomething(): void {
        console.log('Doing something');
    }
}

My app.ts and MyComponent.ts are both in the same folder. Anyway, I've also tried path like this: import { MyComponent } from "/app/resources/dev/ts/MyComponent". Also, I've tried adding it to the files array in tsconfig (some people wrote that I should do that)... Still... Nothing worked! I've also checked the js output, because some people wrote that even though it throws the error, it might still be compiled... No luck!

====================

EDIT:

Ok, as inoabrian suggests in the first comment... I thought I tried everything, but it seems I haven't tried "./MyComponent" for the import part.

import { MyComponent } from './MyComponent';

Now the transcompiler does it's job. Thank you inoabrian, but now I have another issue. When I try running in the browser, I check my console and both systemjs and angular2-pollyfills scream:

http://my-app/resources/dist/js/MyComponent 404 (Not Found)

respectively:

XHR error (404 Not Found) loading  http://my-app/resources/dist/js/MyComponent(…)

Don't be thrown off by the path (when comparing to my project folder structure), I have my local server pointing at /app when I access http://my-app

This is my index.html with system config and all included js files:

<!DOCTYPE html>
<html lang="en">
<head>
    <!-- ... Meta tags & CSS assets -->

    <script src="resources/dist/modules/es6-shim.js"></script>
    <script src="resources/dist/modules/angular2-polyfills.js"></script>
    <script src="resources/dist/modules/system.src.js"></script>
    <script src="resources/dist/modules/Rx.js"></script>
    <script src="resources/dist/modules/http.dev.js"></script>
    <script src="resources/dist/modules/angular2.dev.js"></script>
</head>
<body>
<script>
    System.config({
        packages: {
            app: {
                format: 'register',
                defaultExtension: 'js'
            }
        }
    });
    System.import('resources/dist/js/app.js')
            .then(null, console.error.bind(console));
</script>

<my-app></my-app>

</body>
</html>

I have the feeling that I should do one more thing with the transcompiled file "MyComponent.js", but don't know what (I've tried to add it to System.import, hoping it would accept an array... but it seems it doesn't). What should I do next?

P.S. This is disappointing nevertheless, I hoped that importing MyComponent into app.ts would be everything, and that I would find the MyComponent class + everything from MyComponent.ts + my transcompiled app.ts file ALL IN ONE app.js file, not haveing yet another js file :(

share|improve this question
    
Have you changed the import location to './MyComponent'? – inoabrian Jan 19 at 14:06
    
I thought I've tried everything, but it seems I didn't. It worked with "./MyComponent"... but now things raise another issue, I've edited my question and added the issue at the end, after "EDIT:" – MrCroft Jan 19 at 14:39
    
Now this part seems to be a directory issue with your server. This can occur when you have nested directories for development and dist. So could you post what your server side code looks like..? I'm running off of lite-server and I set my directories to be served via an array [ ] – inoabrian Jan 19 at 15:13
1  
@Zhenyang Hua I forgot about this until recently... And I have just been answered on Udemy, by an instructor. Now it seems silly, but here's what the problem was: in the System.config section, I thought that the key "app" from "app: {}" is generic, a convention coming from "application". BUT NO! It seems that it's a PATH... to your app root folder. So, if you have your transpiled/js files in "folderX/blah-blah" then in System.config, instead of app: {} you should have : 'folderX/blah-blah' : {}. I hope you made the same mistake so this will help you. (continued in the next comment)... – MrCroft Apr 16 at 13:22
1  
... (continued): If you check out the folder structure in my question, I had my index.html IN the APP folder. So, my System.config should've actually been like this: System.config({ packages: { 'resources/dist/js': { format: 'register', defaultExtension: 'js' } } }); System.import('app') .then(null, console.error.bind(console)); The folder "app" didn't even existed as far as index.html was concerned. And now, if I check even their quickstart, it does explain that "app" si actually a path. But, until I've been told directly what my mistake was, I never noticed that they also explain that :)) – MrCroft Apr 16 at 13:22

I believe you are missing the proper parameter in system config. add it like this: System.config({ defaultJSExtensions: true })

share|improve this answer
    
Alright, adding this doesn't throw a 404 on MyComponent anymore ('cause now it actually looks for MyComponent.js) - I should have noticed that. BUT it breaks all the rest. Now I get 404s because it's looking in the wrong places for /angular2/platform/browser.js respectively http.js and core.js (which are not in /angular2 of course - they're actually outside the public root (/app is my public root) - but had no 404s on these before because it wasn't even requesting them before adding defaultJSExtensions: true, and everything worked fine). Why on earth is this happening :| ? – MrCroft Jan 24 at 10:03
    
I would suggest to go through the quick start or the tutorial : angular.io/docs/ts/latest/quickstart.html and also you should create a plunkr, because this seems to be a neverending story... :) your other files not accessible probably because you are not loading them in index.html. I believe if you check the tutorial it should start working. One more note, that there are some issues with beta1 so I would suggest to use beta0 for now. – eesdil Jan 24 at 10:13
    
Also, if you have a custom folder structure, it is hard to grab it at first, so I suggest to follow the recommendation on angular page for now. – eesdil Jan 24 at 10:15

What is a bit strange is that you don't have a MyComponent.js within the same folder than app.js. In my case, when I add the outDir in the tsconfig.json file, all my TypeScript files are compiled into JavaScript in this folder.

Here is my configuration in my tsconfig.json file:

{
  "compilerOptions": {
    "target": "ES5",
    "module": "system",
    "moduleResolution": "node",
    "sourceMap": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "removeComments": false,
    "noImplicitAny": false,
    "outDir": "app/resources/dist/js"
 },
  "exclude": [
    "node_modules"
  ]
}

I run the compilation phase with the command: tsc -w.

Hope it helps you, Thierry

share|improve this answer
    
It seems I haven't actually tried everything. I tried with "./MyComponent" for the import part in app.ts and it worked, the transcompiler did it's job - it wasn't a transcompiler issue, rather a path issue (don't know how I haven't tried "./" already) and YES, now I do have a MyComponent.js file... but now I have another issue, I've edited my question and added the issue at the end, after "EDIT:" – MrCroft Jan 19 at 14:42
    
In your project screenshot you have the MyComponent.ts but not the MyComponent.js the browser is looking for, have you compiled it yet? – Langley Jan 19 at 15:03
    
The file MyComponent.js is there, I just didn't update the project's folder/file structure in my question. I did it now. – MrCroft Jan 19 at 15:20
up vote 0 down vote accepted

I know it's long overdue, but perhaps others might benefit from an answer. I did realize what the final problem was (other than what I've already edited in the original question). Here it is: I did mention I had a custom folder structure and wasn't willing to change it. If I had, it would have worked by simply following the angular 2 quickstart. But it wouldn't have made me realize the problem in my specific case and I wouldn't have understood how System.js works.

The problem was in my System.config() - in the packages section. This is the bad code:

System.config({
    packages: {
        app: {
            format: 'register',
            defaultExtension: 'js'
        }
    }
});
System.import('my/path/to/app_main_file');

My mistake was thinking that the key "app" is simply a generic key, comming from the word "application". It turns out that in the packages object, each key actually represents a path (where does that package - it's files - reside within your application). So, assuming the folder where my transpiled files are would be "my/app/public" and "app_main_file" is the main js file of my application, then I should've actually had something like this:

System.config({
    packages: {
        'my/app/public': {
            format: 'register',
            defaultExtension: 'js'
        }
    }
});
System.import('my/app/public/app_main_file')
    .then(null, console.error.bind(console));

Or, you can write the config section even nicer, like this:

System.config({
    packages: {
        'my-app': {
            format: 'register',
            defaultExtension: 'js'
        }
    },
    map: {
        'my-app': 'my/app/public'
    }
});

I think it's pretty self-explanatory what "map" does and how to use it.

P.S. I know that in my answer I didn't follow the exact same folder structure as in the original question, but I think it makes more sense to explain it like this. If it matters, just replace "my/app/public" above with what I originally had in the question: "resources/dist/js/", and it's the same thing.

share|improve this answer

Add a .js extension to your module import. This will most likely throw the IDE error.But when you refresh it works. This is the problem I faced too. It worked yesterday at work and today I tried another example at home it would give 404 errors.

import {MyComponent} from 'MyComponent.js'

Another fix which worked for me is: I was having all the .ts files in the root folder. I created another sub folder app and moved them there.From there on i was able to refer to them without the extension. Not sure why it did not work in the root folder. But moving them inside another folder did the trick. Hope it helps

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.