Having trouble transferring data between Vue.JS components

Wondering how to pass data from the parent component (Home route) to the child component (playlist route) using props? Encountering a

"TypeError: Cannot read property 'length' of undefined"
error in the child component? These two components are currently on the same page, but moving the child component to its own route is triggering this issue.

App.vue

<template>
  <div id="app">
    <Header></Header>
    <router-view></router-view>
    <Footer></Footer>
  </div>
</template>

<script>
import Header from './components/header.vue'
import Footer from './components/footer.vue'


export default {
  name: 'app',
  components: {
    Header,
    Footer,
  }
}
</script>

<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 0px;
}
</style>

Main.js

import Vue from 'vue';
import App from './App.vue';
import "jquery";
import "bootstrap";
import VueRouter from 'vue-router';

import "bootstrap/dist/css/bootstrap.min.css"
import { library } from '@fortawesome/fontawesome-svg-core'
import { faSearch } from '@fortawesome/free-solid-svg-icons'
import { faRedo } from '@fortawesome/free-solid-svg-icons'
import { faPlus } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
import Home from './components/home.vue'
import Next from './components/next.vue'
import List from './components/myList.vue'


library.add(faSearch)
library.add(faRedo)
library.add(faPlus)

Vue.component('font-awesome-icon', FontAwesomeIcon)
Vue.use(VueRouter);
Vue.config.productionTip = false

const router = new VueRouter({
  routes: [
    {
      path: '/home',
      component: Home
    },
    {
      path: '/next',
      component: Next
    },
    {
      path: '/playlist',
      component: List
    }
  ]
});

new Vue({
  render: h => h(App),
  router
}).$mount('#app')

Parent component:

<template>
  <div class="container search">

    <div class="jumbotron" style="clear:both">
      <h1 class="display-4">{{title}}</h1>
      <p class="lead">{{intro}}</p>
      <hr class="my-4">
      <p v-if="validated" :class="errorTextClass">Enter a valid search term</p>

      <button
        type="button"
        class="btn btn-primary btn-lg mb-3"
        v-on:click="refreshPage"
        v-if="result.length > 1"
      >
        <font-awesome-icon icon="redo"/>Start again
      </button>
      <input
        class="form-control form-control-lg mb-3"
        type="search"
        placeholder="Search"
        aria-label="Search"
        v-model="search"
        required
        autocomplete="off"
        id="search"
      >

      <div v-for="(result, index) in result" :key="index">
        <div class="media mb-4">
          <img
            :src="resizeArtworkUrl(result)"
            alt="Album Cover"
            class="album-cover align-self-start mr-3"
          >
          <div class="media-body">
            <h4 class="mt-0">
              <!-- <button
                type="button"
                class="btn btn-primary btn-lg mb-3 float-right"
                v-on:click="addItem(result)"
              >
                <font-awesome-icon icon="plus"/>
              </button>-->

              <button
                type="button"
                class="btn btn-primary btn-lg mb-3 float-right"
                v-on:click="addItem(result)"
                :disabled="result.disableButton"
              >

                <font-awesome-icon icon="plus"/>
              </button>

              <b>{{result.collectionName}}</b>
            </h4>
            <h6 class="mt-0">{{result.artistName}}</h6>
            <p class="mt-0">{{result.primaryGenreName}}</p>
          </div>
        </div>
      </div>

      <div :class="loadingClass" v-if="loading"></div>

      <button
        class="btn btn-success btn-lg btn-block mb-3"
        type="submit"
        v-on:click="getData"
        v-if="result.length < 1"
      >
        <font-awesome-icon icon="search"/>Search
      </button>
    </div>
  </div>
</template>

<script>
import List from "../components/myList.vue";

export default {
  name: "Hero",
  components: {
    List
  },
  data: function() {
    return {
      title: "Simple Search",
      isActive: true,
      intro: "This is a simple hero unit, a simple jumbotron-style.",
      subintro:
        "It uses utility classes for typography and spacing to space content out.",
      result: [],
      errors: [],
      List: [],
      search: "",
      loading: "",
      message: false,
      isValidationAllowed: false,
      loadingClass: "loading",
      errorTextClass: "error-text",
      disableButton: false
    };
  },

  watch: {
    search: function(val) {
      if (!val) {
        this.result = [];
      }
    }
  },

  computed: {
    validated() {
      return this.isValidationAllowed && !this.search;
    },
    isDisabled: function() {
      return !this.terms;
    }
  },

  methods: {
    getData: function() {
      this.isValidationAllowed = true;
      this.loading = true;
      fetch(`https://thisapi.com/api`)
        .then(response => response.json())
        .then(data => {
          this.result = data.results;
          this.loading = false;
          /* eslint-disable no-console */
          console.log(data);
          /* eslint-disable no-console */
        });
    },

    toggleClass: function() {
      // Check value
      if (this.isActive) {
        this.isActive = false;
      } else {
        this.isActive = true;
      }
    },

    refreshPage: function() {
      this.search = "";
    },
    addItem: function(result) {
      result.disableButton = true; // Or result['disableButton'] = true;
      this.List.push(result);
      /* eslint-disable no-console */
      console.log(result);
      /* eslint-disable no-console */
    },

    resizeArtworkUrl(result) {
      return result.artworkUrl100.replace("100x100", "160x160");
    }
  }
};
</script>

<style>
.loading {
  background-image: url("../assets/Rolling-1s-42px.gif");
  background-repeat: no-repeat;
  height: 50px;
  width: 50px;
  margin: 15px;
  margin-left: auto;
  margin-right: auto;
}

.error-text {
  color: red;
}

.media {
  text-align: left;
}

.album-cover {
  width: 80px;
  height: auto;
}

.red {
  background: red;
}

.blue {
  background: blue;
}

.div {
  width: 100px;
  height: 100px;
  display: inline-block;
  border: 1px solid black;
}
</style>

Child component or /list (route)

<template>
  <div class="mb-5 container">
    <button type="button" class="btn btn-primary mt-2 mb-2 btn-block">
      My List
      <span class="badge badge-light">{{List.length}}</span>
    </button>

    <div class="col-md-4 float-left p-2 mb-3 " v-for="(result, index) in List" :key="index">
      <img
          :src="resizeArtworkUrl(result)"
          alt="Album Cover"
          class="album-cover align-self-start mr-3 card-img-top"
        >
      <div class="card-body">
        <h5 class="card-title">{{result.collectionName}}</h5>
        <h6 class="mt-0 mb-2">{{result.artistName}}</h6>
        <p class="mt-0 mb-2">{{result.primaryGenreName}}</p>

        <button class="btn btn-danger" v-on:click="removeElement(result)">Remove</button>
      </div>
    </div>
  </div>
</template>

<script>
export default {
   name: 'List',
   props: 
   ["List"],

  methods: {
    removeElement: function(index) {
      this.List.splice(index, 1);
    },

    resizeArtworkUrl(result) {
      return result.artworkUrl100.replace("100x100", "160x160");
    }
  }
};
</script>

<style scoped>

.album-cover {
    width: 100%;
    height: auto;
    background-color: aqua;
}

</style>

Answer №1

To navigate from the current parent to your playlist module, you can achieve it this way:

this.$router.push({
    path: '/playlist',
    params: {Playlist: this.Playlist}
});

Next, make sure to include the props property in your router configuration:

{
    path: '/playlist',
    component: Playlist,
    props: true,
}

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

Display the outline of a translucent image

Looking to create an image reveal effect on my website. I want to display only the outline of a transparent image using brightness, then gradually reveal the full image by removing the brightness effect. Currently, I achieve this with a black outline usi ...

When injected, the reactive variable returns an undefined value

I am currently working with Vue3 utilizing the options API. In the code snippet below, I have a provider component where I provide a reactive version of the object isToggleBtnLabelDigitizePolygon. Initially, the value of isToggleBtnLabelDigitizePolygon is ...

How to creatively position custom arrows in a React JS Nuka Carousel

Seeking assistance on properly positioning custom arrows within the Nuka Carousel component. After combining the decorators, I found that both of my arrows are appearing side by side. How can I address this issue? My goal is to have one arrow positioned in ...

Adding an extra element to the <MuiThemeProvider /> causes the page to display as blank with no error notifications

After incorporating Material UI into my Meteor application via npm install --save material ui I successfully implemented the <Header /> component in my app.js file. However, when I try to add additional components, such as localhost:3000, all I see ...

I attempted to initiate a transition using JavaScript, but unfortunately it failed to execute

Hey there! I'm just starting out with HTML, CSS, and JavaScript, and I've been trying to make a transition work using JavaScript. The element I'm working with is a "menu-icon" which is a span tag with a small image nested inside another div ...

Unable to bind click eventListener to dynamic HTML in Angular 12 module

I am facing an issue with click binding on dynamic HTML. I attempted using the setTimeout function, but the click event is not binding to the button. Additionally, I tried using template reference on the button and obtaining the value with @ViewChildren, h ...

How to Align Text and Image Inside a JavaScript-Generated Div

I am attempting to use JavaScript to generate a div with an image on the left and text that can dynamically switch on the right side. What I envision is something like this: [IMAGE] "text" Currently, my attempt has resulted in the text showing ...

The ng-show and ng-hide directives are not working as expected, and there are no error

I'm currently working on a Todo App using AngularJS 1.x (version 1.6), but I'm having issues with ng-show and ng-hide functionality. The aim is to have a text box appear in the todo section when the edit button is clicked to modify existing todos ...

The functionality of Highcharts-more.js is not functioning properly within a project set up using vue-cli

Recently, I have been working on a vue-cli project and attempting to create a polar chart similar to the one shown here: https://www.highcharts.com/demo/polar-spider To achieve this, I needed to install and import the highcharts and highchart-more librari ...

Automatically update Dropdown options with value and text through an ajax json request

I am working on dynamically populating a dropdown list with text and values fetched using an ajax call to retrieve a JSONObject. While my current code successfully populates the dropdown, I need the value to be different from the text as I intend to store ...

How can I add a string before a hashtag(#) in AngularJS URLs?

Can we add a prefix to the # symbol in angular.js URLs? For instance: let's say we have a site: http://example.com/ then when I click on the CSharp page, it redirects to http://example.com/#/csharp when I click on the AngularJS page, it redi ...

Unable to navigate to the frame within the Salesforce Lightning interface

Attached below is the screenshot and code that I have used: driver.switchTo().frame(driver.findElement(By.xpath("//iframe[contains(@title,'Deploy Data Set')]"))); <div class="slds-template_iframe slds-card" force-aloha-page_aloha-page=""> ...

The compatibility between Vue-masonry plugin and Vuetify seems to be problematic

While trying to integrate a masonry grid using the vue-masonry plugin in my Nuxt project with Vuetify, I encountered an issue. It seems like vue-masonry does not work well with Vuetify. I included the vue-masonry plugin (vue-masonry.js) in my Nuxt proje ...

Strategies for limiting a table row in JavaScript or jQuery without utilizing the style tag or class attribute for that specific row

I am looking for a way to limit the display of records in a table. Currently, I can restrict the table rows using the style property, but this causes UI issues such as missing mouse-over effects for the entire row. I need to ensure that mouse-over functi ...

An effective way to mimic an un-exported (private) function within a user module using Jest

In my code, I have a function that handles API requests called "private" and several other functions that initiate specific requests with configuration objects. For example, in the requestUploadStatementFile file. I want to test these public functions, bu ...

What action is initiated when the save button is clicked in ckEditor?

Incorporating a ckeditor editor into my asp.net application has been successful. At this point, I am looking to identify the event that is fired by ckeditor when the save button in the toolbar is clicked. Has anyone come across this information? ...

Is there a way to dynamically register an external component in Vue3 without altering the main project?

In my current project, known as "ProjectMain," I am also working on another project that will act as an extension to ProjectMain - let's call it "MyComponent." My intention is to create MyComponent as a standalone library. My main question is: can I ...

What is the best method for incorporating meta data, titles, and other information at dynamic pages using Node.js and Express?

I am currently exploring methods to efficiently pass data to the html head of my project. I require a custom title, meta description, and other elements for each page within my website. Upon initial thought, one method that comes to mind is passing the da ...

The git clone operation encounters a problem with the error message: unable to connect, connection refused on localhost port 80

Currently for my project, I'm utilizing isomorphic-git. However, when I try to implement the git.clone function, I encounter the error message Error: connect ECONNREFUSED 127.0.0.1:80. To provide an example of what I am attempting to achieve: import ...

Unable to Retrieve JSON Output

PHP Code: $contents = ''; $dataarray = file('/location/'.$_GET['playlist'].''); //Loading file data into array $finallist = ''; //Extract Track Info foreach ($dataarray as $line_num => $line) //Loopin ...