Tips for converting the iterator from a v-for to a string within a v-if

I am seeking to comprehend how to utilize v-for with v-if's in order to generate repeated teasers without resorting to more simplistic vue-logic. Currently, it appears that when using v-for with v-if nested within, it is not feasible to assign the index number to each teaser for selecting corresponding values.

In the example below, I aim to substitute the "1" with "{{ n }}" in the v-if statement. Is there a method to achieve this?

<script setup lang="ts">
defineProps<{
  title: string,
  icon1?: string, // possible values: 'sun', 'moon' or 'misc'
  textBefore1: string,
  textColor1?: string,
  textAfter1?: string,
  icon2?: string, // possible values: 'sun', 'moon' or 'misc'
  textBefore2: string,
  textColor2?: string,
  textAfter2?: string,
  icon3?: string, // possible values: 'sun', 'moon' or 'misc'
  textBefore3: string,
  textColor3?: string,
  textAfter3?: string,
  icon4?: string, // possible values: 'sun', 'moon' or 'misc'
  textBefore4: string,
  textColor4?: string,
  textAfter4?: string,
}>()
</script>

<template>
  <div class="teaserContent">
    <div class="inner">
      <div class="positioning--top">
        <div class="titleContainer">
          <h2 class="title">{{ title }}</h2>
        </div>
      </div>
      <div class="positioningBottom">

        <div v-for="n in 4" class="cardElement">
          <!-- Repeat the teaser 4 times and replace the number with the index "n" -->
          <div class="iconContainer">
            <span v-if="icon1 === 'sun' || icon1 === 'moon' || icon1 === 'misc'" class="material-symbols-rounded icon">{{ icon1 === 'sun' ? 'sunny' : icon1 === 'moon' ? 'clear_night' : icon1 === 'misc' ? 'brightness_4' : 'clear_night' }}</span>
            <span v-else class="material-symbols-rounded icon">clear_night</span>
          </div>
          <div class="textContainer">
            <span class="text text--before">{{ textBefore1 }}</span>
            <span v-if="textColor1" class="text text--color">{{ ' ' + textColor1 }}</span>
            <span v-if="textAfter1" class="text text--after">{{ ' ' + textAfter1 }}</span>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<style scoped lang="scss">
// style here ...
</style>

Edit: Added the working Solution

thanks to Keyboard Corporation

CardTeaser.vue:

<script setup lang="ts">
import type {ICardTeaser} from "@/components/CardTeaser/CardTeaser.types";

interface Props {
  title: string,
  teasers: Array<ICardTeaser>,
}

const props = defineProps<Props>();

const getIcon = (icon: ICardTeaser["icon"]) => {
  if (icon === 'sun') {return 'sunny';}
  if (icon === 'misc') {return 'brightness_4';}
  return 'clear_night';
};
</script>

<template>
  <div class="teaserContent">
    <div class="inner">
      <div class="positioning--top">
        <div class="titleContainer">
          <h2 class="title">{{ title }}</h2>
        </div>
      </div>
      <div class="positioningBottom">
        <div v-for="(teaser, n) in props.teasers" v-bind:key="`cardElement-${n}`" class="cardElement">
          <div class="iconContainer">
            <span class="material-symbols-rounded icon">{{ getIcon(teaser.icon) }}</span>
          </div>
          <div class="textContainer">
            <span class="text text--before">{{ teaser.textBefore }}</span>
            <span v-if="teaser.textColor" class="text text--color">{{ ' ' + teaser.textColor }}</span>
            <span v-if="teaser.textAfter" class="text text--after">{{ ' ' + teaser.textAfter }}</span>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<style scoped lang="scss">
// Styles here ...
</style>

CardTeaser.types.ts:

export interface ICardTeaser {
    textBefore: string;
    textColor?: string;
    textAfter?: string;
    icon?: 'sun' | 'moon' | 'misc';
}

Implementation of the Template with data:

<CardTeaser title="Card Teaser" :teasers="[
  {
    textBefore: 'Card 1',
    textColor: 'in color',
    textAfter: 'with more text',
    icon: 'sun',
  },
  {
    textBefore: 'Card 2',
    textColor: 'also in Color',
    icon: 'moon',
  },
  {
    textBefore: 'Card 3',
    textColor: 'in color',
    textAfter: 'and more text',
    icon: 'misc',
  },
  {
    textBefore: 'Card 4',
    textColor: 'with more color',
    textAfter: 'and other text',
  }
]"/>

(it seems I could also create a smaller Template for each card and simply place those within a CardTeaserContainer or something.)

Answer №1

Using the iterator variable n directly from v-for inside v-if as a string is not possible, but you can achieve this by creating a computed property that determines the correct property based on the index.

Begin by specifying your props as an array of objects:

defineProps({
 teasers: {
    type: Array,
    default: () => []
 },
})

Each object within the teasers array should include the attributes icon, textBefore, textColor, and textAfter.

Next, in your template, utilize v-for to loop through the teasers:

<div v-for="(teaser, n) in teasers" class="cardElement">
 <div class="iconContainer">
    <span v-if="teaser.icon === 'sun' || teaser.icon === 'moon' || teaser.icon === 'misc'" class="material-symbols-rounded icon">{{ teaser.icon === 'sun' ? 'sunny' : teaser.icon === 'moon' ? 'clear_night' : teaser.icon === 'misc' ? 'brightness_4' : 'clear_night' }}</span>
    <span v-else class="material-symbols-rounded icon">clear_night</span>
 </div>
 <div class="textContainer">
    <span class="text text--before">{{ teaser.textBefore }}</span>
    <span v-if="teaser.textColor" class="text text--color">{{ ' ' + teaser.textColor }}</span>
    <span v-if="teaser.textAfter" class="text text--after">{{ ' ' + teaser.textAfter }}</span>
 </div>
</div>

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

Tips for differentiating between elements with identical values in an HTML datalist using Angular

My boss is insisting that I use a datalist in our website interface to select an employee, even though there's no way to determine if the user typed in the name or picked from the list. The challenge is that the list must only display full names, but ...

Develop a specialized data structure for rows in ag grid that can adapt to changes

I have been working on creating an independent component using ag-grid. The column definitions are passed to this component from my application as input properties, defined like this: interface ColumnDef { field: string; headerName: string; } @Input() ...

integrating material design components into Vue.js applications

My website is built on the Vue framework and webpack technology. I recently discovered Google's Material Components Web CSS framework, which can be easily implemented using a cdn or npm package for basic html/javascript websites. However, I am encoun ...

Different types of subscriptions for forkJoin observable

I am currently making two API requests with typed responses and combining them using the Observable.forkJoin method. My goal is to store each of the results in separate typed variables. var observableOrganization: Observable<Organization> = this.get ...

When the query result is received in Angular TypeScript, translate epoch time into a time string

Here is the dilemma I am currently facing: I have an Angular script that requests data from a backend service and receives query results to display to the user. One of the fields in the query response is a time stamp, which is currently in epoch time forma ...

Understanding how to display a component within another component in Vue.js

I am faced with a scenario where I have a component that has the following template: <div v-for:"item in store" v-bind:key="item.type"> <a>{{item.type}}</a> </div> Additionally, I have another component named 'StoreCompone ...

Exploring the method to deactivate and verify a checkbox by searching within an array of values in my TypeScript file

I am working on a project where I have a select field with checkboxes. My goal is to disable and check the checkboxes based on values from a string array. I am using Angular in my .ts file. this.claimNames = any[]; <div class="row container"> ...

Strange Node.js: I always avoid utilizing `require()`, yet encountered an unexpected error

For more information on this particular issue, please refer to this link It's quite puzzling as I haven't used the require() function in my code, yet I'm receiving an error telling me not to use it. How odd! The problematic code snippet i ...

Vue js is throwing an error because it is unable to find the "buscador" property or method that is being referenced in the render function

I am currently diving into the world of laravel combined with Vue js. I am working on integrating a search engine using vue js components, and I would greatly appreciate any help you can provide. Thank you in advance. Below is the Vue js component where t ...

What are some techniques for managing scrolling within a particular element?

I am currently working with Vue.js and utilizing Element UI components. I want to incorporate a scroll management function to achieve infinite scrolling. To better understand, please refer to the screenshot in the Example section: Despite trying differen ...

Vue js version 2.5.16 will automatically detect an available port

Every time I run the npm run dev command in Vue.js, a new port is automatically selected for the development build. It seems to ignore the port specified in the config/index.js file. port: 8080, // can be overwritten by process.env.PORT, if port is in u ...

Utilizing Vuetify's datatable search property in conjunction with an autocomplete component

Currently, I am in the process of setting up a dropdown filter for each column within my Vuetify data table. It appears that the Vuetify autocomplete component offers the functionality I need, but I'm uncertain about how to utilize the values from the ...

Did not retrieve the expected value

Why does it seem like getters.getEventById(id) doesn't function the same as state.events.find(event => event.id === id) Check both console.logs at the start of the fetchEvent action. fetchEvent({ commit }, id) { var event = getters.getEve ...

The Vue-Apollo V4 composition API from @vue/apollo-composable encountered an error while trying to call it on the login form, resulting in the issue TS2349: "This expression is not callable. Type 'Ref<any>' has no

Being a newcomer in the world of Apollo, I am utilizing Vue composition API along with @vue/apollo-composable version V4 for my vue apollo client. My backend consists of a nodejs server with apollo server. Currently, I am facing an issue on the login page ...

Setting up AngularJS 1.5.x to function seamlessly with SystemJS and TypeScript

I'm looking to keep all my code in AngularJS 1.x while also preparing it for an easy upgrade to AngularJS 2 in the future. To align my code with Angular 2 standards, I am interested in using TypeScript and SystemJS in version 1.5.x initially. Is ther ...

Dealing with an AWS S3 bucket file not found error: A comprehensive guide

My image route uses a controller like this: public getImage(request: Request, response: Response): Response { try { const key = request.params.key; const read = getFileStream(key); return read.pipe(response); } catch (error ...

Achieving dynamic text alignment within a Grid tile container using HTML and Angular

Here is the main section of my parent component. <div class="o-tile-container "> <div *ngFor="let country of Countrys"> <app-country [na ...

Creating a new JavaScript object using a Constructor function in Typescript/Angular

Struggling with instantiating an object from an external javascript library in Angular/Typescript development. The constructor function in the javascript library is... var amf = { some declarations etc } amf.Client = function(destination, endpoint, time ...

How to Retrieve a Symbol in TypeScript

In the code snippet below, there is a function named factory that returns a Symbol of type Bob. However, TypeScript appears to forget the type of the return value immediately, leading to an error when trying to assign the return value to variable test one ...

Using TypeORM's QueryBuilder to select a random record with a nested relation

Imagine a scenario where I have the following entities: User @Entity('user', { synchronize: true }) export class UserEntity { @PrimaryGeneratedColumn('uuid') id: string; @Column() firstName: string; @Column() lastName: s ...