Different ways to display a static content list using Vue's named slots

I'm struggling to make the following setup work:

My parent template

<comp>
  <a href="#" slot="links">link 1</a>
  <a href="#" slot="links">link 2</a>
</comp>

and in my component comp, the template looks like this:

<ul class="comp">
  <li class="comp-item"><slot name="links"></slot></li>
</ul>

Right now, all my anchors are going into that single li tag (which is expected), but I want to have multiple li elements for each named slot I insert, like so:

<ul class="comp">
  <li class="comp-item"><a href="#" slot="links">link 1</a></li>
  <li class="comp-item"><a href="#" slot="links">link 2</a></li>
</ul>

Is there a way to achieve this without using scoped slots? Since my content is pure HTML, I feel it's unnecessary to wrap static content inside props to render them.

Most Vue UI frameworks seem to require using another custom component for each list item, which seems like overkill for this issue. Is there an alternative approach?

Answer №1

You can easily achieve this using a render function.

Vue.component("comp", {
  render(h){
    let links = this.$slots.links.map(l => h('li', {class: "comp-item"}, [l]))
    return h('ul', {class: 'comp'}, links)
  }
})

Check out this example in action:

console.clear()

Vue.component("comp", {
  render(h){
    let links = this.$slots.links.map(l => h('li', {class: "comp-item"}, [l]))
    return h('ul', {class: 'comp'}, links)
  }
})

new Vue({
  el: "#app"
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.js"></script>
<div id="app">
  <comp>
    <a href="#" slot="links">link 1</a>
    <a href="#" slot="links">link 2</a>
  </comp>
</div>

Alternatively, you can utilize a small utility component to render vNodes with a template like so:

Vue.component("vnode", {
  functional: true,
  render(h, context){
    return context.props.node
  }
})

Vue.component("comp", {
  template: `
    <ul class="comp">
      <li class="comp-item" v-for="link in $slots.links"><vnode :node="link" /></li>
    </ul>
  `
})

new Vue({
  el: "#app"
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.js"></script>
<div id="app">
  <comp>
    <a href="#" slot="links">link 1</a>
    <a href="#" slot="links">link 2</a>
  </comp>
</div>

Answer №2

If you want to utilize scoped slots instead of regular slots, here is how you can do it:

Within your comp component, ensure that it receives a prop called links, which should be an array of links (initialized as a custom option). Iterate through the links and pass each individual link as data to the slot, similar to passing props to a component.

Vue.component("comp", {
  template: `
    <ul class="comp">
      <li class="comp-item" v-for="link in links">
          <slot v-bind="link"></slot>
      </li>
    </ul>
  `,
  props: ["links"]
})

new Vue({
  el: "#app",
  // custom static option , accessed using vm.$options.links
  links: [
      {text: "link1"},
      {text: "link2"},
      {text: "lin3"}
  ]
})

In the parent component where the comp component is being used, make sure to use a <template> element with the special attribute slot-scope, indicating that it is a template for a scoped slot.

The value assigned to slot-scope will be the name of a temporary variable holding the props object passed from the child:

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.js"></script>
<div id="app">
  <comp :links="$options.links">
      <template slot-scope="link">
          <a href="#">{{link.text}}</a>
      </template>
  </comp>
</div>

You can view a working example on this JSFiddle link

Answer №3

If you prefer not to store your data in an array and display a list using v-for

You have the option to place all of them directly in the component without using a slot:

<ul class="custom-comp">
  <li class="comp-item"><a href="#">link 1</a></li>
  <li class="comp-item"><a href="#">link 2</a></li>
</ul>

Alternatively, you can use a slot:

<custom-comp>
  <ul class="custom-comp" slot="links">
    <li class="comp-item"><a href="#">link 1</a></li>
    <li class="comp-item"><a href="#">link 2</a></li>
  </ul>
</custom-comp>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Learn how to retrieve data from the console and display it in HTML using Angular 4

Need help fetching data inside Angular4 HTML from ts variable. Currently only able to retrieve 2 data points outside the loop. Can anyone assist with pulling data inside Angular4? HTML: <tr *ngFor="let accept of accepts"> ...

Tips for incorporating JavaScript into elements that have been modified using jQuery's .html() method

Consider this example: $('#key').on('click', function(){ $('.task').html("<button id='key'>Button</button>"+Date()); }) <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.j ...

Selected value is not displayed in the textbox when using autocomplete feature

---Ajax---- An issue has arisen with the autocomplete feature. While typing "wi" (for example, wipro), the drop-down list appears as expected. However, if only "wi" is selected in the text box, $(document).ready(function () { $("#company_name").key ...

Learn how to retrieve information using the dash operator in ReactJS

I find it a bit amusing, but I'm encountering an issue. Can anyone lend me a hand with this? So, I'm using an API to fetch some data and it appears that the response from the API is in this format: start-time:2323232 end-time:2332323 Now, when I ...

Is there a simpler method to access the source element for an event?

I'm just starting to learn JavaScript and jQuery, and right now I have the following code in my HTML: <a id="tog_table0" href="javascript:toggle_table('#tog_table0', '#hideable_table0');">show</a> After that, I hav ...

Trouble with reading from a newly generated file in a node.js program

Whenever I launch my results.html page, I generate a new JSON file and use express.static to allow access to the public folder files in the browser. Although my application is functioning properly, I find myself having to click the button multiple times f ...

Performing JavaScript functions after fetching an XSLT page via AJAX

Is there a way to trigger JavaScript at a particular time without relying on setInterval() or onClick()? The issue I'm facing is that when I click to load an XSLT page using Ajax, the JavaScript within it does not execute even though it's writt ...

IE Script loading

There is a script that I have, it appends in the document like so: window.d = document s = d.createElement('script') s.setAttribute('type','text/javascript') s.setAttribute('src',options.url) d.getElementById ...

Solving routing issues using object constructors in expressjs

Currently, I am in the early stages of developing an API REST using express and nodejs. As part of my routing process, I have decided to create separate "controllers" for each route and call these controllers within a router file. For example: ... router. ...

Using TypeScript with Watermelondb

I'm currently developing a React App and I want to implement Watermelondb for Offline Storage, but I'm unsure about using it with TypeScript. I have already set up the database and created Course and Lesson model files from the Watermelondb libra ...

Incorporating the id attribute into the FormControl element or its parent in Angular 7

I'm attempting to assign an id attribute to the first invalid form control upon form submission using Angular reactive forms. Here is my current component code: onSubmit() { if (this.form.invalid) { this.scrollToError(); } else { ...

Creating a nested object in React's handleChange method: a step-by-step guide

Hey there, I've been working on an onChange function called handleChange for a set of dynamically created inputs. This function receives the event and then performs the following actions: const handleChange = (e) => { const updatedValues = [...va ...

Confusion arises between Bootstrap button plugin and Vue checkbox click event

After incorporating bootstrap.min.js into my Vue app, I noticed that the checkboxes' @click event is no longer triggered. This issue specifically occurs when using bootstrap's button-group with data-toggle="buttons". If I remove bootstrap.min.js, ...

Configuring Visual Studio Publish settings for Single Page Applications deployed on Azure

I have set up my Azure App Service and downloaded the publish profile settings to use FTP for publishing my single page app to Azure. However, I am interested in configuring this process in Visual Studio similar to how one would publish a .Net application ...

Is combining Nuxt 3 with WP REST API, Pinia, and local storage an effective approach for user authentication?

My current project involves utilizing NUXT 3 for the frontend and integrating Wordpress as the backend. The data is transmitted from the backend to the frontend through the REST API. The application functions as a content management system (CMS), with all ...

Adding a promise to an array using Javascript

I am facing an issue while attempting to create an array of promises and then calling them using Promise.all. The problem lies in correctly pushing the functions into the array. It seems like they are getting executed instead of being inserted and waiting ...

Tally each div individually and display the count within each div, instead of showing the total count across

I have come across various solutions that show the total number of certain special divs, such as: $('.someclass').length However, I am facing a different challenge. I want to sequentially count each div with a numerical sequence. For instance, ...

Styling of Bootstrap HTML element not appearing as expected

Recently, I've been trying out a new approach by embedding Bootstrap components in an iframe. However, despite loading the necessary stylesheet and scripts, the elements seem to be missing their styles. Can anyone shed some light on why this might be ...

Steps for generating a hierarchical menu utilizing data from a CSV file

I am looking to use a CSV file to structure the menu on my webpage. Could someone assist me in creating a nested menu using JavaScript with the provided CSV data? The columns consist of: Level, Menu name, URL 0;"Service"; 1;"Service 1";"http://some-url- ...

Add new data to an existing array in Angular 7 without overwriting it

After clicking a button, I'm retrieving data from the WordPress API: <a (click)="initGetComments()">Get comments</a> This is the code snippet: export class AppComponent { commentsResults: CommentsItem[] = []; ...