0

I follow Angular tutorial from documentation, and it came to routing. This is a trial example application, and main differece is that my example is integrated with ASP.NET Core 2.2 web app and Angular components are displayed in .cshtml view.

Please note, that I use Angular components selectors in my ASP.NET Core views like this in index.cshtml, where all Angular views are rendered in there:

Index View

<current-time></current-time>
<app-top-bar></app-top-bar>
<app-product-list></app-product-list>

All was displayed fine, until I was trying to add routing to ProductListComponent in product-list.component.html:

    <h2>Products</h2>

<div *ngFor="let product of products">

  <h3>
    <a [title]="product.name + ' details'" [routerLink]="['/products', product.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>

And the ProductListComponent is declared in app.module.ts as follows:

import { BrowserModule } from '@angular/platform-browser';
import { RouterModule } from '@angular/router';
import { NgModule, Injector } from '@angular/core';
import { createCustomElement } from '@angular/elements';
import { APP_BASE_HREF } from '@angular/common';
import { ReactiveFormsModule } from '@angular/forms';

import { CurrentTimeComponent } from './current-time/current-time.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({
  declarations: [
    CurrentTimeComponent,
    TopBarComponent,
    ProductListComponent,
    ProductAlertsComponent,
    ProductDetailsComponent
  ],
  imports: [
    BrowserModule,
    ReactiveFormsModule,
    RouterModule.forRoot([
      { path: '', component: ProductListComponent },
      { path: 'products/:productId', component: ProductDetailsComponent },
    ])
  ],
  exports: [
    CurrentTimeComponent,
    TopBarComponent,
    ProductListComponent
  ],
  providers: [{ provide: APP_BASE_HREF, useValue: '/' }], //for ASP.NET Core
})
export class AppModule {
  constructor(private injector: Injector) {
  }

  ngDoBootstrap() {
    customElements.define('current-time', createCustomElement(CurrentTimeComponent, { injector: this.injector }));
    customElements.define('app-top-bar', createCustomElement(TopBarComponent, { injector: this.injector }));
    customElements.define('app-product-list', createCustomElement(ProductListComponent, { injector: this.injector }));
  }
}

According to the tutorial, when hovering mouse pointer over product in product-list view, I should receive anchor path: http://localhost:59119/products/1, but instead of this I have: http://localhost:59119/products/undefined.

Another thing is that when navigating my browser to http://localhost:59119/products/1 i receive 404.

Please note, that in my app.module.ts I have no bootstrap: [ AppComponent]. I assumed, that if Angular views are displayed by .cshtml views, I do not need this. Does it change anything? I start to suspect that yes.

Anyway, is there any way to make my navigation to the product details working?

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')];
    });
  }

}

productc.ts:

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

product-list.component.ts:

import { Component, OnInit } 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 implements OnInit {
  products = products;

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

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

  constructor() { }

  ngOnInit() {
  }
}
bakunet
  • 559
  • 8
  • 25
  • For the second question, it appears that `product.productId` doesn't exist. Can you post `product-list.component.ts` in your question? – Pieterjan Jul 21 '20 at 19:01
  • 1
    @bakunet, you can not do it in this way. Your main.app.module has a `bootstrap` tag. This is the component you need in your index.chtml (the selector of this component) – Eliseo Jul 21 '20 at 19:09
  • @Eliseo I added to **app.module.ts** `bootstrap: [ProductListComponent],` and same result. – bakunet Jul 21 '20 at 19:14
  • Ill try to play with this kind of routing, we will see... https://stackoverflow.com/a/49414757/12603542 – bakunet Jul 21 '20 at 19:33
  • @Eliseo Allright, I noticed now, that my approach was completly wrong. Actually, instead of using single components in my ASP app, I should use maybe several Angular apps, and make routing inside of them. I see, that the way I wanted to do it, is not supported, or lets say it differently, I was doing it wrong :) – bakunet Jul 21 '20 at 20:14

1 Answers1

1

For the First question which you have asked in getting undefined

http://localhost:59119/products/undefined

for this you have to update you html -

<div *ngFor="let product of products">

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

</div>

here productId is not defined that's why you are getting an error.

for the second question in which you are getting a 404 because here

  { path: 'products/:productId', component: ProductDetailsComponent },

as you can see for that path ProductDetailsComponent is defined for that route and angular doesn't route to cshtml files.

piedpiper
  • 520
  • 5
  • 18
  • Ad 1) if products are iterated with `
    `, the ID is not specified implicit in TS? Ad 2) Should not it be routed inside of SPA, somehow?
    – bakunet Jul 21 '20 at 18:34
  • 1
    productId was not defined anywhere in your code.can you check the object of product if the id is coming there and use that id in html like product.id. – piedpiper Jul 21 '20 at 18:36
  • I just updated question body with `products` collection definition in **products.ts**. Actually there is no `productId`, but when added, I have the same result. – bakunet Jul 21 '20 at 18:39
  • if there is no productid how you gonna route using that id? – piedpiper Jul 21 '20 at 18:41
  • Allright, I added `productId`s, but still I am getting url: `http://localhost:59119/products/undefined` – bakunet Jul 21 '20 at 18:42
  • Updated collection; – bakunet Jul 21 '20 at 18:44
  • 1
    In html you have to use product.productId in router link – piedpiper Jul 21 '20 at 18:45
  • Actually it worked, regarding url issue. Now, should I update **app.module.ts** with `bootstrap`, somehow, to make routing available inside of SPA, is this the issue regarding routing? – bakunet Jul 21 '20 at 18:49
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/218307/discussion-between-piedpiper-and-bakunet). – piedpiper Jul 21 '20 at 19:02
  • Thanks for your time. I noticed now, that my approach was completly wrong. Actually, instead of using single components in my ASP app, I should use maybe several Angular apps, and make routing inside of them. I see, that the way I wanted to do it, is not supported, or lets say it differently, I was doing it wrong :) – bakunet Jul 21 '20 at 20:15