( segmentGroup: UrlSegmentGroup, startIndex: number, commands: readonly any[], )
| 411 | } |
| 412 | |
| 413 | function updateSegmentGroupChildren( |
| 414 | segmentGroup: UrlSegmentGroup, |
| 415 | startIndex: number, |
| 416 | commands: readonly any[], |
| 417 | ): UrlSegmentGroup { |
| 418 | if (commands.length === 0) { |
| 419 | return new UrlSegmentGroup(segmentGroup.segments, {}); |
| 420 | } else { |
| 421 | const outlets = getOutlets(commands); |
| 422 | const children: {[key: string]: UrlSegmentGroup} = {}; |
| 423 | // If the set of commands applies to anything other than the primary outlet and the child |
| 424 | // segment is an empty path primary segment on its own, we want to apply the commands to the |
| 425 | // empty child path rather than here. The outcome is that the empty primary child is effectively |
| 426 | // removed from the final output UrlTree. Imagine the following config: |
| 427 | // |
| 428 | // {path: '', children: [{path: '**', outlet: 'popup'}]}. |
| 429 | // |
| 430 | // Navigation to /(popup:a) will activate the child outlet correctly Given a follow-up |
| 431 | // navigation with commands |
| 432 | // ['/', {outlets: {'popup': 'b'}}], we _would not_ want to apply the outlet commands to the |
| 433 | // root segment because that would result in |
| 434 | // //(popup:a)(popup:b) since the outlet command got applied one level above where it appears in |
| 435 | // the `ActivatedRoute` rather than updating the existing one. |
| 436 | // |
| 437 | // Because empty paths do not appear in the URL segments and the fact that the segments used in |
| 438 | // the output `UrlTree` are squashed to eliminate these empty paths where possible |
| 439 | // https://github.com/angular/angular/blob/13f10de40e25c6900ca55bd83b36bd533dacfa9e/packages/router/src/url_tree.ts#L755 |
| 440 | // it can be hard to determine what is the right thing to do when applying commands to a |
| 441 | // `UrlSegmentGroup` that is created from an "unsquashed"/expanded `ActivatedRoute` tree. |
| 442 | // This code effectively "squashes" empty path primary routes when they have no siblings on |
| 443 | // the same level of the tree. |
| 444 | if ( |
| 445 | Object.keys(outlets).some((o) => o !== PRIMARY_OUTLET) && |
| 446 | segmentGroup.children[PRIMARY_OUTLET] && |
| 447 | segmentGroup.numberOfChildren === 1 && |
| 448 | segmentGroup.children[PRIMARY_OUTLET].segments.length === 0 |
| 449 | ) { |
| 450 | const childrenOfEmptyChild = updateSegmentGroupChildren( |
| 451 | segmentGroup.children[PRIMARY_OUTLET], |
| 452 | startIndex, |
| 453 | commands, |
| 454 | ); |
| 455 | return new UrlSegmentGroup(segmentGroup.segments, childrenOfEmptyChild.children); |
| 456 | } |
| 457 | |
| 458 | Object.entries(outlets).forEach(([outlet, commands]) => { |
| 459 | if (typeof commands === 'string') { |
| 460 | commands = [commands]; |
| 461 | } |
| 462 | if (commands !== null) { |
| 463 | children[outlet] = updateSegmentGroup(segmentGroup.children[outlet], startIndex, commands); |
| 464 | } |
| 465 | }); |
| 466 | |
| 467 | Object.entries(segmentGroup.children).forEach(([childOutlet, child]) => { |
| 468 | if (outlets[childOutlet] === undefined) { |
| 469 | children[childOutlet] = child; |
| 470 | } |
no test coverage detected
searching dependent graphs…