Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

rhand's avatar
Level 6

internal link undefined

We have a MenuModal.vue that adds menu items to the menu for navigation. We have standard menu links going to secondary pages, we have external links and internal links. The internal links no longer work. They are supposed to make menu item go to anchor on page but now that part of the url is undefined like https://default.smtv.test/undefined .

For MenuModal.vue part for internal links we have

<!-- isMakingNewInternallink is a variable to show internal links inputs  -->
<div v-show="isMakingNewInternallink">
  <select v-model="internalLinkName" class="deadlink-input form-control">
    <option value="">url to link to</option>
    <option v-for="(module, index) in mainModules" :value="module.id" :key="`main-${index}`">{{ index + 1 }}. {{ module.name || module.getName() }} [Main]</option>
    <option v-for="(module, index) in footerModules" :value="module.id" :key="`footer-${index}`">{{ index + 1 }}. {{ module.name || module.getName() }} [Footer]</option>
  </select>
  <input type="text" v-model="newLinkName" placeholder="link label" class="deadlink-input form-control" style="margin: 0px;" />
  <div class="text-right">
    <button :disabled="!newLinkName.length || internalLinkName.length < 4" @click="createInternalLink" class="btn btn-primary create-deadlink">create</button>
  </div>
</div>

for data we have

data: function() {
  return {
    step: 1,
    menupages: [],
    pages: [],
    menuName: '',
    isMakingNewDeadlink: false,
    newDeadlinkName: "",
    editMenu: null,
    isMakingNewExternallink: false,
    isMakingNewInternallink: false,
    newLinkName: "",
    newLinkUrl: "",
    internalLinkName : "",
    newTab: true,
    isNewMenu: false,
    selectedDevice: null
  }
},

for creation of internal links we have this method

createInternalLink: function() {
            if (this.newLinkName.length < 1 || this.internalLinkName.length < 4) return;

            this.pages.push({
              guid:  this.uuidv4(),
              name: this.newLinkName,
              internalElemName: this.internalLinkName,
              level: 1,
              internal: true
            });

            this.newLinkName = '';
            this.internalLinkName = '';
            this.isMakingNewInternallink = false;
          },

What could be possible issue not linking properly to modules on page that have an anchor id like

...
<div id="module-3560" class="module-container" style="top: 375px; left: 46.666667%; width: 340px; height: 130px; z-index: 0; padding: 0px; max-width: 100vw; text-align: left;"><div class="module" style="width: 100%; height: 100%; z-index: 0; border-width: 0px; border-style: none; border-color: rgba(230, 230, 230, 0.5); ...;"><p>Ankers, ook wel bekend als 'anchors' in het Engels, zijn nuttige elementen in webontwerp die de gebruikerservaring kunnen verbeteren. Een anker is een HTML-tag die wordt gebruikt om naar een specifieke locatie op dezelfde webpagina te linken. Wanneer een gebruiker op een ankerlink klikt, wordt de pagina automatisch naar het aangegeven gedeelte gescrold, wat handig is om snel naar relevante inhoud te navigeren.</p></div></div>
...
0 likes
4 replies
LaryAI's avatar
Level 58

Based on the information provided, it seems that the issue might be related to how the internal links are being constructed and used within the application. The internalLinkName should correspond to the ID of the element on the page you want to navigate to. However, the provided code does not show how the internalLinkName is being used to construct the URL for the internal links.

Here's a possible solution to ensure that the internal links are constructed properly:

  1. Make sure that the internalLinkName corresponds to the actual ID of the module you want to link to. For example, if you have a module with an ID of module-3560, the internalLinkName should be module-3560.

  2. When constructing the URL for the internal link, you should append a hash (#) followed by the internalLinkName to the base URL of the page. This will create an anchor link that, when clicked, will navigate to the element with the corresponding ID on the page.

Here's how you might adjust the createInternalLink method to include the correct URL construction:

createInternalLink: function() {
  if (this.newLinkName.length < 1 || this.internalLinkName.length < 4) return;

  // Construct the URL with the hash for the internal link
  const internalUrl = `#${this.internalLinkName}`;

  this.pages.push({
    guid: this.uuidv4(),
    name: this.newLinkName,
    url: internalUrl, // Use the constructed URL here
    level: 1,
    internal: true
  });

  this.newLinkName = '';
  this.internalLinkName = '';
  this.isMakingNewInternallink = false;
},
  1. Ensure that when rendering the links in your template, you use the url property to set the href attribute of the anchor (<a>) tag:
<a v-for="page in pages" :href="page.url">{{ page.name }}</a>

This will create clickable links that navigate to the corresponding module on the page when clicked.

If the issue persists, you may need to debug further by checking the following:

  • Ensure that the internalLinkName is being set correctly when a menu item is selected.
  • Verify that the IDs of the modules on the page match the internalLinkName values.
  • Check for any JavaScript errors in the console that might be preventing the navigation.

Remember to replace the placeholder base URL (https://default.smtv.test/) with the actual base URL of your application if needed.

rhand's avatar
Level 6

We use code below for adding url with hash. So perhaps that method in other Vue 2 component resources/js/components/publish/MenuModule.vue is not receiving the data properly from resources/js/components/editor/modals/MenuModal.vue for some reason causing the undefined error

} else if(menu.internal && $("#module-" + menu.internalElemName).length) {
      $('.device-container').animate({
        scrollTop: $('.device-container').scrollTop() + ($("#module-" + menu.internalElemName).offset().top - $('.device-container').offset().top)
      }, 'normal');
}

Might be an issue there with InternalElemName . Not sure yet what.

wonder about

<option v-for="(module, index) in mainModules" :value="module.id" :key="`main-${index}`">{{ index + 1 }}. {{ module.name || module.getName() }} [Main]</option>
<option v-for="(module, index) in footerModules" :value="module.id" :key="`footer-${index}`">{{ index + 1 }}. {{ module.name || module.getName() }} [Footer]</option> 

If it does not receive the id it cannot be sent to other Vue component resources/js/components/publish/MenuModule.vue to add it to hash url . But when I check the select box dropdown I do see the options.

rhand's avatar
Level 6

When I used

...
navigate(menu) {
    if (menu.external) {
        let target = (menu.externalNewtab) ? '_blank' : '_self';
        window.open(menu.externalLinkUrl, target);
    } else if (menu.internal && document.getElementById("module-" + menu.internalElemName)) {
        console.log("Internal Menu:", menu);
        document.getElementById("module-" + menu.internalElemName).scrollIntoView()
    }

    if (!menu.id) return;
    // If home page change to root domain
    let page = menu.slug == 'home' ? '' : menu.slug;
    console.log("Page:", page);
    this.$router.push('/' + page);
},
...

for resources/js/components/publish/MenuModule.vue

I got

guid: "dc3c59c6-a9a2-4fb4-afcd-d32a5b47a565", name: "image", internalElemName: 3563, level: 1, internal: true}

Frontend the image module linked to has module-3563 so the id is correct. In resources/js/components/editor/modals/MenuModal.vue I got

 internalElemName: this.internalLinkName

, so it is replaced there by InternalLinkName and that is loaded from choice in

...
<select v-model="internalLinkName" class="deadlink-input form-control">
    <option value="">url to link to</option>
    <option v-for="(module, index) in mainModules" :value="module.id"
        :key="`main-${index}`">{{ index + 1 }}. {{ module.name || module.getName() }}
        [Main]</option>
...

so perhaps something is off there.

rhand's avatar
rhand
OP
Best Answer
Level 6

Main change made to fix all was adding prevent to @click and making sure not only that the menu is an internal menu item but also not an element name:

<router-link v-if="menu.internal && !menu.internalElemName" @click.prevent="navigate(menu)" class="menu-item" :style="menuItemStyle"
    :to="menu.slug == 'home' ? '/' : `/${menu.slug || ''}`">
    {{ menu.name }}
</router-link>

this done for main menu items and children.

Please or to participate in this conversation.