Erro após cadastrar em vue - resolvido

Faço o cadastro no banco de dados, com o formulário abaixo.

<script setup lang="ts">
import { computed, onMounted, ref } from "vue";

import BaseBreadcrumb from "@/components/shared/BaseBreadcrumb.vue";
import UiParentCard from "@/components/shared/UiParentCard.vue";
import { router } from "@/router";
import { useTemaStore } from "@/stores/apps/tema";
import { format } from "date-fns";
import type { Header } from "vue3-easy-data-table";
import "vue3-easy-data-table/dist/style.css";

const page = ref({ title: "Temas de Estudo" });
const breadcrumbs = ref([
  {
    disabled: true,
    href: "#",
  },
]);

const store = useTemaStore();

const valid = ref(true);
const editedIndex = ref(-1);
const editedItem = ref({
  nome: "",
});
const desserts = ref({});
const save = async () => {
  if (editedIndex.value > -1) {
    Object.assign(editedIndex.value, editedItem.value);
  } else {
    desserts.value = editedItem.value;
  }
  await store
    .salvar({
      nome: editedItem.value.nome,
      callback: editedItem.value.nome,
    })
    .then();
};
</script>
<template>
  <BaseBreadcrumb
    :title="page.title"
    :breadcrumbs="breadcrumbs"
  ></BaseBreadcrumb>
  <v-row>
    <v-col cols="12" md="12">
      <UiParentCard title="Cadastrar tema de estudo">
        <v-card-text>
          <v-form ref="form" v-model="valid" lazy-validation>
            <v-col cols="12" sm="12">
              <v-text-field
                variant="outlined"
                hide-details
                v-model="editedItem.nome"
                label="Nome"
              ></v-text-field>
            </v-col>
          </v-form>
        </v-card-text>
        <v-card-actions class="pa-4">
          <v-spacer></v-spacer>
          <v-btn color="error">Cancelar</v-btn>
          <v-btn
            color="primary"
            variant="flat"
            @click="save"
            :disabled="editedItem.nome === ''"
          >
            Salvar
          </v-btn>
        </v-card-actions>
      </UiParentCard>
    </v-col>
  </v-row>
</template>

Após quando clico no menu para abrir esta página:

<script setup lang="ts">
import { computed, onMounted, ref } from "vue";

import BaseBreadcrumb from "@/components/shared/BaseBreadcrumb.vue";
import UiParentCard from "@/components/shared/UiParentCard.vue";
import { router } from "@/router";
import { useTemaStore } from "@/stores/apps/tema";
import { format } from "date-fns";
import type { Header } from "vue3-easy-data-table";
import "vue3-easy-data-table/dist/style.css";

const page = ref({ title: "Temas de Estudo" });
const breadcrumbs = ref([
  {
    disabled: true,
    href: "#",
  },
]);

const store = useTemaStore();
onMounted(() => {
  store.listaNormal();
});

const getAnalisesTemas = computed(() => {
  return store.temas;
});
const items = ref(getAnalisesTemas);
const searchField = ref("nome");
const searchValue = ref("");

const headers: Header[] = [
  { text: "Sub-temas", value: "total", sortable: true },
  { text: "Tema", value: "nome", sortable: true },
  { text: "Criado em", value: "createdat", sortable: true },
  { text: "Atualizado em", value: "updatedat", sortable: true },
  { text: "Editado por", value: "nomepessoa", sortable: true },
  { text: "Ativo ?", value: "ativoInativo", sortable: true },
  { text: "", value: "operation" },
];
const themeColor = ref("rgb(var(--v-theme-secondary))");
const visualizar = (id: number) => {
  router.push("/tema/" + id);
};
const subTema = (id: number) => {
  router.push("/sub-tema/" + id);
};
const cadastrar = () => {
  router.push("/tema/cadastrar");
};
</script>
<template>
  <BaseBreadcrumb
    :title="page.title"
    :breadcrumbs="breadcrumbs"
  ></BaseBreadcrumb>
  <v-row>
    <v-col cols="12" md="12">
      <UiParentCard title="Gerenciador dos Temas de Estudo">
        <v-row justify="space-between" class="align-center mb-3">
          <v-col cols="12" md="4">
            <v-text-field
              type="text"
              variant="outlined"
              placeholder="Pesquisa por nome"
              v-model="searchValue"
              density="compact"
              hide-details
              prepend-inner-icon="mdi-magnify"
            />
          </v-col>
          <v-col cols="6" md="1">
            <v-btn icon variant="text" @click="cadastrar()">
              <v-tooltip activator="parent"> Cadastrar tema</v-tooltip>
              <v-icon>mdi-shape-circle-plus</v-icon>
            </v-btn>
          </v-col>
        </v-row>
        <EasyDataTable
          :headers="headers"
          :items="items"
          table-class-name="customize-table"
          :theme-color="themeColor"
          :search-field="searchField"
          :search-value="searchValue"
          :rows-per-page="5"
          buttons-pagination
        >
          <template #item-total="{ total }">
            <div class="player-wrapper">
              {{ total }}
            </div>
          </template>
          <template #item-nome="{ nome }">
            <div class="player-wrapper">
              {{ nome }}
            </div>
          </template>
          <template #item-createdat="{ createdat }">
            <div class="player-wrapper">
              {{ format(new Date(createdat), "dd/MM/yyyy HH:mm:ss") }}
            </div>
          </template>
          <template #item-updatedat="{ updatedat }">
            <div class="player-wrapper">
              {{ format(new Date(updatedat), "dd/MM/yyyy HH:mm:ss") }}
            </div>
          </template>
          <template #item-nomepessoa="{ nomepessoa }">
            <div class="player-wrapper">
              {{ nomepessoa }}
            </div>
          </template>
          <template #item-ativoInativo="{ ativoInativo }">
            <div class="player-wrapper">
              {{ ativoInativo }}
            </div>
          </template>
          <template #item-operation="item">
            <div class="operation-wrapper">
              <v-btn icon variant="text" @click="visualizar(item.id)">
                <v-tooltip activator="parent"> Visualizar </v-tooltip>
                <EyeIcon size="18" />
              </v-btn>
              <v-btn
                icon
                variant="text"
                v-if="item.total > 0"
                @click="subTema(item.id)"
              >
                <v-tooltip activator="parent"> Ver Sub-temas </v-tooltip>
                <ApiAppIcon size="18" />
              </v-btn>
            </div>
          </template>
        </EasyDataTable>
      </UiParentCard>
    </v-col>
  </v-row>
</template>

TemaStateProps

export interface TemaStateProps {
  temas?: Tema[];
  temaPorId?: TemaPorId;
  tema?: TemaSalvar;
}

export type Tema = {
  id?: string | number | undefined;
  total?: number;
  nome?: string;
  createdat?: any;
  updatedat?: any;
  nomepessoa?: string;
  ativoInativo?: boolean;
};

export type TemaPorId = {
  id?: string | number | undefined;
  apresentacao?: string;
  callback?: string;
  createdat?: Date;
  formtripeto?: string;
  icone?: string;
  ativoInativo?: boolean;
  nome?: Date;
  updatedat?: Date;
};

export type TemaSalvar = {
  nome?: string;
  callback?: string;
};

tema.ts

import type { TemaSalvar, TemaStateProps } from "@/types/TemaType";
import axios from "@/utils/axios";
import { defineStore } from "pinia";

const url = import.meta.env.VITE_APP_BACKEND_URL;
const token = localStorage.getItem("token");
const headers = {
  headers: { Authorization: "Bearer " + token },
};
const urlFinal = url + "/api/estudo-tema/";
export const useTemaStore = defineStore({
  id: "tema",
  state: (): TemaStateProps => ({
    temas: [],
    temaPorId: {},
    tema: {},
  }),
  getters: {},
  actions: {
    async buscaPorId(id: number): Promise<any> {
      try {
        const data = await axios.get(
          urlFinal + "buscar-por-id/" + id + "/",
          headers
        );
        this.temaPorId = data.data;
        return this.temaPorId;
      } catch (error) {
        console.log(error);
      }
    },
    async listaNormal() {
      try {
        const data = await axios.get(urlFinal + "lista/", headers);
        this.temas = data.data;
      } catch (error) {
        console.log(error);
      }
    },
    async listaSubTemaWithSumFilhos() {
      try {
        const data = await axios.get(urlFinal + "sub-lista/", headers);
        this.temas = data.data;
      } catch (error) {
        console.log(error);
      }
    },
    async salvar(modelo: TemaSalvar) {
      try {
        const data = await axios.post(urlFinal + "salvar/", modelo, headers);
        this.temas = data.data;
      } catch (error) {
        console.log(error);
      }
    },
  },
});

Mostra o erro

Não dá erro no backend
image

O que pode ser ?

mostra o package.json

package.json

{
  "name": "quizme",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "dev": "vite --port 8081",
    "build": "vue-tsc --noEmit && vite build",
    "homologacao": "vue-tsc --noEmit && vite build --mode homologacao",
    "preview": "vite preview --port 5050",
    "typecheck": "vue-tsc --noEmit",
    "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore"
  },
  "dependencies": {
    "@tiptap/pm": "^2.0.0-beta.220",
    "@tiptap/starter-kit": "2.0.0-beta.220",
    "@tiptap/vue-3": "2.0.0-beta.220",
    "@types/aos": "^3.0.4",
    "aos": "^2.3.4",
    "apexcharts": "3.36.3",
    "axios": "^0.27.2",
    "axios-mock-adapter": "^1.21.2",
    "chance": "^1.1.8",
    "date-fns": "^2.29.3",
    "keycloak-js": "^20.0.3",
    "lodash": "^4.17.21",
    "maska": "^1.5.0",
    "pinia": "2.0.11",
    "remixicon": "2.5.0",
    "svgmap": "^2.10.1",
    "v-calendar": "3.0.0-alpha.8",
    "vee-validate": "4.6.7",
    "vite-plugin-vuetify": "1.0.2",
    "vue": "3.2.31",
    "vue-clipboard3": "^2.0.0",
    "vue-draggable-next": "^2.2.1",
    "vue-i18n": "^9.2.2",
    "vue-moment": "^4.1.0",
    "vue-router": "4.0.12",
    "vue-scrollto": "^2.20.0",
    "vue-tabler-icons": "2.9.0",
    "vue3-apexcharts": "1.4.1",
    "vue3-carousel": "^0.2.9",
    "vue3-easy-data-table": "^1.4.19",
    "vue3-perfect-scrollbar": "1.6.0",
    "vue3-print-nb": "^0.1.4",
    "vue3-recaptcha-v2": "1.0.1",
    "vuedraggable": "^2.24.3",
    "vuetify": "3.3.3",
    "yup": "^0.32.11"
  },
  "devDependencies": {
    "@mdi/font": "^6.5.95",
    "@rushstack/eslint-patch": "^1.1.0",
    "@types/chance": "^1.1.3",
    "@types/node": "^16.11.25",
    "@vitejs/plugin-vue": "4.0.0",
    "@vue/eslint-config-prettier": "^7.0.0",
    "@vue/eslint-config-typescript": "^10.0.0",
    "@vue/tsconfig": "^0.1.3",
    "esbuild": "^0.17.5",
    "eslint": "^8.5.0",
    "eslint-plugin-vue": "^8.2.0",
    "prettier": "^2.5.1",
    "sass": "^1.49.9",
    "sass-loader": "^10.0.0",
    "typescript": "~4.5.5",
    "vite": "4.1.1",
    "vue-cli-plugin-vuetify": "2.5.5",
    "vue-tsc": "1.0.3",
    "vuetify-loader": "^2.0.0-alpha.9"
  },
  "engines": {
    "node": ">= 4.0.0",
    "npm": ">= 3.0.0"
  },
  "browserslist": [
    "> 1%",
    "last 2 versions",
    "not ie <= 8"
  ]
}

O problema acontece quando vc salva? ou quando vai pra tabela?


O problema pode ser no EasyDataTable. Comenta esse componente e tenta recarregar a pagina

1 curtida

Sim. Deveria ter falado. Já tinha feito isto.

Assim não dá erro.

<!--<EasyDataTable
          :headers="headers"
          :items="items"
          table-class-name="customize-table"
          :theme-color="themeColor"
          :search-field="searchField"
          :search-value="searchValue"
          :rows-per-page="5"
          buttons-pagination
        >
          <template #item-total="{ total }">
            <div class="player-wrapper">
              {{ total }}
            </div>
          </template>
          <template #item-nome="{ nome }">
            <div class="player-wrapper">
              {{ nome }}
            </div>
          </template>
          <template #item-createdat="{ createdat }">
            <div class="player-wrapper">
              {{ format(new Date(createdat), "dd/MM/yyyy HH:mm:ss") }}
            </div>
          </template>
          <template #item-updatedat="{ updatedat }">
            <div class="player-wrapper">
              {{ format(new Date(updatedat), "dd/MM/yyyy HH:mm:ss") }}
            </div>
          </template>
          <template #item-nomepessoa="{ nomepessoa }">
            <div class="player-wrapper">
              {{ nomepessoa }}
            </div>
          </template>
          <template #item-ativoInativo="{ ativoInativo }">
            <div class="player-wrapper">
              {{ ativoInativo }}
            </div>
          </template>
          <template #item-operation="item">
            <div class="operation-wrapper">
              <v-btn icon variant="text" @click="visualizar(item.id)">
                <v-tooltip activator="parent"> Visualizar </v-tooltip>
                <EyeIcon size="18" />
              </v-btn>
              <v-btn
                icon
                variant="text"
                v-if="item.total > 0"
                @click="subTema(item.id)"
              >
                <v-tooltip activator="parent"> Ver Sub-temas </v-tooltip>
                <ApiAppIcon size="18" />
              </v-btn>
            </div>
          </template>
        </EasyDataTable>-->

Video:
http://sc.com.ly/show/06495532-78b0-4d02-be11-9271b1ee91a3

entendi oq ta rolando… Na hora que vc salva o novo tema, a sua variável items tá virando um objeto, e deixando de ser um array.

esse trecho salva o novo tema, certo? O correto seria:

this.temas = [...this.temas, data.data];

assim ele vai pegar tudo que já existe, e vai incluir um novo objeto.


ou vc pode simplesmente dar um push também,

this.temas.push(data.data);
1 curtida

Realmente. Mas o certo é assim, porque do backend ele só retorna um, após salvar

async salvar(modelo: TemaSalvar) {
  try {
    const data = await axios.post(urlFinal + "salvar/", modelo, headers);
    this.tema = data.data;
  } catch (error) {
    console.log(error);
  }
},

Obrigado e vou me atentando a isto

1 curtida