External Link within menu

Hello,
I’m trying to create a standard navigation menu, but one of the links (in the middle of the nav) is an external link.
How could I achieve this within the menu snippet and maintain the callout for the folders to be linked, instead of hardcoding the menu for reach folder/page?
It wouldn’t be as big of an issue if I weren’t adding additional links to the nav in the future, though I will be.

Example of the nav needed: Roster (internal) Supervision (external link) About (internal) Contact (internal)

Any insight to this would be very helpful.

Thank you.

1 Like

I have a similar use case in one of my projects:

Add a field to your panel for your external url like:

ext_url:
    label: external URL (dominant)
    type:  url

Then you can switch your target url by something like this:

<?php

// main menu items
$items = $pages->visible();

?>
<nav>
  <ul>
    <?php
    foreach($items as $item): 
    ($item->ext_url() != '') ? $href = $item->ext_url()->html()
                             : $href = $item->url()->html();
    ?>
    
    <li><a href="<?php echo $href ?>">
        <?php echo $item->title()->html() ?>
      </a></li>
    <?php endforeach ?>
  </ul>
</nav>

Just with the menu example from the documentation.

1 Like

By the way: you can add a checkbox as well to switch between external and internal type, but I think this would not be necessary.
You can ass a target="_blank" as well. Simply create another variable which has a different text id ext_url is set.

Awesome. Thank you so much!

I am getting an error on line 12 which is:

: $href = $item->url()->html();

Also, within the panel, for ext_url. Is that within the folder panel blueprint, or elsewhere?
Kinda still learning a lot of this.

The first code is for your blueprint of that site. It must be added below fields: like this

<?php if(!defined('KIRBY')) exit ?>
 
title: some page
pages: false
files: true
  sortable: true
fields:
  title: 
    label: title
    type:  text
 
  ext_url:
    label: ext. URL (dominant)
    type:  url

Simply remove the html() method call:

: $href = $item->url();

Perfect! Got it. Thank you so much!

One last thing with trying to add the target="_blank"

Also, learned that you can just put ext_url: url link in the blueprint for the page and it will send it to that link.

The only issue I’m having currently is when I want to add target=“blank” it wraps like this: a href=“http://domain.com target=”_blank"

INSTEAD OF:
a href=“http://domain.com” target="_blank"

hm.

Sorry for that. Simply change your template code, not the url text in the panel.

The ugly way:

($item->ext_url() != '') ? $href = $item->ext_url()->html() . '" target="_blank'
                            : $href = $item->url();

The nice way:

if ($item->ext_url() != '') {
    $href = $item->ext_url()->html();
    $target = 'target="_blank"';
}else {
    $href = $item->url();
    $target = '';
}

...

<a href="<?php echo $href ?>" <?php echo $target ?>>

The last row is from the <li> tag.

I have a couple different scenarios and have not been able to implement this. I’m absolutely 100% sure that it’s me.

I have two different situations. I’ll post the code below. Any help would be greatly appreciated.

<?php snippet('header') ?>
<?php echo css('assets/css/screen.css'); ?>
  <main class="main" role="main">

    <div class="text2">
      <h1><?php echo $page->title()->html() ?></h1>
<h2>Subpages</h2>
<ul>
  <?php foreach($page->children() as $subpage): ?>
  <li>
    <a href="<?php echo $subpage->url() ?>">
      <?php echo html($subpage->title()) ?>
    </a>
  </li>
  <?php endforeach ?>
</ul>
       // End Menu
      <?php echo $page->text()->kirbytext() ?>
    </div>

  </main>

<?php snippet('footer') ?>

and

<?php snippet('header') ?>

  <main class="main" role="main">

    <div class="text">
      <h1><?php echo $page->title()->html() ?></h1>
      
      // Menu

<?php

// independent sub sub menu
$items = false;

// get the open item on the first level
if($root1 = $pages->findOpen()) {

  // get the open item on the second level
  if($root2 = $root1->children()->findOpen()) {

    // get visible children of the second level item
    $items = $root2->children()->visible();
  }
}

// only show the menu if items are available
if($items and $items->count()):


?>
<nav>
  <ul class="small-block-grid-1 medium-block-grid-2 large-block-grid-4 agentresourcemenu">
    <?php foreach($items as $item): ?>
    <li>
      <a<?php e($item->isOpen(), ' class="active"') ?> href="<?php echo $item->url() ?>"><?php echo $item->title()->html() ?></a>

      <?php

      // get all children for the current menu item
      $children = $item->children()->visible();

      // display the submenu if children are available
      if($children->count() > 0):

      ?>
      <ul>
        <?php foreach($children as $child): ?>
        <li><a<?php e($child->isOpen(), ' class="active"') ?> href="<?php echo $child->url() ?>"><?php echo $child->title()->html() ?></a></li>
        <?php endforeach ?>
      </ul>
      <?php endif ?>

    </li>
    <?php endforeach ?>
  </ul>
</nav>
<?php endif ?>


      // End Menu
      <?php echo $page->text()->kirbytext() ?>
    </div>

  </main>

<?php snippet('footer') ?>

These are my code snippets. I’ll keep trying and if I find a solution I will post it here.

Your code snippets are hard to read. Can you please wrap them by using three backticks (```)?

Fixed the layout on here. Still having issue with menus. What these pages do are call in child menus and the smaller one calls in children of a page, but without restrictions to their visability.

What exactly do you want to achieve and what does not work as expected?

BTW. Your css should go in the head tag of your header, not before the main element in your first snippet.

I’m trying to make the menu items linkable. So I can have sub menu pages that you can click on and be redirected to an external link.

What’s happening is when I try and impliment this code around the the foreach items. All my menu items disappear. With the smaller snippet, I have no idea where to even start. On the bigger one> I’ve tried just about everything.

The CSS is in the template because we don’t want it calling in the header because that’s global. We only want it calling on that template.

You have to youse this code inside you inner most for each loop. So in your case it’s $child instead of $item.

And with your CSS: simply do not close the head tag in your header snippet, so you can add elements in your template as well. Then close the head tag as fist action of your template.

Or even easier you in your head tag use the css auto function. Or manually create an if statement that checks the template and returns the css file only for the wanted template.

It’s generelly not such a good idea to close elements in another file, because it might easily be forgotten.

Therefore using the css auto function or an if statement is definitely the better way.

As regards the external links: Have you defined them in your content files? What is the name of the field? Can any page have an external link or only the subpages in the inner foreach loop (second example)?

Let’s suppose your field was called “ext_url” like in the examples above, your code for the first example would look like this:

<?php foreach($page->children() as $subpage): ?>
  <li>
    <a href="<?php e($subpage->ext_url()->isNotEmpty(), $subpage->ext_url(), $subpage->url()) ?>" <?php e($subpage->ext_url()->isNotEmpty(), 'target="_blank"', '') ?>>
      <?php echo html($subpage->title()) ?>
    </a>
  </li>
<?php endforeach ?>
2 Likes

Hey all, just stumbled across this and wondered whether anyone here had seen: https://getkirby.com/docs/cookbook/simple-redirects

Seems to be even easier than the suggestions above. Just thought I’d put it in for anyone else looking on the same topic.

1 Like