vue.js shows no error but page show blank page - api

im making a vue crud page, i already made the route, there is no error in the cmd but when i open the page i doesn't show anything.
here is the barang.vue file that i use for the home
<template>
<div>
<router-link to="/BarangForm/create">Tambah Barang</router-link>
<table>
<tr>
<th>no</th>
<th>Nama</th>
<th>jenis</th>
<th>Harga</th>
<th>Kuantitas</th>
</tr>
<tr v-for="(barang, i) in data_barang" :keys="i">
<td>{{ i + 1}}</td>
<td>{{ barang.nama_barang }}</td>
<td>{{ barang.harga_barang }}</td>
<td>{{ barang.jenis_barang }}</td>
<td>{{ barang.kuantitas }}</td>
<td>
<router-link :to="'/barang' + barang.id">Edit</router-link>
<button #click="deleteRow(barang.id)">Delete</button>
</td>
</tr>
</table>
</div>
</template>
<script>
import axios from 'axios'
export default {
name: 'barang',
data () {
return{
data_barang: []
}
},
mounted () {
this.get()
},
methods: {
get () {
axios.get('barang').then(res => {
if (res.data.status === 'success') {
this.data_barang = res.data.result
}
})
},
deleteRow (id) {
axios.delete('barang/' + id).then(res => {
if(res.data.status === 'success') {
this.get()
}
})
}
}
}
</script>
here is the form for the create and edit
<template>
<div>
<form #submit.prevents="submitForm">
<div>
<label>Nama Barang : </label>
<input type="text" v-model="barang.nama_barang">
</div>
<div>
<label>Harga Barang : </label>
<input type="text" v-model="barang.harga_barang">
</div>
<div>
<label>Jenis Barang : </label>
<input type="text" v-model="barang.jenis_barang">
</div>
<div>
<label>Kuantitas : </label>
<input type="text" v-model="barang.kuantitas">
</div>
<button type="submit">Masukan</button>
</form>
</div>
</template>
<script>
import axios from 'axios'
export default {
name: 'BarangForm',
data () {
return {
barang: {
id: null,
nama_barang: null,
jenis_barang: '',
harga_barang: '',
kuantitas: ''
}
}
},
mounted () {
let id = this.$route.params.id
if (id) {
axios.get('/barang/' + id).then(res => {
this.barang = res.data.result
})
}
},
methods: {
submitForm () {
let data = this.barang
let url = 'barang'
if (this.barang.id){
url += '/' + this.barang.id
}
axios.post(url, data).then(res => {
if (res.data.status === 'success') {
this.$router.push('/barang')
}
})
}
}
}
</script>
this is the router for configuring the route
import Vue from 'vue'
import barang from '#/components/barang'
import BarangForm from '#/components/BarangForm'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
export default new VueRouter({
routes: [
{
path: '/',
name: 'barang',
component : barang
},
{
path: '/barang/create',
name: 'BarangCreate',
component: BarangForm
},
{
path: '/barang/:id',
name: 'BarangEdit',
component: BarangForm
}
]
})
here is the file to render the page
import Vue from 'vue'
import App from './App.vue'
import Router from './router/index.js'
Vue.config.productionTip = false
new Vue({
Router,
render: h => h(App),
}).$mount('#app')
i plan to put every router-link in the home page.

Related

quasar [vuex] unknown action type: loadUsers

I like to get a store running to get a api call, Ive tryed a lot of examples end all ends up with
[vuex] unknown action type: loadUsers
thats my store:
import Vue from "vue";
import Vuex from "vuex";
import axios from "axios";
Vue.use(Vuex);
axios.defaults.baseURL = "https://jsonplaceholder.typicode.com/";
export default new Vuex.Store({
state: {
users: [],
},
actions: {
loadUsers({ commit }) {
Vue.axios.get("users").then((result) => {
commit("SAVE_USERS", result.data);
}).catch((error) => {
throw new Error(`API ${error}`);
});
},
},
mutations: {
SAVE_USERS(state, users) {
state.users = users;
},
},
});
and thats my component to display the received data
<template>
<div class="hello">
<table class="users">
<tr>
<th>Name</th>
<th>Username</th>
<th>Email</th>
</tr>
<tr v-for="user in users" :key="user.id">
<td>{{ user.name }}</td>
<td>{{ user.username }}</td>
<td>{{ user.email }}</td>
</tr>
</table>
</div>
</template>
<script>
import { mapState } from "vuex";
export default {
name: "storenews",
computed: mapState(["users"]),
created() {
this.$store.dispatch("loadUsers");
},
};
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
table {
width: 100%;
}
</style>
taken from a working fiddle from this codepen
Is this because of the Quasar Framework that I miss some fancy special stuff?
Thank you
Can you try to call your dispatch like this:
this.$store.dispatch('loadUsers', null, {root:true})
?

After making a POST request to my heroku endpoint and saved it to my mongoDB, the data only shows if I refresh the page

I deployed my Vue app to Netlify and the backend to heroku. Everything works fine, I can edit, delete and get data from my database, except when I submit the form (creating a new client) and I redirect to this.$router.push("/tabela"); . The data is created, but when I go to the ListComponent.vue (path:'tabela') my data isn't there. It only shows when I refresh the page. Before deploying to heroku, I fixed the issue with window.location.href="/tabela"; instead this.$router.push but now, If I use window.location.href="/tabela" I cannot save to my database anymore. I need to use this.$router.push in order to make it "work" but as I said, then I need to refresh the page to update my table with the new client.
Here is my app https://cadastro-app.netlify.app/ .
CreateComponent.vue
methods: {
submitForm(){
if(this.cliente.cpf === ''){
this.cliente.cpf = 'Não Informado'
}else if(this.cliente.cnpj === ''){
this.cliente.cnpj = 'Não Informado'
}
axios.post('https://cadastro-backend-app.herokuapp.com/clientes', {
data: this.cliente
}).then(function(){
this.cliente = {
nome: '',
sobrenome: '',
email: '',
telefone: '',
cnpj: '',
cpf: ''
}
}).catch(function (error) {
console.log(error);
});
/* window.location.href="/tabela"; */
this.$router.push("/tabela");
}
}
ListComponent.vue
<template>
<div class="row">
<div class="col-md-12 ">
<div class="search">
<input #keyup.enter.prevent="search()" v-model='nomePesquisado' class="form-control mb-3" type="text" placeholder="Pesquisar" aria-label="Search"/>
</div>
<table class="table table-striped">
<thead class="thead-dark">
<tr>
<th>Nome completo</th>
<th>Email</th>
<th>telefone</th>
<th>CNPJ</th>
<th>CPF</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr v-for="cliente in clientes" :key="cliente._id">
<td>{{ cliente.nome }}</td>
<td>{{ cliente.email }}</td>
<td>{{ cliente.telefone }}</td>
<td>{{ cliente.cnpj }}</td>
<td>{{ cliente.cpf }}</td>
<td>
<router-link :to="{name: 'edit', params: { id: cliente._id }}" class="btn btn-success">Editar
</router-link>
<button #click.prevent="removerCliente(cliente._id)" class="btn btn-danger">Remover</button>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</template>
<script>
import axios from "axios";
export default {
data() {
return {
clientes: [],
nomePesquisado:''
}
},
created() {
let apiURL = 'https://cadastro-backend-app.herokuapp.com/clientes/';
axios.get(apiURL).then(res => {
this.clientes = res.data;
console.log(this.clientes);
}).catch(error => {
console.log(error)
});
},
methods: {
removerCliente(id){
const apiURL = `https://cadastro-backend-app.herokuapp.com/clientes/${id}`;
const indexOfArrayItem = this.clientes.findIndex(i => i._id === id);
if (window.confirm("Tem certeza que deseja remover este item?")) {
axios.delete(apiURL).then(() => {
this.clientes.splice(indexOfArrayItem, 1);
}).catch(error => {
console.log(error)
});
}
},
search(){
this.$router.push(`results/${this.nomePesquisado}`);
}
}
}
</script>
router index.js
import Vue from "vue";
import VueRouter from "vue-router";
Vue.use(VueRouter);
const routes = [
{
path: "/",
name: "home",
component: () => import("../components/CreateComponent")
},
{
path: "/tabela",
name: "tabela",
component: () => import("../components/ListComponent")
},
{
path: "/edit/:id",
name: "edit",
component: () => import("../components/EditComponent")
},
{
path: "/results/:id",
name: "results",
component: () => import("../components/Results")
}
];
const router = new VueRouter({
mode: "history",
base: process.env.BASE_URL,
routes
});
export default router;
You are changing the route (this.$router.push("/tabela");) too early
This is what is happening:
You make a POST request
Without waiting for a request to complete, you are telling Vue router to switch to ListComponent (this.$router.push("/tabela");)
Router activates ListComponent component
ListComponent runs a GET request to the server in it's created hook
Result is a "race". Will POST request be fast enough so the GET request sees the new data ?
To be sure, move this.$router.push("/tabela"); inside then

Unable to register child component in vue.js

Getting following error.
Unknown custom element: - did you register the component correctly? For recursive components, make sure to provide the "name" option.
I am not sure what is wrong with the code. I have followed this link https://michaelnthiessen.com/solve-unknown-custom-element-vue/
I have used Local registration for child component. ( RobotBuilder.vue)
<template>
<div class="content">
<button class="add-to-cart" #click="addToCart()">Add to Cart</button>
<div class="top-row">
<PartSelector />
</div>
<div class="middle-row">
<PartSelector />
<PartSelector />
<PartSelector />
</div>
<div class="bottom-row">
<PartSelector />
</div>
<div>
<table>
<thead>
<tr>
<th>Robot</th>
<th class="cost">Cost</th>
<th></th>
</tr>
</thead>
<tbody>
<tr v-for="(robot,index) in cart" :key="index">
<td>{{robot.head.title}}</td>
<td>{{robot.cost}}</td>
<td>
<button #click="removeItem([index])">X</button>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</template>
<script>
import availableParts from '../data/parts';
import { PartSelector } from './PartSelector.vue';
export default {
name: 'RobotBuilder',
components: { PartSelector },
data() {
return {
availableParts,
cart: [],
selectedRobot: {
head: {},
leftArm: {},
rightArm: {},
torso: {},
base: {},
},
};
},
computed: {},
methods: {
addToCart() {
const robot = this.selectedRobot;
const cost = robot.head.cost
+ robot.leftArm.cost
+ robot.torso.cost
+ robot.rightArm.cost
+ robot.base.cost;
this.cart.push({ ...robot, cost });
},
removeItem(index) {
this.cart.splice(index, 1);
},
},
};
</script>
<style scoped>
</style>
PartSelector.vue
<template>
<div class="part">
<img :src="selectedPart.src" title="arm"/>
<button #click="selectPreviousPart()" class="prev-selector"></button>
<button #click="selectNextPart()" class="next-selector"></button>
<span class="sale" v-show="selectedPart.onSale">Sale!</span>
</div>
</template>
<script>
import availableParts from '../data/parts';
const parts = availableParts.heads;
function getPreviousValidIndex(index, length) {
const deprecatedIndex = index - 1;
return deprecatedIndex < 0 ? length - 1 : deprecatedIndex;
}
function getNextValidIndex(index, length) {
const incrementedIndex = index + 1;
return incrementedIndex > length - 1 ? 0 : incrementedIndex;
}
export default {
name: 'PartSelector',
data() {
return { selectedPartIndex: 0 };
},
computed: {
selectedPart() {
return parts[this.selectedPartIndex];
},
},
methods: {
selectNextPart() {
this.selectedPartIndex = getNextValidIndex(
this.selectedPartIndex,
parts.length,
);
},
selectPreviousPart() {
this.selectedPartIndex = getPreviousValidIndex(
this.selectedPartIndex,
parts.length,
);
},
},
};
</script>
You are exporting as default but importing as named import.
In Robot builder, import like this :
import PartSelector from './PartSelector.vue';

Why child component not mounted?

Why child component not mounted?
Base template:
<TableComponent :data="data">
<template slot="thead">
<tr>
<TableHeader></TableHeader>
</tr>
</template>
</TableComponent>
TableComponent:
<template>
<div>
<table>
<thead>
{{ renderThead() }}
</thead>
<tbody>
</tbody>
<tfoot>
</tfoot>
</table>
</div>
</template>
<script>
export default {
name: 'TableComponent',
props: {
data: {
required: true,
type: [Array, Function]
},
itemKey: {
default: 'id',
},
},
methods: {
renderThead: function () {
let method = this.$scopedSlots.thead
? this.$scopedSlots.thead
: () => this.$slots.thead
console.info(method())
// return method();
},
},
}
</script>
It is TableHeader component :
<template>
<th>
{{ name }}
</th>
</template>
<script>
export default {
name: 'TableHeader',
props: {
name: {
type: String
}
},
mounted() {
console.info("MOUNTED")
}
}
</script>
Console info on TableHeader not working.
Do you have any ideas?

Computed property on child component props

I'm having this setup where I have child component props that have datetime format inside it and I want to change it to more human readable format in my table, so i use moment js to change the format and to do those kinds of task it will be made more sense if I use computed property. Like this in my index.vue
<div class="page-container">
<div class="page-content">
<div class="content-wrapper">
<data-viewer :source="source" :thead="thead">
<template scope="props">
<tr>
<td>{{props.item.name}}</td>
<td>{{props.item.creator}}</td>
<td>
<i class="icon-checkmark5" v-if="props.item.publish === '0'"></i>
<i class="icon-cancel-circle2" v-else></i>
{{props.item.publish}} //for testing purpose to see returned value
</td>
<td>{{publishDate}}</td> //this is where i put my computed to change created_at format
</tr>
</template>
</data-viewer>
</div>
</div>
</div>
<script type="text/javascript">
import DataViewer from '../../components/dataviewer.vue'
import moment from 'moment'
export default{
components:{
DataViewer
},
data(){
return{
source: '/api/article',
thead: [
{title: 'Name', key: 'name', sort: true},
{title: 'Creator', key: 'creator_id', sort: true},
{title: 'Publish', key: 'publish', sort: true},
{title: 'Created', key: 'created_at', sort: true}
],
}
},
computed: {
publishDate: function(){
return moment(props.item.created_at).format('YYYY-MM-DD')
}
}
}
</script>
and here is what inside my dataviewer file
<template>
<table class="table">
<thead class="bg-primary">
<tr>
<th v-for="item in thead">
<span>{{item.title}}</span>
</th>
</tr>
</thead>
<tbody>
<slot v-for="item in model.data" :item="item"></slot>
</tbody>
</table>
</template>
<script>
import Vue from 'vue'
import axios from 'axios'
export default {
props: ['source', 'thead'],
data() {
return {
model: {
data: []
},
}
},
beforeMount() {
this.fetchData()
},
methods: {
fetchData() {
var vm = this
axios.get(this.source)
.then(function(response) {
Vue.set(vm.$data, 'model', response.data.model)
})
.catch(function(error) {
console.log(error)
})
}
}
}
</script>
but it just won't work, it can't find props.item.created_at, so how I can change created_at or any other property item to change from my index.vue?
Seems like using a filter will work here:
Instead of using computed props:
filters: {
publishDate: function(value){
return moment(value).format('YYYY-MM-DD')
}
}
In place of {{publishDate}}
<td>{{props.item.created_at | publishedDate }}</td>