0

In a customer management app, I'm trying to have the following:

  • Client List (Left Side of the Page)
  • Client Details (Right Side of thePage) dashboard/client/id/
  • Add a Client (Right Side of the Page). dashboard/client/new.
  • Edit a Client (Right Side of the Page). dashboard/client/id/edit

I would like to change the view only on the right side depending what user clicks.

Router Configuration

//imports removed to make this shorter

const clientRoutes: Routes = [
  {
    path: '',
    component: ClientsComponent,
    children: [
      {
        path: '',
        component: ClientListComponent,
        children: [
          { path:'new', 
            component: ClientNewComponent
          },
          { path: ':id', 
            component: ClientDetailComponent,
            resolve: { client: ClientDetailResolver},
            children: [
              { path:'edit',
                outlet: 'section1',
                component: ClientEditComponent,
              },
            ]
          }
        ]
      }
    ]
  }
];

@NgModule({
  imports: [RouterModule.forChild(clientRoutes)],
  exports: [RouterModule ],
  providers: [ClientDetailResolver]
})
export class ClientRouting { }

Client List Component HTML

<div class="col-md-5">
  <div class="row button-wrapper">
    <div class="search-client">
      <i class="search-strong" ></i>
      <input id="searchInput" [(ngModel)]="term" placeholder="Search client by Name or Phone..." type="text">
    </div>
    <button type="button" class="btn-client-details" (click)="onSelectNew()">New Client</button>
  </div>
  <div>
      <div *ngIf="(clients | async)?.length==0">Add a Client</div>
      <div *ngIf="(clients | async)?.length>0" class="vertical-scroll">
        <table class="table">
          <thead>
          <tr class="muted">
            <th>Name</th>
            <th>Phone</th>
            <th>Client ID</th>
          </tr>
          </thead>
          <tbody>
          <tr *ngFor="let item of clients | async | filter:term"
            (click)="onSelect(item)">
            <td>{{item.name}}</td>
            <td>{{item.phone}}</td>
            <td>{{item.id}}</td>
          </tr>
          </tbody>
        </table>
      </div>
  </div>
</div>
<router-outlet></router-outlet>

Client Detail Component

 onSelectEdit(): void {
 this.router.navigate([{ outlets: { 'section1' : ['edit'] } }], { relativeTo: this.route });

Client Detail Component HTML

<div class="col-md-7">
 <div>
  <button type="button" class=" btn-client-details"
    (click)="onSelectEdit()">Edit</button>
</div>

<router-outlet name="section1"></router-outlet>

<div *ngIf="client">

//Show all client details for a selected client here {name}{address}etc
</div>
</div>

client app

J.Rem
  • 545
  • 2
  • 6
  • 24

2 Answers2

1

It's because the path edit doesn't exist.

The paths in your module are calculated by concatenating all the paths in the tree (parent + child + child...), which means that you end up with the relative path :id/edit, or the absolute path /dashboard/client/:id/edit.

Try with this code:

// Note. An `id` property must be defined/accessible in your code.

// Relative path syntax
// NB. `ActivatedRoute` must be injected into the `route` property.
this.router.navigate([{ outlets: { 'section1' : [id, 'edit'] } }, { relativeTo: this.route }]);

// Absolute path syntax
this.router.navigate([{ outlets: { 'section1' : ['dashboard', 'client', id, 'edit'] } }]);
AngularChef
  • 13,797
  • 8
  • 53
  • 69
  • This gives me same results. Error: Cannot match any routes. URL Segment: 'id/edit' with id being the corresponding id of a client. – J.Rem Jan 29 '17 at 17:21
  • Oops. I forget that `router.navigate()` doesn't assume paths to be relative by default. I updated my answer with the corrected syntax. I have never tried to combine the `outlets` with the `relativeTo` param. Please confirm whether the relative syntax works once you've had the chance to try it. – AngularChef Jan 29 '17 at 17:57
  • I still didn't have luck with that but now I use this and it get something: `this.router.navigate([{ outlets: { 'section1' : ['edit'] } }], { relativeTo: this.route });` However, after I click on "Edit" the form gets rendered on top of the details of the client. I'd like just to have the details view removed and open a form with the details so the user can edit. What is wrong with the router configuration or how can I best approach this pls? See the edited version of my question for references. – J.Rem Jan 30 '17 at 05:03
0

It's an angular2 bug: Secondary child outlet inside empty primary segment does not match

What you can try to do is to change the empty path of

path: '',
component: ClientListComponent,

to

path: 'whatever',
component: ClientListComponent,
user6749974
  • 206
  • 2
  • 2