Top method for organizing Vue JS elements

I am looking to integrate a search feature on my website using Vue 2, where the search functionality will be applied to components generated from a JSON file upon page load.

The JSON file contains the keywords I want to utilize for the search - specifically, the 'Name' and 'Tag' properties. (Just to clarify, the components are referred to as pools.) While considering using a computed property for this purpose, I am a bit unsure about how to proceed.

Here's what I have so far for the search bar component:

<template>
    <div class="search">
        <input type="text" v-model="search" placeholder="Search for pools">
    </div>
</template>

<script>
    export default {
        mounted() {
            console.log('Search Box Mounted')
        },
        data(){
            return{
                search:''
            }
        },
        computed: {
            filteredPools: function(){

            }
        }
    }
</script>

This code snippet is responsible for displaying the list of pools:

<template>
    <div class="container pool" v-bind:id="'poolalgo-' + algo">
        <h2 class="type text-center">{{algo}}</h2>
        <hr class="poolruler" />
        <div class="row">
            <pool v-for="pool in pools" :pool="pool" :key="pool.tag">
            </pool>
        </div>
    </div>
</template>

<script>
    export default {
        mounted() {
            console.log('PoolList mounted.')
        },
        props:['pools','algo']
    }
</script>

And here's the component that displays the individual pool details:

<template>

    <div class="col-xl-3 centered icon">
        <a v-bind:href="pool.url" target="_blank">
            <img class="logo img rounded-circle" v-bind:src="pool.image" height="120px" width="120px">
        </a>
        <h4>{{pool.name}}</h4>
        <p>Symbol/Tag: {{pool.tag}}</p>
        <p>Block Time: {{pool.blocktime}}</p>
        //ect
        <br>
    </div>
</template>

<script>
    export default {
        props: ['pool'],

        mounted() {
            console.log('Pool mounted.')
        },
    }
</script>

Lastly, this is how the pool list is rendered on the main page:

<pool-list v-for="(pools,algo) in poolConfig" :pools="pools" :algo="algo"></pool-list>

Answer №1

Try running this code snippet on a full page to see if it meets your requirements. It consists of a single component, but you can customize it by following the comments provided (the search input component + the list component).

Search Component

<template>
  <div class="search">
      <input type="text" @input="emitSearch" placeholder="Search for pools">
  </div>
</template>
<script>
export default {
    methods: {
    emitSearch (ev) {
      this.$root.$emit('app:search', ev.target.value)
    }
  }
}
</script>

List Component

<template>
 <div class="col-xl-3 centered icon" v-for="pool in list" :key="pool.name">
    <a v-bind:href="pool.image" target="_blank">
        <img class="logo img rounded-circle" v-bind:src="pool.image" height="120px" width="120px">
    </a>
    <h4>{{pool.name}}</h4>
    <p>Symbol/Tag: {{pool.tag}}</p>
    <p>Block Time: {{pool.blocktime}}</p>
    //ect
    <br>
  </div>
</template>
<script>
export default {
  data () {
    return {
      search: '',
      orderBy: 'name', // sort by property
      pools: [ // raw list
        {name: 'Yellow pool', tag: 'yellow', blocktime: 123, image: 'https://placehold.it/120'},
        {name: 'Blue pool', tag: 'blue', blocktime: 123, image: 'https://placehold.it/120'},
        {name: 'Purple pool', tag: 'purple', blocktime: 123, image: 'https://placehold.it/120'},
        {name: 'Black pool', tag: 'black', blocktime: 123, image: 'https://placehold.it/120'},
      ]
    }
  },
  computed: {
    list () {
      return this.pools.filter(p => { // filter based on this.search
        return p.name.toLowerCase()
          .indexOf(this.search.toLowerCase()) > -1
      })
        .sort((a, b) => { // sort by this.orderBy
          const first = a[this.orderBy].toLowerCase()
          const next = b[this.orderBy].toLowerCase()
          if (first > next) {
            return 1
          }
          if (first < next) {
            return -1
          }
          return 0
        })
    }
  },
  created () {
    this.$root.$on('app:search', search => {
      this.search = search
    })
  },
  beforeDestroy () {
    // remove listener
    this.$root.$off('app:search')

  }
}
</script>

Executable Fiddle

new Vue({
  el: '#app',
  data () {
    return {
      search: '',
      orderBy: 'name', // sort by property
      pools: [ // raw list
        {name: 'Yellow pool', tag: 'yellow', blocktime: 123, image: 'https://placehold.it/120'},
        {name: 'Blue pool', tag: 'blue', blocktime: 123, image: 'https://placehold.it/120'},
        {name: 'Purple pool', tag: 'purple', blocktime: 123, image: 'https://placehold.it/120'},
        {name: 'Black pool', tag: 'black', blocktime: 123, image: 'https://placehold.it/120'},
      ]
    }
  },
  computed: { // list component computed properties
    list () {
      return this.pools.filter(p => { // filter based on this.search
        return p.name.toLowerCase()
          .indexOf(this.search.toLowerCase()) > -1
      })
        .sort((a, b) => { // sort by this.orderBy
          const first = a[this.orderBy].toLowerCase()
          const next = b[this.orderBy].toLowerCase()
          if (first > next) {
            return 1
          }
          if (first < next) {
            return -1
          }
          return 0
        })
    }
  },
  methods: { // search component method
    emitSearch (ev) {
      this.$root.$emit('app:search', ev.target.value)
    }
  },
  created () { // list component lifecycle hook
    this.$root.$on('app:search', search => {
      this.search = search
    })
  },
  beforeDestroy () { // list component lifecycle hook
    // remove listener
    this.$root.$off('app:search')

  }
})
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script>Vue.config.productionTip = false</script>

<div id="app">
  <!-- search component emits 'app:search' event -->
  <div class="search">
    <input type="text" @input="emitSearch" placeholder="Search for pools">
  </div>
  <hr>
  <!-- list component listens 'app:search' event -->
  <div class="col-xl-3 centered icon" v-for="pool in list" :key="pool.name">
    <a v-bind:href="pool.image" target="_blank">
        <img class="logo img rounded-circle" v-bind:src="pool.image" height="120px" width="120px">
    </a>
    <h4>{{pool.name}}</h4>
    <p>Symbol/Tag: {{pool.tag}}</p>
    <p>Block Time: {{pool.blocktime}}</p>
    //ect
    <br>
  </div>
</div>

Answer №2

If you want to filter pools using the search function, follow these steps:

  1. Add a prop to your pools component to accept the filter-text from the parent component.

  2. Create a computed property for your pools component, then use the Array.filter method to apply your custom filter.

  3. Replace

    <pool v-for="pool in pools">
    with:

<template>
    <div class="container pool" v-bind:id="'poolalgo-' + algo">
        <h2 class="type text-center">{{algo}}</h2>
        <hr class="poolruler" />
        <div class="row">
            <pool v-for="pool in filteredPools" :pool="pool" :key="pool.tag">
            </pool>
        </div>
    </div>
</template>

<script>
    export default {
        mounted() {
            console.log('PoolList mounted.')
        },
        props:['pools','algo', 'filterText'],
        computed: {
            filteredPools: function(){ //filter out tag|name includes this.search
              return this.pools.filter((item)=>{
                return this.filterText in item.tag or this.filterText in item.name
              })
            }
        }
    }
</script>

Lastly, in your parent component, use

<pools v-bind:filter-text="search">

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

Unable to render chart using angularjs-nvd3-directives

After developing a basic Angular - nvd3 project, I decided to utilize liveData.example from the angularjs-nvd3-directives Library on Github. To tailor it for my needs, I made enhancements to integrate with my REST API. Here is the REST API endpoint: http ...

Validation scheme for the <speak> element

When using validators in an angular formarray for input fields, I encountered a challenge with the regex to check the <speak> tag. https://i.sstatic.net/ogFA3.png The content provided was considered valid. https://i.sstatic.net/ar5FJ.png An error ...

What happens when 'grid' property is undefined in modal?

I encountered an issue with my modal where I wanted to display pre-selected rows, but kept getting a 'cannot read 'grid' of undefined' error. The UI Grids are defined within the modal, and I have declared two Grid APIs with different na ...

Difficulty setting up virtual host for a Vue.js single-page application

Looking for assistance with hosting a single page Vuejs application that utilizes vue router on an Apache2 virtual host? See the code snippet below: <VirtualHost *:80> ServerAdmin <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data ...

ShadowBox not displaying Vimeo videos

I can't figure out why my Vimeo videos are not appearing in a Shadowbox. I have followed the steps I know to be the simplest, which involve copying the example directly from the github page and then updating the shadowbox paths to match the locations ...

Deleting a row from a table in Angular when a form is submitted

I am new to using Angular and I have been attempting to remove certain elements from a table upon submission. <tr ng-repeat="val in values "> <td ng-bind="$index"></td> <td ng-bind="val.rec">ED1500322</td> <td& ...

A comprehensive guide to leveraging synchronous execution of setTimeout in JavaScript

Can the desired output shown below be obtained using setTimout? If it is possible, please provide your insight: console.log("1st"); setTimeout(() => { console.log("2nd"); },0); console.log("3rd"); The expected output should be: 1st 2nd 3rd ...

Learn the ins and outs of utilizing *ngIf in index.html within Angular 8

Can anyone explain how I can implement the *ngIf condition in index.html for Angular2+? I need to dynamically load tags based on a condition using the *ngIf directive, and I'm trying to retrieve the value from local storage. Below is my code snippet b ...

Develop a custom function in Typescript that resolves and returns the values from multiple other functions

Is there a simple solution to my dilemma? I'm attempting to develop a function that gathers the outcomes of multiple functions into an array. TypeScript seems to be raising objections. How can I correctly modify this function? const func = (x:number, ...

How can you retrieve a value from a JavaScript closure function?

I'm struggling with getting a value from a closure function in Javascript. In my initial attempt, I placed the return statement inside the inner function, but it was not effective. Then, I tried moving the return statement to the outer function, howev ...

Discovering identical elements within a list in Python through index-based location scanning

Check out this JavaScript code that can determine whether there are any duplicate elements in an array. function findDuplicates(arr) { let seen = []; for (let i = 0; i < arr.length; i++) { if(seen[arr[i]] === 1) { ...

Display the footer once the user has reached the end of the page by scrolling

Below is the footer code I am working with. <div class="row"> <div class="col-md-12"> <div> this section always remains at the bottom </div> </div> <div class="col-md-12"> <div> only v ...

Using canvas to smoothly transition an object from one point to another along a curved path

As a beginner in working with canvas, I am facing a challenge of moving an object from one fixed coordinate to another using an arc. While referring to the code example of a solar system on https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutori ...

If you encounter a file type that requires special handling, make sure to have a suitable loader configured for it. In the case of VUEJS 2, no loaders

I am facing an issue while trying to import appsync settings for my project Here is the error message: error in ./node_modules/@aws-sdk/signature-v4/dist-es/getCanonicalHeaders.js Module parse failed: Unexpected token (10:30) You may need an appropriat ...

What is the best approach for dynamically accessing or rendering Children within an Angular Component?

I am facing an issue with reusing a component called wrapper with different child components. I found some helpful resources such as this SO question and this article. However, these only address cases where the child component is known in advance. In my s ...

What is the best method for implementing ajax in Codeigniter?

Exploring the best approach to writing ajax in CodeIgniter. Is it acceptable to write ajax in views, or is it better to create a new directory named assets at the root of the CodeIgniter project folder and relocate all scripts to a js folder within our a ...

How can an Angular directive dynamically update template fields with the latest model values from the controller?

I am currently working with a <superhero> directive that includes two other directives: web-buttons, which handles form validation and posting the updated ngModel value to the respective controller. fieldMap, which generates dynamic fields based on ...

Difficulty in showcasing error on the website with JavaScript

I have recently developed a webpage that includes several input boxes and a submit button within a form as shown below: <form action="" method="post" name="password"> Upon clicking the submit button, a JavaScript function is triggered to validate i ...

How can I use an input array to filter data in mongodb?

When receiving input from the front-end, it looks like this: { "options":[ { "optionId":"5ebbe0f56b197f36fc472168" }, { "optionId":"5ebbe1aa6b197f36fc47216e" } ] } The goal is to filter the data in a way that ...

Dragend event for images does not trigger in webkit when using TinyMCE

When using the TinyMCE editor, I tried binding the dragend event on images with the following code: _imagePlugin.editor.dom.bind(_imagePlugin.editor.dom.select('img'), 'dragend', function(){console.log('aaaa');}); Oddly enou ...