1
votes

I'm learning Angular2 at the moment and the issue is that it change every time I find a good tutorial (and it's not fit to the latest Angular2 version).

Anyway - I'm trying to inject a service from one file to another, but can't repeat what guy on the tutorial did.

Here's the link to the tutorial: https://egghead.io/lessons/angular-2-injecting-a-service

./main.ts

import {bootstrap} from '@angular/platform-browser-dynamic';
import {Component} from "@angular/core";
import {TodoInput} from './todo-input';
import {TodoService} from "./todo-service";

@Component({
    selector: 'my-app',
    directives: [TodoInput],
    template: '<div><todo-input></todo-input></div>'
})

class App{}

bootstrap(App, [TodoService]);

./todo-service.ts

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

@Injectable()

export class TodoService {
    todos:string[] = [];
}

./todo-input.ts

import {Component} from "@angular/core";
import {TodoService} from "./todo-service";

@Component({
    selector: 'todo-input',
    template: `<div>
    I'm a todo input
    <input type="text" #myInput>
    <button (mouseover)="onClick($event, myInput.value)">Click me</button>
    </div>`
})

export class TodoInput{
    constructor(todoService:TodoService) {
        console.log(todoService);
    }

    onClick(event, value) {
        console.log(event, value);
    }
}

and I have that in a console:

EXCEPTION: TypeError: Cannot read property 'query' of null platform-browser.umd.js:962 EXCEPTION: TypeError: Cannot read property 'query' of nullBrowserDomAdapter.logError @ platform-browser.umd.js:962BrowserDomAdapter.logGroup @ platform-browser.umd.js:972ExceptionHandler.call @ core.umd.js:3696(anonymous function) @ core.umd.js:8982ZoneDelegate.invoke @ zone.js:323NgZoneImpl.inner.inner.fork.onInvoke @ core.umd.js:6075ZoneDelegate.invoke @ zone.js:322Zone.run @ zone.js:216(anonymous function) @ zone.js:571ZoneDelegate.invokeTask @ zone.js:356NgZoneImpl.inner.inner.fork.onInvokeTask @ core.umd.js:6066ZoneDelegate.invokeTask @ zone.js:355Zone.runTask @ zone.js:256drainMicroTaskQueue @ zone.js:474ZoneTask.invoke @ zone.js:426 platform-browser.umd.js:971EXCEPTION: Error: Uncaught (in promise): TypeError: Cannot read property 'query' of null platform-browser.umd.js:962EXCEPTION: Error: Uncaught (in promise): TypeError: Cannot read property 'query' of nullBrowserDomAdapter.logError @ platform-browser.umd.js:962BrowserDomAdapter.logGroup @ platform-browser.umd.js:972ExceptionHandler.call @ core.umd.js:3696(anonymous function) @ core.umd.js:8951schedulerFn @ core.umd.js:6007SafeSubscriber.__tryOrUnsub @ Subscriber.ts:240SafeSubscriber.next @ Subscriber.ts:192Subscriber._next @ Subscriber.ts:133Subscriber.next @ Subscriber.ts:93Subject._finalNext @ Subject.ts:154Subject._next @ Subject.ts:144Subject.next @ Subject.ts:90EventEmitter.emit @ core.umd.js:5996NgZone._zoneImpl.NgZoneImpl.onError @ core.umd.js:6227NgZoneImpl.inner.inner.fork.onHandleError @ core.umd.js:6096ZoneDelegate.handleError @ zone.js:327Zone.runGuarded @ zone.js:233_loop_1 @ zone.js:487drainMicroTaskQueue @ zone.js:494ZoneTask.invoke @ zone.js:426 platform-browser.umd.js:962STACKTRACE:BrowserDomAdapter.logError @ platform-browser.umd.js:962ExceptionHandler.call @ core.umd.js:3698(anonymous function) @ core.umd.js:8951schedulerFn @ core.umd.js:6007SafeSubscriber.__tryOrUnsub @ Subscriber.ts:240SafeSubscriber.next @ Subscriber.ts:192Subscriber._next @ Subscriber.ts:133Subscriber.next @ Subscriber.ts:93Subject._finalNext @ Subject.ts:154Subject._next @ Subject.ts:144Subject.next @ Subject.ts:90EventEmitter.emit @ core.umd.js:5996NgZone._zoneImpl.NgZoneImpl.onError @ core.umd.js:6227NgZoneImpl.inner.inner.fork.onHandleError @ core.umd.js:6096ZoneDelegate.handleError @ zone.js:327Zone.runGuarded @ zone.js:233_loop_1 @ zone.js:487drainMicroTaskQueue @ zone.js:494ZoneTask.invoke @ zone.js:426 platform-browser.umd.js:962Error: Uncaught (in promise): TypeError: Cannot read property 'query' of null at resolvePromise (zone.js:538) at PromiseCompleter.reject (zone.js:515) at eval (core.umd.js:8981) at ZoneDelegate.invoke (zone.js:323) at Object.NgZoneImpl.inner.inner.fork.onInvoke (core.umd.js:6075) at ZoneDelegate.invoke (zone.js:322) at Zone.run (zone.js:216) at zone.js:571 at ZoneDelegate.invokeTask (zone.js:356) at Object.NgZoneImpl.inner.inner.fork.onInvokeTask (core.umd.js:6066)BrowserDomAdapter.logError @ platform-browser.umd.js:962ExceptionHandler.call @ core.umd.js:3699(anonymous function) @ core.umd.js:8951schedulerFn @ core.umd.js:6007SafeSubscriber.__tryOrUnsub @ Subscriber.ts:240SafeSubscriber.next @ Subscriber.ts:192Subscriber._next @ Subscriber.ts:133Subscriber.next @ Subscriber.ts:93Subject._finalNext @ Subject.ts:154Subject._next @ Subject.ts:144Subject.next @ Subject.ts:90EventEmitter.emit @ core.umd.js:5996NgZone._zoneImpl.NgZoneImpl.onError @ core.umd.js:6227NgZoneImpl.inner.inner.fork.onHandleError @ core.umd.js:6096ZoneDelegate.handleError @ zone.js:327Zone.runGuarded @ zone.js:233_loop_1 @ zone.js:487drainMicroTaskQueue @ zone.js:494ZoneTask.invoke @ zone.js:426 zone.js:461 Unhandled Promise rejection: Cannot read property 'query' of null ; Zone: angular ; Task: Promise.then ; Value: TypeError: Cannot read property 'query' of null(…)consoleError @ zone.js:461_loop_1 @ zone.js:490drainMicroTaskQueue @ zone.js:494ZoneTask.invoke @ zone.js:426 zone.js:463 Error: Uncaught (in promise): TypeError: Cannot read property 'query' of null(…)consoleError @ zone.js:463_loop_1 @ zone.js:490drainMicroTaskQueue @ zone.js:494ZoneTask.invoke @ zone.js:426

but small change and it's starts working:

./todo-input.ts

import {Component} from "@angular/core";
import {TodoService} from "./todo-service";

@Component({
    selector: 'todo-input',
    template: `<div>
    I'm a todo input
    <input type="text" #myInput>
    <button (mouseover)="onClick($event, myInput.value)">Click me</button>
    </div>`
})

export class TodoInput{
    constructor() {
        console.log(TodoService);
    }

    onClick(event, value) {
        console.log(event, value);
    }
}

and I have normal object in the console (without any errors)

SystemJS config

<script>
    (function(global) {
        // map tells the System loader where to look for things
        var map = {
            'app':                        'app', // 'dist',
            '@angular':                   '@angular',
            'angular2-in-memory-web-api': 'angular2-in-memory-web-api',
            'rxjs':                       'rxjs'
        };
        // packages tells the System loader how to load when no filename and/or no extension
        var packages = {
            'app':                        { main: 'main.js',  defaultExtension: 'js' },
            'rxjs':                       { defaultExtension: 'js' },
            'angular2-in-memory-web-api': { main: 'index.js', defaultExtension: 'js' },
        };
        var ngPackageNames = [
            'common',
            'compiler',
            'core',
            'http',
            'platform-browser',
            'platform-browser-dynamic',
            'router',
            'router-deprecated',
            'upgrade',
        ];
        // Individual files (~300 requests):
        function packIndex(pkgName) {
            packages['@angular/'+pkgName] = { main: 'index.js', defaultExtension: 'js' };
        }
        // Bundled (~40 requests):
        function packUmd(pkgName) {
            packages['@angular/'+pkgName] = { main: pkgName + '.umd.js', defaultExtension: 'js' };
        };
        // Most environments should use UMD; some (Karma) need the individual index files
        var setPackageConfig = System.packageWithIndex ? packIndex : packUmd;
        // Add package entries for angular packages
        ngPackageNames.forEach(setPackageConfig);
        var config = {
            baseURL: '{!! url('public/admin/js') !!}',
            map: map,
            packages: packages
        }
        System.config(config);
    })(this);

    System.import('app').catch(function(err){ console.error(err); });
</script>

So my question is: Why I can't call that service from constructor argument as it's done in the tutorial? Or how to do that? Am I missing something? Tutorial seems to be really great and can give me very good basics of Angular2 but it's hared to learn when you stuck on something simple like that.

Many thanks! Tom

1
It should work (defining a constructor parameter for injection). Do you use TypeScript or ES6 only?Thierry Templier
My tsconfig.json: { "compilerOptions": { "target": "es5", "module": "commonjs", "moduleResolution": "node", "sourceMap": true, "emitDecoratorMetadata": true, "experimentalDecorators": true, "removeComments": false, "noImplicitAny": false, "outDir": "./public/admin/js/app/" }, "filesGlob": [ "./**/*.ts", "!node_modules/**/*.ts" ] }MrTomAsh
Your SystemJS configuration could also help...Thierry Templier
Sorry, I forget that I have some issues with tsconfig.json, so I decide that PhpStorm will compile / handle it automatic. So above configuration may not be working. Anyway I will add my SystemJS config above in a sec.MrTomAsh
Thanks! Are all your TS files under the app folder?Thierry Templier

1 Answers

0
votes

Get it sorted. TypeScript compiler delivered with PHPStorm was causing these issues. I've set up my tsconfig.json file and run it through npm tsc and it's working all now.

tsconfig.json

{
  "compilerOptions": {
    "target": "es5",
    "module": "commonjs",
    "moduleResolution": "node",
    "sourceMap": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "removeComments": false,
    "noImplicitAny": false,
    "outDir": "./public/admin/js/app"
  },
  "exclude": [
    "node_modules",
    "build",
    "vendor",
    "public"
  ]
}

Only think that I'm still not sure is how to get rid of these compiling errors from the log that seems to coming from excludes folders.

Cheers all!