Exploring nested JSON data in Vue.js

In my attempt to access nested JSON within an array using Vue for a simple search functionality, I encountered a problem. Each school is encapsulated in a "hit" array, causing the system to perceive only one result of "hit" instead of returning data for each individual school. I believe that adding 'hit' to every occurrence of 'schools' would solve this issue, but I am unsure how to proceed. Your assistance is greatly appreciated.

Here is the key part of my app file:

<template>
    <div class="app search">
        <!-- Search header -->
        <header id="searchHeader" class="search--header py-2 py-md-4">
            <div class="container">
                <div class="input-group">
                    <!-- Type filter -->
                    <TypeFilter v-model="type"/>

                    <!-- Location filter -->
                    <!--<LocationFilter />-->

                    <!-- Search box -->
                    <SearchBox v-model="searchTerm"/>

                    <!-- More filters -->
                    <!--<div class="dropdown checkbox-dropdown mx-2">
                        <button class="btn btn-lg btn-white py-3 px-4 dropdown-toggle" type="button" id="dropdownMenuButtonFilters" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">More Filters</button>
                        <div class="dropdown-menu" aria-labelledby="dropdownMenuButtonFilters">
                        </div>
                    </div>-->

                    <!-- Search button -->
                    <button v-on:click="searchSubmit(searchTerm)" class="btn btn-lg btn-white ml-2 px-4 search-submit">Search</button>
                </div>

                <!-- Active filters (hidden for v0) -->
                <!--<div class="search--header--filters mt-3">
                    <span class="badge">Filter</span>
                    <span class="badge">Filter</span>
                    <span class="badge">Filter</span>
                </div>-->
            </div>
        </header>

        <!-- Main results -->
        <div class="container">
            {{ message }}

            <!-- Result count and show/sort -->
            <ResultCount v-model="page" :items="schools.length" :perPage="10"/>

            <!-- Results -->
            <SchoolList :schools="pageOfSchools"/>

            <!-- Pagination -->
            <Pagination v-model="page" :items="schools.length" :perPage="10"/>
        </div>
    </div>
</template>

<script>
    import SchoolList from './SchoolList'
    import ResultCount from './ResultCount'
    import Pagination from './Pagination'
    import SearchBox from './SearchBox'
    import TypeFilter from "./TypeFilter";
    import LocationFilter from "./LocationFilter";
    import getArraySection from '../utilities/get-array-section'
    //import {schools as schoolData} from '../data'

    export default {
        name: 'app',
        components: {SchoolList, ResultCount, Pagination, SearchBox, TypeFilter, LocationFilter},
        data: () => ({
            searchTerm: '',
            type: '',
            //schools: [],
            schools: [
                {
                    "hit": [{
                        "title": "State Peter Pan Institute",
                    }, {
                        "title": "State Flatland University",
                    }, {
                        "title": "State Applewood Halls of Ivy",
                    }]
                }
            ],
            page: 1,
            message: '{}'
        }),
        computed: {
            pageOfSchools: function () {
                return getArraySection(this.schools, this.page, 10)
            }
        },
        watch: {
            /*searchTerm: function () {
                this.filterSchools()
            },
            type: function () {
                this.filterSchools()
            }*/
        },
        methods: {    
            filterSchools: function () {
                const searchTerm = this.searchTerm.toLowerCase()
                const type = this.type
                let result = schoolData

                if (searchTerm) {
                    result = result.filter(school => {
                        return (
                            school.title.toLowerCase().search(searchTerm) >= 0 ||
                            school.location.toLowerCase().search(searchTerm) >= 0
                        )
                    })
                }

                if (type) {
                    result = result.filter(school => school.type.indexOf(type) >= 0)
                }

                this.schools = result
                this.page = 1
            }
        },
        created: function () {
            this.filterSchools()
        }
    }
</script>

Let's take a look at my SchoolList component:

<template>
    <Transition name="swap" mode="out-in">
        <div class="school-list" :key="schools">
            <div class="row">
                <div class="col-md-8 search--results">
                    <School class="school row justify-content-between search--results--card my-2 pt-2 pb-3 border-bottom" v-for="school in schools" :item="school" :key="school"/>
                </div>

                <div class="col-md-4 mt-4 pl-md-6 search--results--featured">
                    <FeaturedList />
                </div>
            </div>
        </div>
    </Transition>
</template>

<script>
    import School from './School'
    import FeaturedList from './FeaturedList'

    export default {
        name: 'school-list',
        components: {School, FeaturedList},
        props: ['schools']
    }
</script>

<style scoped>
    .swap-enter-active, .swap-leave-active {
        transition: opacity 0.2s ease-in-out;
    }

    .swap-enter, .swap-leave-active {
        opacity: 0;
    }

    .swap-enter {
        opacity: 1;
    }
    .swap-leave-to {
        opacity: 0;
    }
</style>

Lastly, here is the School component I have created:

<template>
    <div>
        <div class="col-9 col-md-auto d-flex align-items-center card-body">
            <img v-bind:src="item.logo" class="logo mr-2 mr-md-4 p-2 bg-white rounded-circle">
            <div>
                <h5 class="mb-0"><a :href="item.url" class="text-dark">{{ item.title }}</a></h5>
                <p class="mb-0">{{ item.location }}</p>
                <TypeLabel class="badge type-label mt-2" v-for="type in item.type" :type="type" :key="type"/>
                <span class="badge badge-yellow mt-2">Featured</span>
            </div>
        </div>
        <div class="col-3 col-md-auto text-right">
            <button type="button" class="btn btn-link d-inline-flex px-2 save"><i></i></button>
            <button type="button" class="btn btn-link d-inline-flex px-2 share"><i></i></button>
            <a data-placement="top" data-toggle="popoverMoreInfo" data-title="Get More Info" data-container="body" data-html="true" href="#" id="login" class="btn btn-outline-light d-none d-md-inline-block ml-3">Get More Info</a>
            <div id="popover-content" class="d-none more-info">
                <form>
                    <div class="form-group mb-2 has-float-label">
                        <input class="form-control" id="your-name" type="text" placeholder="Your name"
                               aria-label="Your name" aria-describedby="your-name"/>
                        <label for="your-name">Your name</label>
                    </div>

                    <div class="form-group mb-2 has-float-label">
                        <input class="form-control" id="your-email" type="email" placeholder="Your email"
                               aria-label="Your email" aria-describedby="your-email"/>
                        <label for="your-email">Your email</label>
                    </div>

                    <div class="form-group mb-2 has-float-label">
                        <input class="form-control" id="your-phone" type="tel" placeholder="Your phone"
                               aria-label="Your phone" aria-describedby="your-phone"/>
                        <label for="your-phone">Your phone</label>
                    </div>

                    <button type="submit" class="btn btn-primary w-100">Request More Info</button>
                </form>
            </div>

        </div>
    </div>
</template>

<script>
    import TypeLabel from './TypeLabel'

    let parser = document.createElement('a')

    export default {
        name: 'school',
        props: ['item'],
        components: {TypeLabel},
        methods: {
            domainOf: url => ((parser.href = url), parser.hostname.replace(/^www\./, ''))
        }
    }
</script>

Answer №1

If you want to retrieve the name of each school, you can do so by following these steps:

const hit = this.schools[0].hit;

Next, iterate through the 'hit' property like this:

hit.forEach(function(el) {
  console.log(el.title);
});

To simplify this process, you may consider flattening the 'schools' property into a computed property for easier access.

In order to declare the flattened variable, define it within the computed properties section like this:

computed: {
 // other properties ...
 flattenedSchools: function () {
      const schools = [];
      if (this.schools && this.schools.length) {
          // Ensure that 'hit' exists and contains values
          this.schools[0].hit.forEach(function(el) {
            schools.push((el.title);
          });
      }
      return schools;
   },
},

You can then access the 'flattenedSchools' by using this.flattenedSchools and iterating through it accordingly.

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 showing menu only when a user scrolls on your WordPress site

I've been working on creating an effect where the menu stays hidden until the user starts scrolling. However, I can't seem to figure out why my code is not producing the desired effect. Here is the jQuery code snippet I am using: <script src= ...

Is the validation for the 'prop' property missing in props?

Seeking assistance with react's forwardRef feature. Currently encountering errors related to missing props validation in FadeContents. Is there a way to resolve this issue? It seems like the props need to be defined somewhere in order to be used withi ...

Encountering a cross-origin resource sharing (CORS) error while attempting

My Vue App is being hosted on an express server (nodejs running on port 60702) with the following setup: 'use strict'; const fs = require('fs'); const path = require('path'); const express = require('express'); var h ...

Total the values of several items within the array

Here is the data I currently have: const arrayA = [{name:'a', amount: 10, serviceId: '23a', test:'SUCCESS'}, {name:'a', amount: 9, test:'FAIL'}, {name:'b', amount: ...

What is the process for retrieving the text element from a React component when using React.cloneElement?

Can I centralize a translation function for all table header elements? const CustomersTable = () => { var headers=<> <th>Name</th> <th>Age</th> <th>Another text</th> </> ...

I'm facing a challenge where Multer is preventing me from showing images in my React app

Hi there, I'm currently facing an issue where I am using multer to save files on my server and store their path in mongodb. However, I am struggling to display them on my React application. Any assistance would be greatly appreciated. Thank you in ad ...

Having trouble triggering a click event on Ant Design menu button using jest and enzyme

Troubleshooting the simulation of a click event on the Menu component using Antd v4.3.1 Component: import React from 'react' import PropTypes from 'prop-types' import { Menu } from 'antd' import { SMALL_ICONS, PATHS } fro ...

Issue arises when isomorphic-dompurify is used alongside dompurify in Next.js 13 causing compatibility problems

I am currently facing a compatibility problem involving isomorphic-dompurify and dompurify in my Next.js 13 project. It appears that both libraries are incompatible due to their dependencies on canvas, and I am struggling to find a suitable alternative. M ...

What is the process of using JavaScript code to read a text file?

Trying to use Google Charts while reading data from a text file. The code in JS is written for this purpose: function readTextFile(file){ var rawFile = new XMLHttpRequest(); rawFile.open("GET", file, false); // using synchronous call var allTe ...

Tips for showing a single progress message when uploading multiple files on eleme.io [vuejs]

Tech Stack: Utilizing Vuejs with element.eleme.io framework. Objective: To implement a feature that allows users to upload multiple files while displaying only one "in progress message". To handle image uploads, we are integrating . During the upload pr ...

Tips for validating a text field in React Material UI depending on the input from another text field

Currently, I am working with Material UI TextField and encountered an issue where I need to create a code that establishes a dependency between two textfields. For example, if I enter the number 4 in textfield one, then the number in textfield two should ...

Can someone guide me on how to organize a div structure into a table format with the help of JQuery

I am new to JQuery and I have created a table using divs instead of the traditional table structure. Each row has the same ids, which I thought would help me sort the table. Here's an example of my code: <div class="column_title">Column 1</ ...

Setting Authorization with username, password, and domain in Angular 2 HTTP Request

I am facing an issue with calling an API method hosted on another machine using Angular 2 component with Http. When accessing the API from a browser, I can connect by entering a username and password as shown below: https://i.stack.imgur.com/JJqpC.png Ho ...

Can anyone point out where the mistake lies in my if statement code?

I've encountered an issue where I send a request to a page and upon receiving the response, which is a string, something goes wrong. Here is the code for the request : jQuery.ajax({ url:'../admin/parsers/check_address.php', meth ...

Open the HTML page from a separate directory

I'm facing an issue with loading additional HTML onto a page in my project when a link is clicked. The HTML fragment file I want to load is stored in a different folder within the project structure. Despite my efforts, I keep encountering a 404 error ...

Changing a 64-bit Steam ID to a 32-bit account ID

Is there a way to convert a 64-bit Steam ID to a 32-bit account ID in Node.js? According to Steam, you should take the first 32 bits of the number, but how exactly can this be done in Node? Would using BigNumber be necessary to handle the 64-bit integer? ...

The error encountered is an unhandled rejection with a message stating "TypeError: Cannot access property 'username' of null

My tech stack includes NodeJS, PassportJS, MySQL, and Sequelize (ORM for MySQL). The following code snippet is taken from my Passport.JS file. Whenever a user registers on my website, an error is returned if the username or email is already in use. If both ...

JavaScript effectively divides multiple child dropdowns with the main dropdown, thanks to Bootstrap innovation

I have implemented a jQuery function to dynamically change multiple child dropdowns based on the selected value of the main dropdown. For reference, you can view the image here. However, I encountered an issue when applying the Bootstrap styles "form-con ...

vuejs props become null upon page refresh

MyComponent.vue template: <ResponsiveNavigation :nav-links="navLinks" /> script data: () => ({ navLinks: [] }), created: function() { this.getSocialMediaLinks(); }, methods: { getSocialMediaLinks() { var self = this; ...

Ways to incorporate a scroll feature and display an iframe using JQuery

Is there a way to animate the appearance of hidden iframes one by one as the user scrolls down the website using jQuery? I have come across some solutions, but they all seem to make them appear all at once. I'm looking for a way to make the iframes s ...