Aún no tienes acceso a esta clase

Crea una cuenta y continúa viendo este curso

Ciclos de vida de un componente: Composition API

35/37
Recursos

Aportes 11

Preguntas 1

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad? Crea una cuenta o inicia sesión.

Reto realizado con Composition API:

Se agrega un Input para buscar con una directiva v-model:

        <div class="product-search">
          <input
            type="text"
            placeholder="Buscar producto..."
            v-model="filtro"
          />
        </div>

dentro de setup() se declara el filtro:

const filtro = ref("");

Se utiliza una propiedad computada:

          filteredProducts = computed(() => {
            if (filtro.value != "") {
              return products.value.filter((product) =>
                product.name.toUpperCase().includes(filtro.value.toUpperCase())
              );
            }
            return products.value;
          });

y en v-for del componente **product **se reemplaza la propidad **products **por **filteredProducts **:

        <product
          v-for="product in filteredProducts"
          :key="product.name"
          :product="product"
          @sendtocart="addToCart($event)"
        ></product>

Al final se agrega al return del setup() **filtro ** y filteredProducts:

          return {
            ...toRefs(cartState),
            products,
            filtro,
            addToCart,
            filteredProducts,
          };

👌

Reto listo, no sé muy bien en dónde se usaría la computed, ya que desde mi punto de vista no hace falta, pero yo la use para trackear cuando el valor de products cambie y en lugar de usar a products dentro del ```forestoy usando la computedallProducts``:
.
Primero este es mi input que ejecuta la búsqueda cuando el usuario presiona enter:

<div class="input-container">
	<input type="text" v-model="search" @keypress.enter="searchProducts">
</div>

Y a products lo sustituí por la computed:

<product v-for="product in allProducts" :key="product.name" :product="product" @sendtocart="addToCart($event)"></product>

A data() le agregué una propiedad search que contendrá la búsqueda del usuario:

data() {
    return {
        products: [],
        cartOpen: true,
        search: "",
        // total: 0,
        cart: []
    }
},

No supe como hacer el filtro desde el API, así que hago el filtro desde JavaScript cuando se presiona enter y cambio la lista de products:

searchProducts() {
    fetch("https://my-json-server.typicode.com/iosamuel/demo/products")
    .then(res => res.json())
    .then(data => {

        this.products = data.filter(
            result => this.search == "" || result.name.toLowerCase() == this.search.toLowerCase()
        );

    });
}

Y simplemente la computed está pendiente por cuando products cambia:

allProducts() {
    return this.products;
}

También le agregué un poco de estilos y lo hice con el Compositio API, pero eso está en mi repositorio jajaja 👀:
.
https://github.com/RetaxMaster/vue3-platzi-commerce/tree/cc4652a233ebe89c6c8375279a4cf3f1445e8825

En composition API, la función setup, reemplaza las funciones de beforeCreated, created. Las funciones del ciclo de vida que serán utilizadas, deben ser llamadas dentro de composition API para poderlas utilizar.

usando composition API:
en el HTML

// Para el filtro
<input type="text" placeholder="Ingrese texto a filtrar" v-model="search" />
// Para mostrar los productos
<main>
        <product
          v-for="product in filteredProducts"
          :key="product.name"
          :product="product"
          @sendtocart="addToCart($event)"
        ></product>
      </main>

Agregar al setup()

const filterState = reactive({
  search: '',
  filteredProducts: computed(() => {
    if (filterState.search === '') {
      return products.value;
    } else {
      return products.value.filter((product) => {
        return product.name.toLowerCase().includes(filterState.search);
      });
    }
  })
});```
Y luego exportarlo:

…toRefs(filterState),

Quise hacerlo con el @keyup.enter pero el computed no se actualizaba ya que no estaba actualizando el array principal de products, y si mutaba ese array luego si se borraba el filtro de búsqueda tenía que mostrar todo el array original, por eso mejor no tocar el array principal y sólo mostrar lo que vas filtrando, y el computed funciona ya que se está observando el search del filterState.

con Compasition API
El input, lo deje con v-model pero no se si la forma correcta es :value

<input v-model="searchValue" type="text" placeholder="Escribe el producto">

La computada, se cambia la referencia de los productos a que sea la de los filtrados en el for.

const filteredProduct = computed(() => {
            if (!searchValue.value || searchValue.value.length < 4)  return products.value
            return products.value.filter((product) => (product.name.toLowerCase()).includes(searchValue.value.toLowerCase()))
          })

y se agregaron las nueva referencia y la computada al setup.

return {
            ...toRefs(cartState),

            searchValue,
            
            addToCart,

            filteredProduct,
          };

estuvo algo complicado el reto pero lo logre

<product v-if="filter"
              v-for="product in filteredProduct"
              :key="product.id"
              :product="product"
              @sendtocart="addToCart($event)"
              ></product>
     <product v-else
              v-for="product in products"
              :key="product.name"
              :product="product"
              @sendtocart="addToCart($event)"
              ></product>

primero condicione la renderización del item, si hay un producto dentro del arreglo de filteredProduct entonces se rederiza ese bloque, si no entonces se renderiza la lista completa.

   const filter = ref(false);
      const filteredProduct = ref([]);
      const search = ref('');

      const searchItem = computed(()=>{
        if(search.value === ''){
          return filter.value = false;
        }else{
          filter.value = true;
          return filteredProduct.value = products.value.filter(product => product.name.toLowerCase().includes(search.value.toLowerCase()));
        }})
     

este código primero conecta “search” a un input con v-model, de esa forma sabermos que esta colocando el usuario, despues recorre el nombre de los elementos en products, y si alguno incluye el valor de search entonces se guarda en filteredProduct y filter se vuelve true, si lo que hay es un string vacio, entonces filter vuelve false, asi condicione la renderizacion

Me encanta todas las soluciones, pero como recién comienzo con vue, para options API lo hice así:

  • Template
    <section>
      <input type="search" id="site-search" name="query" v-model="word" placeholder="Ingresar Producto"> 
      <button @click="search()">Buscar <img src="./images/search-icon.svg" alt="icono de buscar" height="12"/></button>
    </section>

<Product v-for="product in filterProducts" :key="product.name" :product="product" @sendtocart="addToCar($event)"/>
  • data
	word: "",

        query: ""
  • methods
	search(){
          this.query = this.word;
        }
  • computed
	filterProducts(){
          if(this.query != "") {
            return this.products.filter(prod => prod.name.toLowerCase().includes(this.query.toLowerCase()));
            // return this.products.filter(prod => prod.name.toLowerCase().includes(this.query.toLowerCase()) ? prod : false);
          }
          return this.products;
        }

La verdad no entiendo porque el profesor recomienda usar una computed. No se como la computed tendria cabida en el reto, yo lo hice con una function normal, v-model, y capturando el evento.

reto cumplido 😄

ahora recorro productsFiltered

<input type="text" placeholder="buscar..." v-model="filter" />

const filter = ref("");

        const productsFiltered = computed(() => {
          if(!filter.value == ""){
            return products.value.filter(p => p.name.toLowerCase().includes(filter.value.toLowerCase()))
          }
          return products.value;
        })

f

Mi solución
Buscador

<input type="text" v-model="search" placeholder="Ingresar Producto">

Listado

<product v-for="product in productFiltrado" :key="product.name" :product="product" @send-product="addToCart($event)"></product>

Computed

 productFiltrado() {
               if(this.search!=''){
                return this.products.filter(product=>product.name.toUpperCase().includes(this.search.toUpperCase()));
              }
              return this.products;
          }