web-dev-qa-db-fra.com

Comment puis-je utiliser conditionnellement [href] ou [routerLink] sur une ancre?

J'ai besoin que le même lien d'ancrage soit pointé de manière conditionnelle localement ou vers une ressource externe. j'ai essayé 

<a [href]="outside?externalUrl:null"  [routerLink]="outside?[]:['/route',id]" >test</a>

Mais ça ne marche pas. Je ne reçois aucune erreur, mais il pointe sur la même page locale et ignore l'URL externe. Des idées?

Une autre option serait de construire le lien, mais je ne trouve pas de documentation permettant d’accéder à routerLink dans un service.

Edit: Je sais que je peux cloner tout le lien avec *ngIf mais je ne veux pas le faire, mon lien contient une balise video avec beaucoup d'options.

8
Toolkit

Le moyen le plus simple serait d'utiliser *ngIf / else:

<ng-container *ngIf="outside; else internalBlock">
  <a [href]="externalUrl">External</a>
</ng-container>

<ng-template #internalBlock>
  <a [routerLink]="['/route', id]">Internal</a>
</ng-template>

EDIT # 1: (solution de contournement)

Puisque vous ne voulez pas utiliser *ngIf (je ne comprends toujours pas pourquoi), vous pouvez faire ceci:

Modèle:

<a href="javascript:void(0)" (click)="handleClick(outside, '/route', id, externalUrl)">Link</a>

Composant:

handleClick(outside: boolean, internalUrl: string, internalId: string, externalUrl: string): void {
  if (outside) {
    window.location.href = externalUrl;
    // You can also use Location class of Angular
  } else {
    this.router.navigate([`${internalUrl}/${internalId}`]);
  }
}
17
developer033

Pour un href conditionnel, en utilisant le paramètre attr. avant que le href ne fonctionne pour moi en utilisant une valeur nulle, comme ceci:

[attr.href]="!item.subMenu ? item.url : null"
1
ohjeeez

Vous pouvez accéder à instance de routerLink en injectant RouterLinkWithHref dans la directive.

Directive:

@Directive({
  selector: '[externalLink]'
})
export class ExternalLinkDirective {

  @Input() externalLink: string;

  constructor(
    // Inject RouterLinkWithHref
    @Optional() private link: RouterLinkWithHref
  ) { 

    if (!link) {
      return;
    }

    // Save original onClick method
    const onClick = link.onClick;

    // Replace method with your own (I know this is not good idea)
    link.onClick = (...args: any[]) => {
      if (this.externalLink) {
        // Process external url
        window.location.href = this.externalLink;
        return false;
      } else {
        // Process internal url by calling routerLink original method
        return onClick.apply(link, args);
      }
    }

  }

}

Utilisation:

<!-- Ignore router link and use external link -->
<a routerLink="/some/path" externalLink="https://google.com">Link</a>

Inconvénient de cette approche - l'attribut href dans le DOM n'a pas changé

1
taras-d

Après de nombreuses investigations, j'ai mis en place une approche différente de ce problème, car mon <a href>...</a> contient du code à l'intérieur (un div cliquable par exemple). Par exemple, je ne veux pas utiliser ngIf car cela me force à dupliquer le code interne de la div. Donc voici ma solution:

Composant HTML

<div>
   <a [href]="getRouterLink()" >
     <div class="section">
     <!-- stuff inside the div -->
     </div>   
   </a>
</div>

Composant JS

Component({
selector: 'app-home-section',
templateUrl: './home-section.component.html',
styleUrls: ['./home-section.component.scss']
})
export class HomeSectionComponent implements OnInit {

@Input() link: string;

constructor(private router: Router) { }

ngOnInit() {
}

isRouterLink() {

  if (this.link) {
    let firstLinkChar = this.link.charAt(0);
    let isSlash = firstLinkChar == '/';
    return isSlash;
  }

  return false;
}

getRouterLink() {

  let url = this.isRouterLink() ? window.location.Origin + this.link : 'http://' + this.link;  
return url;
 }
}

C’était le seul moyen de simplifier les choses, car même si j’ai mis le "www.exemple.com" directement dans la href (avec ou sans le [ ]), il a toujours ajouté l’URL de base. Ce n'est pas joli, mais c'est fonctionnel.

0
Tito Leiva