You don't have access to this class

Keep learning! Join and start boosting your career

Aprovecha el precio especial y haz tu profesión a prueba de IA

Antes: $249

Currency
$209
Suscríbete

Termina en:

0 Días
10 Hrs
14 Min
15 Seg

Mejorar proyecto: filtros y ordenar

36/38
Resources

How to optimize the cryptocurrency filter and add functionality?

Modern web applications require a smooth and efficient user experience. Part of this includes offering real-time filtering and sorting capabilities that improve user interaction with the data. In this guide, we'll show you how to implement a search filter and sort a list of cryptocurrencies using Vue.js. We will first explore how to build these functionalities and then how to integrate them into our platform.

How to implement a real-time search filter?

To provide a real-time filtering experience, we will use an HTML input that dynamically binds to our cryptocurrency list. This input will allow users to type any text and filter the list according to the cryptocurrency token or name.

  1. Creating an input to filter:

    • Add an input element in the table header in your Vue component.
    • Use v-model to bind the input value to a property called filter.
    <template> <input v-model="filter" placeholder="Filter..." /></template>.
  2. Filter function definition:

    • In the component's data object, initializes the empty filter property.
    • Create a computedproperty that uses the JavaScript filter() function to filter the list of cryptocurrencies based on the input value.
    data() { return { filter: '' };},computed: { filteredCryptos() { if (!this.filter) return this.coins; return this.coins.filter(coin => { return coin.symbol.toLowerCase().includes(this.filter.toLowerCase()) || coin.name.toLowerCase().includes(this.filter.toLowerCase()); }); } }}}

How to sort the list of cryptocurrencies by ranking?

An essential skill to improve the UX is to allow users to sort the list of cryptocurrencies by various criteria, such as ascending or descending ranking. We will implement this using JavaScript's sort() function.

  1. Add support for sorting:

    • Introduce a new sortOrder property on the data object to define the current order (ascending or descending).
    data() { return { sortOrder: 1 // 1 for ascending, -1 for descending };}
  2. Modifying the computed property:

    • Extend the computed property to sort the list of cryptocurrencies after applying the filter.
    computed: { sortedAndFilteredCryptos() { let filtered = this.filteredCryptos; return filtered.sort((a, b) => (a.rank - b.rank) * this.sortOrder); } }}
  3. Visual and functional configuration of the order change:

    • Make sure to provide a user interface to change the order by clicking on the column header.
    <th@click="toggleSortOrder" class="sortable"> Ranking</th>
    methods: { toggleSortOrder() { this.sortOrder = this.sortOrder === 1 ?-1 : 1; }}

How to ensure that the functionality is intuitive and enjoyable?

  • Visual cues: use CSS classes to underline or change the cursor when hovering over clickable headings.
  • Sorting in both conditions: Make sure the list can be sorted regardless of whether there is a filter applied or not. Eliminate unnecessary conditions that prevent sorting without a filter.
  • Testing in different cases: Test the functionality with various inputs and make sure that all possible scenarios are handled correctly.

With these simple but effective additions, your application will not only look more professional but will also provide a more intuitive and efficient experience for users. Keep honing your skills and enjoy creating enriching experiences!

Contributions 23

Questions 4

Sort by:

Want to see more contributions, questions and answers from the community?

HTML:

<input
            class="bg-gray-100 focus:outline-none border-b border-gray-400 py-2 px-4 block w-full appearance-none leading-normal"
            id="filter"
            placeholder="Buscar..."
            type="text"
            v-model="filter"
          />

Podria evitar el “altOrder” retornando en caso de no cumplir la condicion de a.rank > b.rank, el opuesto de sortOrder

.sort((a, b) => {
          if (parseInt(a.rank) > parseInt(b.rank)) {
            return this.sortOrder;
          }

          return this.sortOrder * -1;
        });

No me funcionaba el filtro hasta que agregue un return dentro del filter

return this.assets.filter((asset) => {
        return asset.symbol.toLowerCase().includes(this.filter.toLowerCase()) ||
          asset.name.toLowerCase().includes(this.filter.toLowerCase());
});

Me encanta lo fácil que lo hace ver Vue, yo me hubiese tomado buen rato haciendo ese filtro y el ordenamiento con JavaScript puro xD

Esto ya es meramente Js 😃 toca darle duro a eso 😃

de donde copia el html para los filtros porque no lo colocan en las notas o archivos ???

Para que no se confundan al pronunciar “symbol”:
how pronounce symbol

Repasamos sobre el uso de propiedades computadas y haciendo uso de los metodos propios de javascript logramos mejorar la aplicacion de forma facil y muy profesional.

Puliendo detalles

Otra forma de cambiar el valor de sortOrder de 1 a -1, y viceversa, es multiplicando su valor por -1:

changeSortOrder() {
      this.sortOrder = this.sortOrder * -1
    }

Si el valor es -1, al multiplicarlo por -1, dara como resultado 1 positivo. Y si el valor es 1, al multiplicarlo por -1, dara como resultado -1.

<template>
  <table>
    <thead>
      <tr class="bg-gray-100 border-b-2 border-gray-400">
        <th></th>
        <th :class="{up: this.sortOrder === 1, down: this.sortOrder === -1}">
          <span 
          class="underline cursor-pointer"
          @click="changeSortOrder">Ranking</span>
        </th>
        <th>Nombre</th>
        <th>Precio</th>
        <th>Cap. de Mercado</th>
        <th>Variación 24hs</th>
        <td class="hidden sm:block">
          <input
            class="bg-gray-100 focus:outline-none border-b border-gray-400 py-2 px-4 block w-full appearance-none leading-normal"
            id="filter"
            placeholder="Buscar..."
            type="text"
            v-model="filter"
          />
        </td>
      </tr>
    </thead>
    <tbody>
      <tr
        v-for="a in filteredAssets"
        :key="a.id"
        class="border-b border-gray-200 hover:bg-gray-100 hover:bg-orange-100"
      >
        <td>
          <img
            class="w-6 h-6"
            :src="`https://static.coincap.io/assets/icons/${a.symbol.toLowerCase()}@2x.png`"
            :alt="a.name"
          />
        </td>
        <td>
          <b># {{ a.rank }}</b>
        </td>
        <td>
          <router-link 
          class="hover:underline text-green-600"
          :to="{name: 'coin-detail', params: { id: a.id }}">
            {{ a.name }}
          </router-link>
          <small class="ml-1 text-gray-600">{{a.symbol}}</small>
        </td>
        <td>{{ dollarFilter(a.priceUsd) }}</td>
        <td>{{ dollarFilter(a.marketCapUsd) }}</td>
        <td
          :class="
            a.changePercent24Hr.includes('-')
              ? 'text-red-600'
              : 'text-green-600'
          "
        >
          {{ percentFilter(a.changePercent24Hr) }}
        </td>
        <td class="hidden sm:block">
          <px-button @click="goToCoin(a.id)"><span>Detalle</span></px-button>
        </td>
      </tr>
    </tbody>
  </table>
</template>

<script>
import { dollarFilter, percentFilter } from '../filter'
import PxButton from './PxButton.vue';

export default {
  name: 'PxAssetsTable',
  components: { PxButton },

  data(){
    return {
      filter: '',
      sortOrder: 1
    }
  },

  props: {
    assets: {
      type: Array,
      default: () => [],
    },
  },

  computed: {
    filteredAssets(){
      return this.assets.filter(
        a => 
        a.symbol.toLowerCase().includes(this.filter.toLowerCase()) || 
        a.name.toLowerCase().includes(this.filter.toLowerCase())
      )
      .sort((a,b)=>{
        if(parseInt(a.rank) > parseInt(b.rank)){
          return this.sortOrder
        }
        return this.sortOrder * -1;
      })
    }
  },

  methods: {
    goToCoin(id){
      this.$router.push({name: 'coin-detail', params:{id}})
    },

    changeSortOrder(){
      this.sortOrder = this.sortOrder === 1 ? -1 : 1
    }
  },

  setup() {
    return {
      dollarFilter,
      percentFilter,
    }
  },
}
</script>

<style scoped>
.up::before {
  content: '👆';
}

.down::before {
  content: '👇';
}

td {
  padding: 20px 0px;
  font-size: 0.6rem;
  text-align: center;
}

th {
  padding: 5px;
  font-size: 0.6rem;
}

@media (min-width: 640px) {
  td,
  th {
    padding: 20px;
    font-size: 1rem;
  }

  th {
    padding: 12px;
  }
}
</style>

Un breve aporte, en vez de usar condicional, podriamos a ver multiplicado por -1.

this,sortOrder = this,sortOrder * (-1)

Si eres como yo y te gusta entender lo que haces y no entendiste como hace el ordenamiento el profe, esto sirve exactamente igual

filteredAssets() {
      if (this.sortOrder === 1) {
        return this.assets
          .filter(
            (a) =>
              a.symbol.toLowerCase().includes(this.filter.toLowerCase()) ||
              a.name.toLowerCase().includes(this.filter.toLowerCase())
          )
          .sort();
      }
      return this.assets
        .filter(
          (a) =>
            a.symbol.toLowerCase().includes(this.filter.toLowerCase()) ||
            a.name.toLowerCase().includes(this.filter.toLowerCase())
        )
        .reverse();

Cual seria la forma de realizar el filtro utilizando watch sobre la propiedad de filter? de haber una forma realizando watch, cual es mejor, con computed properties o con watch??

Forma sin CSS 😃 y con Vue

<span @click=“this.changeSortOrde” :style="{cursor:‘pointer’}"> {{ this.sortOrder == 1 ? ‘☝’:‘👇’}} Ranking</span>

<h1>Aporte - Búsqueda por regexp</h1>

Les comparto esta pequeña mejora en el filtro, puede no notarse a simple vista pero esta solución es más rápida que utilizar la función .includes.

<h1>Código</h1>
filteredAssets() {
  const normalizedFilter = this.filter.trim();
  if (!normalizedFilter) {
    return this.assets;
  }
  const regexp = new RegExp(normalizedFilter, 'ig');
  return this.assets.filter((x) => regexp.test(x.name) || regexp.test(x.symbol));
},

Ordenar por ranking

Hola, estoy un poco confundido con esta función:

  .sort((a, b) => {
      if (parseInt(a.rank) > parseInt(b.rank)) {
        return sortOrder
      }

      return altOrder
    })

Alguien me puede explicar cómo funciona?
Muchas gracias.

casi!!!

Wuo este curso realmente es genial, entiendo que se debe afianzar algunos conceptos pero eso se debe realizar en la practica pero creo que esta bien diseñado y el profesor es genial

filteredAssets(){
      const altOrder = this.sortOrder === 1 ? -1 : 1
      return this.assets.filter( a => 
      a.symbol.toLowerCase().includes(this.filter.toLowerCase()) ||
      a.name.toLowerCase().includes(this.filter.toLowerCase())
      ).sort((a, b) => {
        if(parseInt(a.rank) > b.rank) return this.sortOrder
        return altOrder;
      })
    }
  }

👌

Para en tengan en cuenta, que se escribe “includes” no “include”, se escribe en plural