CRUD con vue.js

Siguiendo con el ejemplo que empezamos a trabajar en el último post dedicado al acceso de datos vía API con vue.js, vamos a implementar ahora los metodos necesarios para poder crear, actualizar, borrar y ver los datos guardados (CRUD).

En realidad, uno de los elementos del CRUD (Read), ya lo tenemos resuelto en el post anterior

ya que fuimos capaces de acceder a los datos y mostrarlos en pantalla al usuario.

Vamos a pasar al resto de acciones que vamos a tener disponibles. Iremos viendo en cada caso, la configuración necesaria en el fichero api_movies.js (revisar el post anterior), el código correspondiente a la acción en la vista Movies.vue y el codigo html que hemos de incluir en el template.

En todos los casos, el propio código está bastante documentado, con lo que no serán necesarias demasiadas explicaciones. Vamos a por ello.

Editar y borrar

Lo primero que haremos será crear dos botones en una nueva columna en la tabla donde mostramos los datos. Estos botones nos permitirán lanzar los eventos de edición y borrado.

Veamos el metodo en la llamada a la API

// LLAMADAs A LA API DE LAS PELÍCULAS
// api_moves.js

//....... codigo anterior......

// Modificar una película
async function updateMovie(movieId, updatedMovieData) {
  try {
    const token = getAccessToken(); // Obtiene el token de acceso

    if (token) {
      const response = await axios.put(`${API_MOVIES}${movieId}/`, updatedMovieData, {
        headers: {
          Authorization: 'Bearer ' + token,
        },
      });
      return response.data;
    } else {
      console.error('Token de acceso no disponible');
      return null;
    }
  } catch (error) {
    console.error('Error al modificar detalles de la película:', error);
    return null;
  }
}

/ Exporta todas las funciones
export { getMovies, getMovieById, updateMovie}

En Movies.vue, preparamos el template para mostrar un formulario de edicion:

// Movies.vue

<!-- Formulario para la edición de las películas-->
        <div v-if="selectedMovieIndex !== null">
        <div class="edit-form">
          <h3 class="mb-4">Editando Película</h3>
          <form @submit.prevent="saveEditedMovie">
            <div class="row">
              <div class="col">
                <input type="text" class="form-control" v-model="movies[selectedMovieIndex].title_movie" :placeholder="'Título'">
              </div>
              <div class="col">
                <input type="text" class="form-control" v-model="movies[selectedMovieIndex].gender_movie" :placeholder="'Género'">
              </div>
              <div class="col">
                <input type="text" class="form-control" v-model="movies[selectedMovieIndex].year_movie" :placeholder="'Año'">
              </div>
              <div class="col">
                <input type="text" class="form-control" v-model="movies[selectedMovieIndex].director_movie" :placeholder="'Director'">
              </div>
              <div class="col">
                <button type="submit" class="btn btn-primary mb-2" @click="saveEditedMovie">Guardar</button>
              </div>
            </div>
          </form>
        </div>
        </div>
          <!-- Formulario para la edición de las películas-->

Y el método correspondiente en el apartado script

data() {
    return {
      ....
      selectedMovieIndex: null,
      ....
    };
  },

 // METODO PARA EDITAR PELICULAS
    editMovie(index) {
      this.selectedMovieIndex = index;
    },
    // METODO PARA GUARDAR LAS PELICULAS EDITADAS
    async saveEditedMovie() {
      if (this.selectedMovieIndex !== null) {
        try {
          const movieToEdit = this.movies[this.selectedMovieIndex]; // Obtener la película seleccionada para editar
          const movieId = movieToEdit.id; // Obtener el ID de la película a modificar

          const updatedMovieData = {
            // Actualiza estos campos con los datos del formulario
            title_movie: movieToEdit.title_movie, 
            gender_movie: movieToEdit.gender_movie,
            year_movie: movieToEdit.year_movie,
            director_movie: movieToEdit.director_movie,
          };

          const updatedMovie = await updateMovie(movieId, updatedMovieData);

          if (updatedMovie) {
            // Manejar la película actualizada (si es necesario)
            console.log('Película actualizada:', updatedMovie);
            // Actualizar la lista de películas
            this.movies[this.selectedMovieIndex] = updatedMovie;
            this.successMessage = '¡La película se ha actualizado correctamente!';

            // El mensaje aparece durante 2 segundos
            setTimeout(() => {
              this.successMessage = '';
            }, 2000);

          } else {
            this.errorMessage = 'Error al actualizar la película';
          }
        } catch (error) {
          console.error('Error al guardar la película editada:', error);
          this.errorMessage = 'Error al guardar la película editada';
        } finally {
          this.selectedMovieIndex = null; // Resetear la variable de índice de película seleccionada
        }
      } else {
        this.errorMessage = 'No se ha seleccionado ninguna película para editar';
      }
    },

La reacción a la pulsación al boton de borrado es similar, en cuento a estructura, pero en esta ocasión muestra un alert de petición de confirmación al usuario. Vamos a verlo.

// LLAMADAs A LA API DE LAS PELÍCULAS
// api_moves.js

//....... codigo anterior......

// Eliminar una película por ID
async function deleteMovieById(movieId) {
  console.log("La película a borrar es " + movieId);
  try {
    const token = getAccessToken(); // Obtiene el token de acceso

    if (token) {
      const response = await axios.delete(`${API_MOVIES}${movieId}/`, {
        headers: {
          Authorization: 'Bearer ' + token,
        },
      });
      
      if (response.status === 200) {
        return '¡La película se ha eliminado correctamente!';
      } else {
        return 'Error al eliminar la película';
      }
    } else {
      console.error('Token de acceso no disponible');
      return 'Token de acceso no disponible';
    }
  } catch (error) {
    console.error('Error al eliminar la película:', error);
    return 'Error al eliminar la película';
  }
}

// Exporta todas las funciones
export { getMovies, getMovieById, updateMovie, deleteMovieById };

De vuelta a la vista, creamos el método de respuesta al evento click del boton de borrado

 // METODO PARA BORRAR PELÍCULAS
    async deleteMovie(index) {
      const movieId = this.movies[index].id;

      if (confirm('¿Estás seguro de que quieres borrar esta película?')) {
        try {
          const deleted = await deleteMovieById(movieId);
          console.log(movieId);

          if (deleted) {
            console.log('Película eliminada con éxito');

            // Eliminar la película del array local en Vue
            //this.movies.splice(index, 1);

            this.successMessage = '¡La película se ha eliminado correctamente!';
            // El mensaje aparece durante 2 segundos
            setTimeout(() => {
              this.successMessage = '';
            }, 2000);

            // Después de eliminar, actualiza la lista de películas llamando a la función para obtener películas
            await this.getMoviesAndDetails();
          } 
        } catch (error) {
          this.errorMessage = 'Error al eliminar la película';
        }
      }
    },

De esta manera, el sistema pedirá confirmación al usuario antes de borrar un registro

Creando nueva películas

Para completar los procesos del CRUD, vamos a permitir al usuario crear sus propias películas, llamando a la API y con los correspondientes formularios y métodos en la vista Movies.vue

Siguiendo la estructura anterior vemos la llamada a la API

// LLAMADAs A LA API DE LAS PELÍCULAS
// api_moves.js

//....... codigo anterior......

// Crear una nueva película
async function createMovie(newMovieData) {
  try {
    const token = getAccessToken(); // Obtiene el token de acceso

    if (token) {
      const response = await axios.post(`${API_MOVIES}`, newMovieData, {
        headers: {
          Authorization: 'Bearer ' + token,
        },
      });
      return response.data;
    } else {
      console.error('Token de acceso no disponible');
      return null;
    }
  } catch (error) {
    console.error('Error al crear la película:', error);
    return null;
  }
}

// Exporta todas las funciones
export { getMovies, getMovieById, updateMovie, deleteMovieById, createMovie };

Ahora montamos un boton para llamar a un evento que nos permita crear una película, usando un formulario similar al de edición, visto anteriormente

// Movies.vue

<!-- CODIGO ANTERIOR -->
       <!-- Formulario para la creación de películas -->
        <div v-if="isCreateFormVisible" class="edit-form">
          <h3 class="mb-4">Crear Película</h3>
          <form>
            <div class="row">
              <div class="col">
                <input type="text" class="form-control" v-model="newMovie.title_movie" :placeholder="'Título'">
              </div>
              <div class="col">
                <input type="text" class="form-control" v-model="newMovie.gender_movie" :placeholder="'Género'">
              </div>
              <div class="col">
                <input type="text" class="form-control" v-model="newMovie.year_movie" :placeholder="'Año'">
              </div>
              <div class="col">
                <input type="text" class="form-control" v-model="newMovie.director_movie" :placeholder="'Director'">
              </div>
              <div class="col">
                <button type="submit" class="btn btn-primary mb-2" @click="saveNewMovie">Guardar</button>
              </div>
            </div>
          </form>
        </div>
        <!-- Formulario para la creación de películas -->

<!-- Botón para mostrar el formulario de creación de película -->
<button class="btn btn-primary" @click="showCreateForm">Crear Película</button>

Ahora creamos las variables y métodos necesarios para gestionar la creación de registros


export default {
  data() {
    return {
      ....  
      // Objeto para almacenar los datos de la nueva película
      newMovie: { 
        title_movie: '',
        gender_movie: '',
        year_movie: '',
        director_movie: ''
      },
     ...... 
    };
  },

 // METODO PARA MOSTRAR EL FORMULARIO DE CREACION DE PELICULAS
    showCreateForm() {
      this.isCreateFormVisible = true;
      // Limpiar los campos del nuevo formulario
      this.newMovie = {
        title_movie: '',
        gender_movie: '',
        year_movie: '',
        director_movie: ''
      };
    },

    // METODO PARA GUARDAR UNA NUEVA PELÍCULA
    async saveNewMovie() {
      if (this.newMovie.title_movie && this.newMovie.gender_movie && this.newMovie.year_movie && this.newMovie.director_movie) {
        try {
          const createdMovie = await createMovie(this.newMovie);

          if (createdMovie) {
            // Hacer algo con la película creada, por ejemplo, limpiar los campos del formulario
            this.newMovie = {
              title_movie: '',
              gender_movie: '',
              year_movie: '',
              director_movie: ''
            };

            // Actualizar la lista de películas llamando a la función para obtener películas
            await this.getMoviesAndDetails();
            
            this.successMessage = '¡La película se ha creado correctamente!';
           
            // El mensaje desaparece después de 2 segundos
            setTimeout(() => {
              this.successMessage = '';
            }, 2000);
          } else {
            this.errorMessage = 'Error al crear la película';
          }
        } catch (error) {
          console.error('Error al guardar la nueva película:', error);
          this.errorMessage = 'Error al guardar la nueva película';
        }
      } else {
        this.errorMessage = 'Por favor, completa todos los campos';
      }
    },

De esta forma, tenemos a disposición del usuario, un formulario para crear películas

Y la nueva película se quedará guardada en nuestra base de datos

Y esto es todo por el momento, en lo referido a las acciones que podemos llevar a cabo con bases de datos, APIS y un frontend como VUE.JS.

Como siempre, el código está disponible en mi repositorio de Github

Por Jose Manuel Sanz Prieto

Desarrollador web. En este blog hablo de fotografía, programación con Django, Python, PHP y privacidad.

1 comentario

Dejar un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *