V-If and V-else questions (Vue and Firebase Real-time Database) - vue.js

I'm working on a web application using Vue and Firebase-Real-time Database. I managed to include all the CRUD functions following several tutorials in Youtube. The problem right now is that i am unable to show or hide a certain element when changing the {Edit:} condition of the user via v-if/v-else. Below will be the code;
<template>
<div class="row">
<div class="container">
<table class="table table-striped">
<thead>
<tr>
<th>Name</th>
<th>Email</th>
<th>ID</th>
<th>Actions</th>
</tr>
</thead>
<tbody v-for="userProfile in Users" :key="userProfile.key">
<tr v-if="userProfile.edit">
<td>{{userProfile.username}}</td>
<td>{{userProfile.email}}</td>
<td>{{userProfile.userId}}</td>
<td>
<button #click.prevent="updateUser(userProfile.key)" class="btn btn-primary"> Update </button>
<button #click.prevent="removeUser(userProfile.key)" class="btn btn-danger">Delete</button>
</td>
</tr>
<tr v-else>
<td> <input type="text" v-model="userProfile.username"> </td>
<td> <input type="text" v-model="userProfile.email"> </td>
<td> <input type="text" v-model="userProfile.userId"> </td>
<td>
<button #click.prevent="saveUser(userProfile)" class="btn btn-primary"> Save </button>
<button #click.prevent="cancel(userProfile.key)" class="btn btn-danger"> Cancel </button>
</td>
</tr>
</tbody>
</table>
</div>
</div>
As for my script
import { usersRef } from '../main.js';
export default {
data() {
return {
Users: [],
}
},
created() {
usersRef.once('value', (Users) => {
Users.forEach((doc) => {
this.Users.push({
key: doc.key,
email: doc.child('email').val(),
username: doc.child('username').val(),
userId: doc.child('userId').val(),
})
})
})
},
methods:{
removeUser: function(key) {
usersRef.child(key).remove()
.then(function() {
console.log("deleted Sucessfully");
alert("Sucessfully Deleted");
}).catch(function(error) {
console.log(error);
});
},
updateUser: function(key) {
usersRef.child(key).update({edit:false})
.then(function() {
console.log("update Sucessfully");
alert("Sucessfully Update");
}).catch(function(error) {
console.log(error);
});
},
cancel:function(key){
usersRef.child(key).update({edit:false})
},
saveUser:function(userProfile) {
const key = userProfile.key;
usersRef.child(key).set({username:userProfile.username,email:userProfile.email,userId:userProfile.userId,edit:true})
.then(function() {
console.log("Saved Sucessfully");
alert("Successfully Saved");
}).catch(function(error) {
console.log(error);
});
}
}
}
am i doing something wrong? thanks in advance!

Related

Not able to remove a user from a table

I have a nested table where I'm grouping users by the department that they belong to. The issue I'm having is that if I click on the delete button, that specific user that I've deleted isn't being removed from the list and I'm not getting any errors in my console.
Here is my code
<template>
<div>
<div class="row">
<div class="col-lg-12">
<table class="table table-bordered table-sm">
<thead>
<tr>
<th>Name</th>
<th>Job Title</th>
</tr>
</thead>
<tbody v-for="(users, department) in personnal">
<tr>
<td>{{ department }}</td>
</tr>
<tr v-for="user in users">
<td>{{ user.name }}</td>
<td>{{ user.job_title }}</td>
<td>
<div class="btn btn-danger btn-sm" #click="removeUser(user)">
<i class="fa fa-trash"></i>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</template>
export default
{
props: [],
data() {
return {
personnal: {},
}
},
computed: {
},
methods: {
getUsers(){
axios.get(`/api/users`).then(response => {
this.personnal = response.data.users;
});
},
removeUser(user){
axios.delete(`/api/users/${user.id}/delete`).then(response => {
Object.keys(this.personnal).forEach(user => {
this.personnal[user].filter(u => u.id !== response.data.id);
this.personnal[user].slice(response.data);
});
});
}
},
mounted() {
this.getUsers();
}
}
</script>
First of all, you have to pass both department and user in the click event:
<div class="btn btn-danger btn-sm" #click="removeUser(department, user)">
<i class="fa fa-trash"></i>
</div>
Then, in the removeUser method:
removeUser(department, user){
axios.delete(`/api/users/${user.id}/delete`).then(response => {
const index = this.personnal[department].findIndex(u => u.id === user.id);
this.personnal[department].splice(index, 1);
});
}

How to redirect to a page with an object in vue

I have a couple of vue pages, one page is a list of users, the second is a list of permissions and the third is a vue component
that displays the list of users and another vue component that shows the details of a user.
What I'm trying to do is, if I'm on the permissions page and I would like to go to a specific user's details I would like to redirect
with that panel open.
I am able to redirect the the users page by doing window.location.href = '/admin/users'; but I'm not sure how I'm going to get
the user panel open.
I thought that if I could do $emit then that could pass the user object over to the users main page, but that won't work if I do
a window.location.href = '/admin/users';
Here is my code. This has 2 components displays a list of users and their details
<template>
<div class="row">
<div class="col-md-6">
<users :emit="emit" :users="users"></users>
</div>
<div class="col-md-6">
<detail v-if="userDetails" :emit="emit" :user="manageUser"></detail>
</div>
</div>
</template>
<script>
export default {
props: ['emit', 'users'],
data() {
return {
userDetails: false,
manageUser: null
}
},
mounted() {
this.emit.$on('user', payload => {
this.manageUser = payload.user;
this.userDetails = true;
});
}
}
</script>
This is my users lists
<template>
<div class="card">
<div class="card-header">
<h3 class="card-title text-success" style="cursor: pointer;" #click="createUser"> New User</h3>
</div>
<div class="card-body">
<table class="table table-sm table-striped">
<thead>
<tr>
<th>Name</th>
<th style="width:120px;"></th>
</tr>
</thead>
<tbody>
<tr v-for="user in users">
<td>{{user.name}}</td>
<td style="text-align: right;">
<button class="btn btn-sm btn-outline-info" #click="detail(user)">Details</button>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</template>
<script>
export default {
props: ['emit', 'users'],
data() {
return {
}
},
methods: {
detail(user) {
this.emit.$emit('user', { user: user });
}
}
}
</script>
and this is my permissions pages
<template>
<div class="card">
<div class="card-header">
<h3 class="card-title">{{permission.name}}</strong></h3>
</div>
<div class="card-body p-0">
<table class="table table-sm table-striped">
<thead>
<tr>
<th>User Name</th>
<th style="width:120px;"></th>
</tr>
</thead>
<tbody>
<tr v-for="user in users">
<td>{{user.name}}</td>
<td style="text-align: right;">
<button class="btn btn-sm btn-outline-info" #click="detail(user)">Details</button>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</template>
<script>
export default {
props: ['emit'],
data() {
return {
users: []
}
},
mounted() {
this.allUsers();
},
methods: {
allUsers() {
this.loading = true;
axios.get('/users').then(response => {
this.users = response.data.users;
});
},
detail(user) {
window.location.href = '/admin/users';
}
}
}
</script>

Disable/Enable input for each item from a loop VueJS

I try to enable/disable each input from a loop. The problem is that my method it works just after refresh. After I modify something in code and save, then the input works.
<tr v-for="(item, index) in customer_names" :key="item.id">
<td>
<input :disabled="!item.disabled"
v-model="item.name"
type="text"
</td>
</tr>
<div class="edit_mode"
:class="{'display-none':!item.disabled}">
<i class="fa fa-save" #click="disableInput(index)" aria-hidden="true"></i>
</div>
<div class="edit_mode"
:class="{'display-none':item.disabled}">
<i class="fa fa-edit" #click="enableInput(index)" aria-hidden="true"></i>
</div>
props:['customer_names'],
data(){
return{
disabled: [],
}
}
enableInput(index){
console.log('enableInput',this.customer_names[index].disabled);
this.customer_names[index].disabled = false;
},
disableInput(index){
console.log('disabeInput',this.customer_names[index].disabled);
this.customer_names[index].disabled = true;
}
I didn't fully understand your problem. I deduced that you might want to enable or disable the text fields that you create from the data provided. If this is still not what you meant, correct your question by pasting more source code, and explain your problem in more detail.
Vue.component("custom", {
template: "#custom-template",
props: ["customer_names"],
methods: {
enableInput(item) {
item.disabled = false;
},
disableInput(item) {
item.disabled = true;
},
toggleInput(item) {
item.disabled = !item.disabled;
}
}
});
new Vue({
data() {
return {
items: [
{ name: "fus", disabled: false },
{ name: "ro", disabled: false },
{ name: "dah", disabled: true }
]
};
}
}).$mount("#app");
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<custom :customer_names="items" />
</div>
<script type="text/x-template" id="custom-template">
<table cellpadding=5>
<tr>
<th>Input</th>
<th>Version 1</th>
<th>Version 2</th>
</tr>
<tr v-for="item in customer_names" :key="item.id">
<td>
<input :disabled="item.disabled" v-model="item.name" type="text" />
</td>
<td>
<button #click="item.disabled = false">E</button>
<button #click="item.disabled = true">D</button>
<button #click="item.disabled = !item.disabled">T</button>
</td>
<td>
<button #click="enableInput(item)">E</button>
<button #click="disableInput(item)">D</button>
<button #click="toggleInput(item)">T</button>
</td>
</tr>
</table>
</script>

posting a vue.js form, cannot get $post in php

I have a form in vue.js with dynamic rows and I am using a classical HTML form tag to get the results in a php page.
My output in Php does not show the $post as expected.
A jsfiddle with the form is available;
my code is as follow:
html
<form method="post" action="action_page.php">
<div id="app">
<table class="table">
<thead>
<tr>
<td><strong>Date</strong></td>
<td><strong>Account</strong></td>
<td><strong>Debit</strong></td>
<td><strong>Credit</strong></td>
<td></td>
</tr>
</thead>
<tbody>
<tr v-for="row in rows">
<td>
<input class="form-control" type="date" v-model="row.myDate">
</td>
<td>
<v-select :options="['Account1','Account2','Account3']"></v-select>
</td>
<td>
<input class="form-control" type="text" v-model="row.debit" v-on:keypress="isNumber(event)">
</td>
<td>
<input class="form-control" type="text" v-model="row.credit" v-on:keypress="isNumber(event)">
</td>
<td ><i class="fa fa-trash-o fa-2x"style="color:brown;" #click="removeRow(row)"></i> <i class="fa fa-plus-circle fa-2x"style="color:#428bca" #click="addRow"></i> </td>
</tr>
</tbody>
<tfooter>
<td class="al-g"> <button class="button btn-primary" #click="addRow">Add Line</button></td>
<td> </td>
<td class="al-r">tot D.: {{ totaldebit | roundme }}</td>
<td class="al-r">tot Cr.:{{ totalcredit | roundme}}</td>
<td class="al-r">Dif: {{ totaldebit-totalcredit | roundme}}</td>
</tfooter>
</table>
</div>
<button class="button btn-danger" type="submit">Post</button>
</form>
</body>
and I have the following script:
<script>
Vue.filter('roundme', function (value) {
return value.toFixed(3);
})
Vue.component('v-select', VueSelect.VueSelect);
var app = new Vue({
el: "#app",
data: {
rows: [{debit:0, credit:0},
]
},
computed: {
totaldebit() {
return this.rows.reduce((total, row) => {
return total + Number(row.debit);
}, 0);
},
totalcredit() {
return this.rows.reduce((total, row) => {
return total + Number(row.credit);
}, 0);
}
},
methods: {
addRow: function() {
this.rows.push({myDate:"",
account:"",
debit: "",
credit: ""
});
},
removeRow: function(row) {
//console.log(row);
this.rows.$remove(row);
},
isNumber: function(evt) {
evt = (evt) ? evt : window.event;
var charCode = (evt.which) ? evt.which : evt.keyCode;
if ((charCode > 31 && (charCode < 48 || charCode > 57)) && charCode !== 46) {
evt.preventDefault();;
} else {
return true;
}
}
}
});
</script>
my php page action_page is as follow:
<?php
echo '$post detail';
foreach ($_POST as $key => $value)
echo "Field ".htmlspecialchars($key)." is ".htmlspecialchars($value)."<br>";
?>
Just add name attribute to inputs.
<input class="form-control" type="date" name="date" v-model="row.myDate">
or dynamical
<input class="form-control" type="date" :name="'date'+index" v-model="row.myDate">
Try this https://jsfiddle.net/jp1zw25a/ and check results in browser dev-tools

How to call method from another component VUE

I have one component
<template>
<div class="section">
<a v-if='type == "events"' class="button is-primary" #click="showForm()">
<i class="fa fa-calendar"></i> &nbsp<span class="card-stats-key"> Add Event</span>
</a>
<a v-if='type == "places"' class="button is-primary" #click="showForm()">
<i class="fa fa-location-arrow"></i> &nbsp<span class="card-stats-key"> Add Place</span>
</a>
<table class="table" v-if="!add">
<thead>
<tr>
<th>
<abbr title="Position"># Client Number</abbr>
</th>
<th>Title</th>
<th>
<abbr title="Played">Status</abbr>
</th>
<th>
<abbr title="Played">View</abbr>
</th>
</tr>
</thead>
<tbody>
<tr v-for="event in events">
<th>{{event.client_number}}</th>
<td v-if='type == "events" '>{{event.title}}</td>
<td v-if='type == "places" '>{{event.name}}</td>
<td>
<p class="is-danger">Waiting</p>
</td>
<td> View </td>
</tr>
</tbody>
</table>
<add v-if="add" v-on:hideAdd="hideFrom()"></add>
</div>
</template>
<script>
import Add from '../forms/AddPlace.vue'
export default {
name: 'Tabbox',
data() {
return {
events: [],
add: ''
}
},
props: ['type'],
created() {
let jwt = localStorage.getItem('id_token')
var ref = wilddog.sync().ref('users').child(jwt).child(this.type);
ref.once("value")
.then((snapshot) => {
this.events = snapshot.val();
}).catch((err) => {
console.error(err);
})
},
methods: {
showForm(add) {
if (this.add == true)
this.add = false;
else {
this.add = true;
}
},
hideFrom() {
this.add = false
console.log('This add is false');
}
},
components: {
Add
}
}
</script>
and another component
<template>
<div class="field is-horizontal">
<div class="field-label">
<!-- Left empty for spacing -->
</div>
<div class="field-body">
<div class="field">
<div class="control">
<button class="button is-primary" v-bind:class="{ 'is-loading': loading } " #click="addPlace()">
Add place
</button>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
add: false
}
},
methods: {
addPlace() {
this.$emit('hideAdd', this.add)
},
},
}
</script>
How i can calling method from showForm() from first first component in second one! I'm trying to that with $emit function, it doesn't work. And trying with $broadcast, same. How i can use event there?
Add a ref attribute to the child component in the parent component's template like this:
<add v-if="add" v-on:hideAdd="hideFrom()" ref="add-component"></add>
Now your parent component will have access to the child component's VueComponent instance and methods, which you can access like this:
methods: {
showForm() {
this.$refs['add-component'].addPlace();
}
}
Here's documentation on refs.