# Storage

# Obtener Imagen

Antes de comenzar voy a cambiar copiar y pegar el archivo Home.vue a About.vue

  • Solo tenemos que modificar el nombre de en exportar
export default {
  name: 'About',

En Home.vue pegaremos v-for del componente Cards de Bootstrap y el método de obtenerDatos de Firestore.

TEMPLATE CARDS

<template>
    <div>
        <Navbar/>
        <div class="container my-5">
            <div class="row row-cols-1 row-cols-md-3 g-4">
                <div class="col" v-for="(item, index) in usuarios" :key="index">
                    <div class="card">
                    <img :src= "item.foto" class="card-img-top">
                    <div class="card-body">
                        <h5 class="card-title"> {{item.nombre}}</h5>
                        <p class="card-text"> {{item.correo}}</p>
                    </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</template>

SCRIPT obtenerDatos / getDocs

<script>
import Navbar from '../components/Navbar.vue'
import { collection, getDocs } from 'firebase/firestore/lite';
import { db } from "../main";
export default {
    name: 'Home',
    components: { 
      Navbar,   
    },
    data() {
        return {
          usuarios: [],
          usuario: {
            nombre: '',
            correo: '',
            foto: ''
          }
        }
    },
    methods:{
  // GET
    async obtenerDatos () { 
      const querySnapshot = await getDocs(collection(db, "usuarios"));
        querySnapshot.forEach((doc) => {
        let usuario = doc.data()
        usuario.id = doc.id
        this.usuarios.push(usuario)
        console.log(usuario)
      });
    }
    },
    mounted() {
        this.obtenerDatos();
    },
}
</script>

# Template Obtener Imagen

En la parte de template añadimos un input type="file" que nos permite buscar un archivo a través del finder antes del botón Guardar.

<div class="input-group my-3">
    <input type="file" @change="buscarImagen($event)">
</div>

Si queremos previsualizar la imagen utilizamos el dato datoImagen, después del botón Guardar.

<div class="mt-4">
    <img :src="datoImagen">
</div>

# Script Obtener Imagen

  • Buscar la imagen y guardarla en una variable file y el contenido datoImagen, y así visualizar el contenido de la imagen. Fíjate que también utilizamos un condicional para verificar que el tipo de archivo sea válido (jpeg, png).

DATA

Añadimos file y datoImagen

data() {
    return {
      file: null,
      datoImagen: null,
}

Obtenemos el archivo y lo guardamos en data, comprobamos el tipo de archivo si es válido y obtenemos la url para poder visualizarla en la página.

FUNCIÓN

 // BUSCAR IMAGEN
buscarImagen(event){
    console.log(event.target.files[0]);
    const tipoArchivo = event.target.files[0].type;
    if(tipoArchivo === 'image/jpeg' || tipoArchivo === 'image/png'){
        this.file = event.target.files[0]
        this.error = null
    }
        else{
        this.error = 'Archivo no válido'
        this.file = null
        return 
        }
        const reader = new FileReader();
        reader.readAsDataURL(this.file);
        reader.onload = (e) => {
        this.datoImagen = e.target.result
        }
},

# Botón Editar / obtenerDatoID

# Template botón editar

Con obtener dato por id podemos rellenar los campos del formulario para editar y actualizar los datos.

Añadimos a la tabla la columna Editar después de Correo

<th scope="col">Editar</th>

Añadimos en la fila el botón Editar antes del botón Eliminar

<td>
    <button @click.prevent="obtenerDatoID( item.id );this.editar = !this.editar;" 
    class="btn btn-primary">Editar
    </button>
</td>

# Script Botón Editar

DATA

data() {
    return {
      editar: false,
    }
}

MÉTODO

Importa getDoc

Método obtenerDatoID getDoc (opens new window)

import { doc, getDoc } from "firebase/firestore";
// GET BY ID / OBTENER POR ID
async obtenerDatoID (id){
  const docRef = doc(db, "usuarios", id);
  const docSnap = await getDoc(docRef);
      if (docSnap.exists()) {
        this.usuario = docSnap.data()
        this.usuario.id = docSnap.id
        } 
        else {
        console.log("¡No existe el documento!");
        }
},

# Storage / subir imagen y guardar el enlace

  • Subir la imagen a storage y guardar la dirección/enlace en una variable.

# Template botón Guardar / Editar

Añadir botón Actualizar y mostrar / ocultar los botones editar: false

<!-- Mostrar/Ocultar Botones Guardar-Editar -->
<div class="mt-3">  
  <button v-show="this.editar === true" 
    @click.prevent="actualizarDato(id)" 
    class="btn btn-primary">
    Actualizar
  </button>
  <button v-show="this.editar === false" 
    @click.prevent="agregarDato()" 
    class="btn btn-primary">
    Guardar
  </button>

# Importar Storage en main.js

import firebase from 'firebase/compat/app';
import 'firebase/compat/storage';

// Initialize Firebase
firebase.initializeApp(firebaseConfig)
var storageRef = firebase.storage().ref();

export { db, storageRef };

# Script / subirImagenDatos / actualizarImagenDatos

MÉTODO subirImagenDatos

Importa Storage

import { updateDoc } from 'firebase/firestore/lite';
import { db, storageRef} from "../main";

// SUBIR IMAGEN STORAGE
async agregarDato(){
  try {
    await storageRef.child('imagenes').child(this.file.name).put(this.file)
    const urlDescarga = await storageRef.child('imagenes').child(this.file.name).getDownloadURL()
    await addDoc(collection(db, "usuarios"), {
        nombre: this.usuario.nombre,
        correo: this.usuario.correo,
        foto: urlDescarga
      })
      this.error = 'Imagen subida con éxito'
      this.file = null
  } 
    catch (error) {
      console.log(error);
    } 
    finally {
      router.push('/')
    }
},

MÉTODO actualizarDatos

Con barra de progreso

<div class="progress">
  <div class="progress-bar" role="progressbar" :style="{width: progress + '%'}" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100"></div>
</div>
  data() {
    return {    
      progress: 0,
import firebase from 'firebase/compat/app';
// MÉTODO actualizarDato
async actualizarDato(){
  try {
    var uploadTask = storageRef.child('imagenes').child(this.file.name).put(this.file)
    uploadTask.on('state_changed', function (snapshot){
    this.progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
    console.log('Upload is ' + self.progress + '% done');
    switch (snapshot.state) {
      case firebase.storage.TaskState.PAUSED:
        console.log('Upload is paused');
        break;
      case firebase.storage.TaskState.RUNNING:
        console.log('Upload is running');   
        break;
     
      }
    
    }.bind(this), function(error) {
    }, function() {
      uploadTask.snapshot.ref.getDownloadURL().then(function(downloadURL) {
        console.log('File available at', downloadURL);
      });
    });
    const urlDescarga = await storageRef.child('imagenes').child(this.file.name).getDownloadURL()
    const elemento = doc(db, "usuarios", this.usuario.id )
    await updateDoc(elemento, {
        nombre: this.usuario.nombre,
        correo: this.usuario.correo,
        foto: urlDescarga
      })
      this.error = 'Imagen subida con éxito'
      this.file = null;
  } 
    catch (error) {
      console.log(error);
    } 
    finally {
      router.go('/');
    }
},