0

I'm following the Angular tutorial at https://angular.io/start/routing . However after a certain step my browser shows me a blank page and gives me Error: Can't resolve all parameters for ProductDetailsComponent: (?) in the console.

I tried different browsers (using Firefox as default), and also commenting / playing around with code to see which exact line causes the error (private route: ActivateRoute in the constructor of product-details.component.ts). Also checked for typos / whether I did miss something in the tutorial but I have followed it to 100% as far as I can see.

Also I use Ubuntu Mate 19.04 with the IntelliJ IDEA.

product-details.component.ts:

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { products } from '../products';

export class ProductDetailsComponent implements OnInit {
  product;

  constructor(
    private route: ActivatedRoute,
  ) { }
}

ngOnInit() {
  this.route.paramMap.subscribe(params => {
    this.product = products[+params.get('productId')];
  });
}
}

product-details.component.html:

<h2>Product Details</h2>
<div *ngIf="product">
  <h3>{{ product.name }}</h3>
  <h4>{{ product.price | currency }}</h4>
  <p>{{ product.description }}</p>    
</div>

product-list.component.ts:

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

import { products } from '../products';

@Component({
  selector: 'app-product-list',
  templateUrl: './product-list.component.html',
  styleUrls: ['./product-list.component.css']
})
export class ProductListComponent {
  products = products;

  share() {
    window.alert('The product has been shared!');
  }

  onNotify() {
    window.alert('You will be notified when the product goes on sale');
  }
}

product-list.component.html:

<h2>Products</h2>

<div *ngFor="let product of products; index as productId">

  <h3>
    <a [title]="product.name + ' details'" [routerLink]="['/products', productId]">
      {{ product.name }}
    </a>
  </h3>

  <p *ngIf="product.description">
    Description: {{ product.description }}
  </p>

  <button (click)="share()">
    Share
  </button>

  <app-product-alerts
    [product]="product"
    (notify)="onNotify()">
  </app-product-alerts>

</div>

app.module.ts:

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { RouterModule, Routes } from '@angular/router';
import { ReactiveFormsModule } from '@angular/forms';

import { AppComponent } from './app.component';
import { TopBarComponent } from './top-bar/top-bar.component';
import { ProductListComponent } from './product-list/product-list.component';
import { ProductAlertsComponent } from './product-alerts/product-alerts.component';
import { ProductDetailsComponent } from './product-details/product-details.component';

@NgModule({
  imports: [
    BrowserModule,
    ReactiveFormsModule,
    RouterModule.forRoot([
      { path: '', component: ProductListComponent },
      { path: 'products/:productId', component: ProductDetailsComponent },
    ])
  ],
  declarations: [
    AppComponent,
    TopBarComponent,
    ProductListComponent,
    ProductAlertsComponent,
    ProductDetailsComponent,
  ],
  bootstrap: [ AppComponent ]
})
export class AppModule { }

products.ts:

export const products = [
  {
    name: 'Phone XL',
    price: 799,
    description: 'A large phone with one of the best screens'
  },
  {
    name: 'Phone Mini',
    price: 699,
    description: 'A great phone with one of the best cameras'
  },
  {
    name: 'Phone Standard',
    price: 299,
    description: ''
  }
];

The result expected in the tutorial is that the routing redirects me to a view for a specific product from the main view, however after adding the above line the site just shows a blank page.

  • Are you sending 'productId' while navigate. It seems that system could not find it. – Harshad Vekariya Jul 22 '19 at 11:11
  • 1
    what does HTML look look like for this product-details.component.ts. Also where is declaration of component? like @Component with style and html properties. – Harshad Vekariya Jul 22 '19 at 11:38
  • @PawelOrlow Please add additional code to your question by editting your question and don't post the code in comments. If you've done so please also delete your code only comments. – frido Jul 22 '19 at 11:54
  • Please add the `@Component` decorator code to your `ProductDetailsComponent`. – frido Jul 22 '19 at 14:07

5 Answers5

1
product-details.component.ts

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { products } from '../products';

@Component({
  selector: 'app-product-details',
  templateUrl: './product-details.component.html',
  styleUrls: ['./product-details.component.css']
})
export class ProductDetailsComponent implements OnInit {
  product;

  constructor(
    private route: ActivatedRoute,
  ) { }

  ngOnInit() {
    this.route.paramMap.subscribe(params => {
      this.product = products[+params.get('productId')];
    });
  }
}

product-list.component.ts

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

import { products } from '../products';

@Component({
  selector: 'app-product-list',
  templateUrl: './product-list.component.html',
  styleUrls: ['./product-list.component.css']
})
export class ProductListComponent {
  products = products;

  share() {
    window.alert('The product has been shared!');
  }

  onNotify() {
    window.alert('You will be notified when the product goes on sale');
  }
}
App.module.ts

import { BrowserModule } from '@angular/platform-browser';

import { NgModule } from '@angular/core';

import { RouterModule, Routes } from '@angular/router';

import { AppRoutingModule } from './app-routing.module';

import { AppComponent } from './app.component';

import { ProductDetailsComponent } from './product-details/product-details.component';

import { ProductListComponent } from './product-list/product-list.component';

@NgModule({
  declarations: [
    AppComponent,
    ProductDetailsComponent,
    ProductListComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    RouterModule.forRoot([
      { path: '', component: ProductListComponent },
      { path: 'products/:productId', component: ProductDetailsComponent },
    ])
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }
vJyOtaku
  • 81
  • 4
0

import { products } from '../products';

From where do you get the data products model. Is it from REST API?

Can you show us you services.ts and product.ts code?

If you are getting data for the products from rest API. Store that Product model into observable and subscribe the product model in ProductDetailsComponent.

If you are using multiple services, make sure two services are not interdependent.

vJyOtaku
  • 81
  • 4
  • No service at this point - just the products.ts - I've added the code to the question. – Pawel Orlow Jul 22 '19 at 13:33
  • Please correct product-details.component.ts code. It doesn't have component decorator and ngOninit out of the component scope block – vJyOtaku Jul 22 '19 at 13:58
0

Made it work by updating package dependencies (see https://github.com/lena-spb/untitled4):

package.json:

"dependencies": {
    "rxjs": "6.5.2",
    "tslib": "1.10.0",
    "core-js": "2.6.9",
    "zone.js": "0.9.1",
    "jasmine-core": "2.99.1",
    "@angular/core": "8.1.2",
    "@angular/forms": "8.1.2",
    "@angular/common": "8.1.2",
    "@angular/router": "8.1.2",
    "jasmine-marbles": "0.6.0",
    "@angular/compiler": "8.1.2",
    "web-animations-js": "2.3.2",
    "@angular/animations": "8.1.2",
    "@angular/platform-browser": "8.1.2",
    "angular-in-memory-web-api": "0.8.0",
    "@angular/platform-browser-dynamic": "8.1.2"
  },
  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "0.801.2",
    "@angular/cli": "~8.1.2",
    "@angular/compiler-cli": "~8.1.2",
    "@angular/language-service": "~8.1.2",
    "@types/node": "~8.9.4",
    "@types/jasmine": "~2.8.8",
    "@types/jasminewd2": "~2.0.3",
    "codelyzer": "~4.5.0",
    "jasmine-core": "~2.99.1",
    "jasmine-spec-reporter": "~4.2.1",
    "karma": "~3.0.0",
    "karma-chrome-launcher": "~2.2.0",
    "karma-coverage-istanbul-reporter": "~2.0.1",
    "karma-jasmine": "~1.1.2",
    "karma-jasmine-html-reporter": "^0.2.2",
    "protractor": "~5.4.0",
    "ts-node": "~8.3.0",
    "tslint": "~5.11.0",
    "typescript": "3.4.5"
  }

src/app/app.module.ts:

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import {RouterModule, Routes} from '@angular/router';
import { ReactiveFormsModule } from '@angular/forms';

import { AppComponent } from './app.component';
import { TopBarComponent } from './top-bar/top-bar.component';
import { ProductListComponent } from './product-list/product-list.component';
import { ProductAlertsComponent } from './product-alerts/product-alerts.component';
import { ProductDetailesComponent } from './product-detailes/product-detailes.component';

const appRoutes: Routes = [
  { path: '', component: ProductListComponent },
  { path: 'products/:productId', component: ProductDetailesComponent }
];

@NgModule({
  imports: [
    BrowserModule,
    ReactiveFormsModule,
    RouterModule.forRoot(
      appRoutes,
      { enableTracing: true } // <-- debugging purposes only
    )
  ],
  declarations: [
    AppComponent,
    TopBarComponent,
    ProductListComponent,
    ProductAlertsComponent,
    ProductDetailesComponent
  ],
  bootstrap: [ AppComponent ]
})
export class AppModule { }

src/app/product-detailes/product-detailes.component.ts:

import { Component, OnInit } from '@angular/core';
import {ActivatedRoute, ParamMap} from '@angular/router';
import { products } from '../products';

@Component({
  selector: 'app-product-detailes',
  templateUrl: './product-detailes.component.html',
  styleUrls: ['./product-detailes.component.css']
})
export class ProductDetailesComponent implements OnInit {
  product;

  constructor(
    private route: ActivatedRoute,
  ) { }

  ngOnInit() {
    this.route.paramMap.subscribe((params: ParamMap) => {
      this.product = products[+params.get('productId')];
    });
  }
}

lena
  • 90,154
  • 11
  • 145
  • 150
  • This actually did help - thank you very much! Out of curiosity: do you have any thoughts on why this is in the constructor in the Angular tutorial? (Which doesn't seem to work - at least for me) – Pawel Orlow Jul 22 '19 at 14:06
  • it's a wrong answer actually, sorry for that... it fixes the first problem, but causes others. still not sure why injecting ActivatedRoute causes errors - will let you know if I find a mistake – lena Jul 22 '19 at 14:14
  • I just noticed - when I use this correction and navigate to item details I get " Error CONTEXT " and "Error TypeError". Thanks again for looking into it. – Pawel Orlow Jul 22 '19 at 14:27
0

As per your code : ngOnInit() method is written outside the ProductDetailsComponent, Update it as below

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { products } from '../products';

export class ProductDetailsComponent implements OnInit {
  product;

  constructor(
    private route: ActivatedRoute,
  ) { }


ngOnInit() {
  this.route.paramMap.subscribe(params => {
    this.product = products[+params.get('productId')];
  });
 }
}
Ankit Prajapati
  • 2,670
  • 2
  • 12
  • 22
0

Made it work:

ngOnInit() {
    this.route.paramMap.subscribe((params: ParamMap) => {
      let productId = params.get('productId') || 0;
        this.product = products[productId] || null;
    });
  }
metodribic
  • 1,561
  • 17
  • 27