Saltar al contenido

Vamos a aprender como utilizar el componente Amplify Connect con múltiples suscripciones en Vuejs 2.

El componente Amplify Connect nos permite obtener o modificar datos de nuestras bases de datos DynamoDB a través de AppSync haciendo uso de las propiedades query y mutation.

En esta entrada vamos a ver cómo trabajar con consultas (query), pero lo importante será ver cómo podemos suscribirnos a múltiples eventos cuando ocurran cosas con nuestros datos, por ejemplo al actualizar o eliminar datos que afecten a lo que estamos mostrando al usuario.

Si no conoces Amplify y todo lo que ofrece, no te pierdas el  Curso de Vuejs 2 con AWS, Cognito y GraphQL, estoy seguro que te resultará súper útil.

Para ponerte en contexto, esto es lo que nos ofrece el componente amplify-connect:

<amplify-connect
      :query="listTodosQuery"
      :subscription="updateOrDeleteTodo"
      :onSubscriptionMsg="onUpdateOrDeleteTodo"
    >
      <template slot-scope="{ loading, data, errors }">
      
      </template>
</amplify-connect>

En este caso nuestro componente ejecutará la query listTodosQuery al inicializarse, la cual lanzará una consulta GraphQL para mostrar los datos necesarios. Además, estará a la escucha de las suscripciones que le hayamos pasado a través de subscription, y por si fuera poco, a través de onSubscriptionMsg, nos retornará datos en el momento en el que alguna suscripción haya sido ejecutada, por ejemplo al borrar un todo. A continuación adjunto un ejemplo completo para poder estar a la escucha de múltiples eventos con el componente amplify-connect.

<template>
  <v-container fluid>
    <amplify-connect
      :query="listTodosQuery"
      :subscription="updateOrDeleteTodo"
      :onSubscriptionMsg="onUpdateOrDeleteTodo"
    >
      <template slot-scope="{ loading, data, errors }">
      
        <div v-if="loading">LOADING DATA...</div>

        <v-layout row wrap v-if="errors.length">
          <v-flex xs12>
            <!-- SHOW ERRORS -->
          </v-flex>
        </v-layout>
        <div v-else-if="data && data.hasOwnProperty('listTodos')">
          <v-layout row wrap mt-4>
            <v-flex xs12 sm8 offset-sm2>
              <v-card>
                <v-list two-line subheader>
                  <v-layout row wrap v-if="!data.listTodos.items.length">
                    <v-flex xs12 pa-2>
                      <!-- NO DATA -->
                    </v-flex>
                  </v-layout>
                  <v-flex xs12 v-else>
                    <todo-item
                      :todo="todo"
                      v-for="todo in data.listTodos.items"
                      :key="todo.id"
                    ></todo-item>
                  </v-flex>
                </v-list>
              </v-card>
            </v-flex>
          </v-layout>
        </div>
      </template>
    </amplify-connect>
  </v-container>
</template>

<script>
import { API, graphqlOperation } from "aws-amplify";
export default {
  name: "TodoList",
  computed: {
    listTodosQuery() {
      return graphqlOperation(this.queryListTodos, { filter: {} });
    },
    updateOrDeleteTodo() {
      const OnUpdateOrDeleteTodo = `subscription OnUpdateOrDeleteTodo {
        onUpdateTodo {
          id
          text
          status
        }
        onDeleteTodo {
          id
          text
        }
      }`;
      return graphqlOperation(OnUpdateOrDeleteTodo);
    }
  },
  methods: {
    canDeleteTodo(todo) {
      //TODO check permissions
    },
    async deleteTodo(todo) {
      // Vuetify Confirm!
      let res = await this.$confirm(
        this.$t("removeTodo", { todo: todo.text }),
        {
          title: this.$t("confirm"),
          buttonTrueText: this.$t("remove"),
          buttonTrueColor: "red",
          color: "red"
        }
      );
      if (res) {
        try {
          await API.graphql(
            graphqlOperation(this.mutationDeleteTodo, {
              input: { id: todo.id }
            })
          );
        } catch (e) {
          // manage errors
        }
      }
    },
    // Subscription on updateOrDeleteTodo fired!
    onUpdateOrDeleteTodo(prevData, newData) {
      if (newData.onUpdateTodo) {
        return this._onUpdateTodo(prevData, newData);
      }
      if (newData.onDeleteTodo) {
        return this._onDeleteTodo(prevData, newData);
      }
    },
    _onUpdateTodo(prevData, newData) {
      const updatedTodo = newData.onUpdateTodo;
      prevData.data.listTodos.items.forEach((todo, index) => {
        if (todo.id === updatedTodo.id) {
          prevData.data.listTodos.items[index].status = updatedTodo.status;
        }
      });
      return prevData.data;
    },
    _onDeleteTodo(prevData, newData) {
      const removedTodo = newData.onDeleteTodo;
      prevData.data.listTodos.items = prevData.data.listTodos.items.filter(
        function(todo) {
          return todo.id !== removedTodo.id;
        }
      );
      return prevData.data;
    }
  }
};
</script>

La idea es simple, haciendo uso de computed definimos la query para listar los todos y las suscripciones a las que necesitamos estar pendientes, en este caso nos conectamos a los eventos onUpdateTodo y onDeleteTodo.

Para entender cómo funcionan las suscripciones y qué nos ofrecen simplemente debes probar este código y revisar el método onUpdateOrDeleteTodo, ahí está todo el código que normalmente necesitarás para mostrar la información actualizada a tus usuarios.

Rutas de aprendizaje