0

I'm working on my first Vue app and have run into a bit of a snag.

My question is: With a list of dictionaries, how can I find and loop through one of the dictionaries, but only if it contains a specific value to a given key?

For context, This is meant to be an online shop. I would like to loop through the list of categories in the data, and to display the products in a given category.

The data is structured like so:

data = {

    "categories": [

        {

            "title": "Pants",

            "products": [

                {

                    "name": "Levi Strauss",
                    "price": "$49.99",

                }

            ]

        },

        {

            "title": "Sneakers",

            "products": [

                {

                    "name": "Adidas",
                    "price": "$149.99",

                }

            ]

        }, {...}

I haven't been able to determine how to target a nested dictionary based on whether it contains a specific key/value pair. I'm used to Python, so I was hoping Vue would support v-for syntax similar to a Pythonic one-liner, something like this:

<template
    v-for="category.product in categories.products if category.title === Sneakers">
<p>{{ product.name }}</p>
<p>{{ product.price }}</p>

...But this type of functionality is not in the documentation, nor have I been able to find an equivalent during my searches over the last week.

I understand it's not likely this functionality exists in the way I was hoping, so I'll likely need to tweak the way I'm approaching it. I'm prepared to do what needs to be done in the name of doing this correctly.

The other options I've brainstormed and come across have been:

1. Change the structure of the JS Object

If I pull the category title out of its own dictionary and restructure the data so that title of the category is the key of the dictionary and the products are the value, I'll be able to target that dictionary and its value easily.

The issue I have with this approach is that I don't know whether I'd be able to access the actual value of the key-- that is, if the key/value pair is "foo" : "bar", will I be able to reference the key and therefore render the string foo in my HTML? Or would I have to keep a key/value pair that defines the category title, and call it with category.sneakers.title? This feels redundant; like it should be avoidable. Given that this is my only problem with this option, and that it's a small one, this is the alternative I have been leaning toward.

2. Use a Vue component

I managed to find another Stack Overflow post (of course, I can't find it now) in which the poster was asking a similar question. The proposed solution was a two-part answer, and one of the solutions was to use a Vue component.

Admittedly, I am not yet familiar with how to use components within Vue, and therefore don't know whether it would be the best solution in this case. I've looked over the documentation, and from what I can see, it seems this just might be the way to go. I'm reluctant to begin integrating Vue components, though, if they aren't what I'm in need of. Why replace your alternator if the issue is really your battery?


Thanks for reading my book of a question, and I want to thank you ahead of time for anyone willing to help. I hope the way I worded my problem was clear enough; it's so easy to fall into abstraction when you've been focused on an issue for so long. Please let me know if anything needs to be changed and I am happy to comply.

2 Answers 2

4

you can use a nested loop:

<div v-for="category in categories" v-if="category.title === 'Sneakers'">
    <div v-for="product in category.products">
        <p>{{ product.name }}</p>
        <p>{{ product.price }}</p>
    </div>
</div>

or filter your category first in a computed property and then loop through it products.

computed: {
    myProducts() {
        return this.categories.filter( ( category ) => { 
             return category.name === 'Sneakers';
        })[ 0 ].products;
    }
}

In the template loop though the products:

<div v-for="product in myProducts">
     <p>{{ product.name }}</p>
     <p>{{ product.price }}</p>
</div>
Sign up to request clarification or add additional context in comments.

2 Comments

A computed property is better than changing the template, because it is (a) cached (until the data it depends on changes), and (b) creates a less complicated template, which helps readability and future changes. Preparing your data with a computed property is more or less the standard.
Yeah you are making a good point. I was just providing more options. But you should also think of it performance wise, as the array grows in size you 're caching more data and Vue has to watch a bigger array. Thanks for the comment!
4

Use a computed property:

computed: {
  sneakerProducts() {
    return this.data.find(category => category.title === 'Sneakers').products;
  }
}

then from your template you can do:

<div v-for="sneaker in sneakerProducts">
    <p>{{ sneaker.name }}</p>
    <p>{{ sneaker.price }}</p>
</div>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.