I have an API project where I need to display some data in a table, but I also have two date fields that the user should be able to fill with a start and a last date, and then when the submit button is clicked, only the data where its "date" field is comprised between the two dates is displayed, but i can't find a way to do it.
Here is the part of the code that is concerned :
<input
style="position: relative; left: 750px"
type="date"
label="starting date"
/>
<input
style="position: relative; left: 750px"
type="date"
label="last date"
/>
<button
style="position: relative; left: 750px"
type="button"
class="btn btn-secondary"
>
submit dates
</button>
<hr />
<table class="table table-hover table-striped">
<!--Table Head-->
<thead class="thead-dark">
<tr>
<th scope="col">ID</th>
<th scope="col">apkMode</th>
<th scope="col">date</th>
<th scope="col">timestamp</th>
<th scope="col">user</th>
<th scope="col">news</th>
<th scope="col">selfEvaluationQuestion</th>
<th scope="col">selfEvaluationAnswer</th>
<th scope="col">questionQuiz</th>
<th scope="col">answerQuiz</th>
<th scope="col">quizAnswer</th>
<th scope="col">questionQ2</th>
<th scope="col">answerQ2</th>
<th scope="col">similarityq2</th>
<th scope="col">questionQ0</th>
<th scope="col">answerQ0</th>
</tr>
</thead>
<tbody>
<tr v-for="(sessions, _id) in sessions" :key="_id">
<td>{{ sessions._id }}</td>
<td>{{ sessions.apkMode }}</td>
<td>{{ sessions.date }}</td>
<td>{{ sessions.timestamp }}</td>
<td>{{ sessions.user }}</td>
<td>
<span
v-for="(interactions, index) in sessions.interactions"
:key="index"
>
<p v-if="sessions.interactions[index].type === 'newsCore'">
{{ sessions.interactions[index].text }}
</p>
</span>
</td>
<td>
<span
v-for="(interactions, index) in sessions.interactions"
:key="index"
>
<p
v-if="
sessions.interactions[index].type ===
'selfEvaluationQuestion'
"
>
{{ sessions.interactions[index].text }}
</p>
</span>
</td>
<td>
<span
v-for="(interactions, index) in sessions.interactions"
:key="index"
>
<p
v-if="
sessions.interactions[index].type ===
'selfEvaluationAnswer'
"
>
{{ sessions.interactions[index].text }}
</p>
</span>
</td>
<td>
<span
v-for="(interactions, index) in sessions.interactions"
:key="index"
>
<p
v-if="
sessions.interactions[index].type === 'questionQuiz'
"
>
{{ sessions.interactions[index].text }}
</p>
</span>
</td>
<td>
<span
v-for="(interactions, index) in sessions.interactions"
:key="index"
>
<p
v-if="sessions.interactions[index].type === 'answerQuiz'"
>
{{ sessions.interactions[index].text }}
</p>
</span>
</td>
<td>
<span
v-for="(interactions, index) in sessions.interactions"
:key="index"
>
<p
v-if="sessions.interactions[index].type === 'answerQuiz'"
>
{{ sessions.interactions[index].quizAnswer }}
</p>
</span>
</td>
<td>
<span
v-for="(interactions, index) in sessions.interactions"
:key="index"
>
<p
v-if="sessions.interactions[index].type === 'questionQ2'"
>
{{ sessions.interactions[index].text }}
</p>
</span>
</td>
<td>
<span
v-for="(interactions, index) in sessions.interactions"
:key="index"
>
<p v-if="sessions.interactions[index].type === 'answerQ2'">
{{ sessions.interactions[index].text }}
</p>
</span>
</td>
<td>
<span
v-for="(interactions, index) in sessions.interactions"
:key="index"
>
<p v-if="sessions.interactions[index].type === 'answerQ2'">
{{ sessions.interactions[index].similarity }}
</p>
</span>
</td>
<td>
<span
v-for="(interactions, index) in sessions.interactions"
:key="index"
>
<p v-if="sessions.interactions[index].type === 'answerQ0'">
{{ sessions.interactions[index].text }}
</p>
</span>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
and the javascript part :
<script>
import axios from "axios";
import papa from "papaparse";
export default {
data() {
return {
sessions: [],
};
},
methods: {
getSessions() {
const path = "http://localhost:5000/data_for_front";
axios
.get(path)
.then((res) => {
this.sessions = res.data;
papa.parse(this.sessions, {
header: true,
dynamicTyping: true,
skipEmptyLines: true,
complete(result) {
this.sessions = result.data;
},
});
})
.catch((err) => {
console.error(err);
});
},
finally, a sample of the data I am working with :
{
"_id" : "userid",
"apkMode" : "SCROLL",
"date" : "2022-04-25",
"timestamp" : NumberLong(1650913068512),
"user" : "username",
"interactions" : [
{
"interactionTimestamp" : NumberLong(1650912989260),
"subject" : "ROBOT",
"type" : "selfEvaluationQuestion",
"text" : "questiontext"
},
{
"interactionTimestamp" : NumberLong(1650913013738),
"subject" : "HUMAN",
"type" : "selfEvaluationAnswer",
"text" : "questionresponse"
},
{
"interactionTimestamp" : NumberLong(1650913022948),
"subject" : "ROBOT",
"type" : "newsCore",
"text" : "newstext"
},
{
"interactionTimestamp" : NumberLong(1650913042076),
"subject" : "ROBOT",
"type" : "questionQ2",
"text" : "Q2text"
},
{
"interactionTimestamp" : NumberLong(1650913047978),
"subject" : "ROBOT",
"type" : "questionQ0",
"text" : "Q0text"
},
{
"interactionTimestamp" : NumberLong(1650913047978),
"subject" : "HUMAN",
"type" : "answerQ2",
"text" : "Q2answer",
"similarity" : 0.0,
"correctAnswer" : "Q2correctanswer"
},
{
"interactionTimestamp" : NumberLong(1650913058686),
"subject" : "HUMAN",
"type" : "answerQ0",
"text" : "Q0answer"
},
{
"interactionTimestamp" : NumberLong(1650913058867),
"subject" : "ROBOT",
"type" : "questionEnd",
"text" : "Endquestion"
},
{
"interactionTimestamp" : NumberLong(1650913068512),
"subject" : "HUMAN",
"type" : "answerEnd",
"text" : "Endanswer"
}
]
}
Also, I know I should not be using v-for with v-if but Since my data sample is limited, I have been authorized to for simplicity reasons.
Thanks !
Related
I'm trying to add rows to a table dynamically with a method in nuxt.js, but the prop that I have defined doesn't work...
I receive this error from the console:
Property or method "invoice_customer" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property.
I'm trying with this template:
<template>
<div>
<h3>Customers</h3>
<input type="text" v-model="search" placeholder="Search for names..." />
<table v-if="customers.length > 0">
<tr>
<th>name</th>
<th>address</th>
</tr>
<tr v-for="customer in customers" :key="customer.id">
<td>{{ customer.name }}</td>
<td>{{ customer.address }}</td>
</tr>
</table>
<div class="center">
<p>Customer</p>
<select v-if="customers.length > 0">
<option v-for="customer in customers" :key="customer.id">
{{ customer.name }}
</option>
</select>
</div>
<table v-if="invoice_customers.length > 0">
<tr>
<th>Id</th>
<th>Amount</th>
<th>Expire Date</th>
<th>Note</th>
</tr>
<tr
v-for="invoice_customers in invoice_customer"
:key="invoice_customers.id"
>
<td>
<input
type="number"
name=""
id=""
v-model="invoice_customer.amount"
/>
</td>
<td>
<b-form-datepicker
id="example-datepicker"
v-model="invoice_customer.expire_date"
class="mb-2"
></b-form-datepicker>
</td>
<td>
<input type="text" name="" id="" v-model="invoice_customer.note" />
</td>
</tr>
</table>
<b-button variant="outline-success" #click="addNewInstallment">+ Add New</b-button>
</div>
</template>
and this is my script:
<script>
export default {
name: "IndexPage",
data() {
return {
selected: "",
customers: [],
search: "",
invoice_customers: [{
id: 0,
amount: 0,
expire_date: "",
note: "",
}],
};
},
props: {
},
async mounted() {
const response = await this.$axios.$get("/api/customers");
this.customers = response.data;
return this.customers.filter((p) => {
// return true if the product should be visible
// in this example we just check if the search string
// is a substring of the product name (case insensitive)
return p.name.toLowerCase().indexOf(this.search.toLowerCase()) != -1;
});
},
methods: {
addNewInstallment() {
this.invoice_customers.push({
id: 0,
amount: 0,
expire_date: "",
note: "",
});
}
}
}
</script>
invoice customer is defined in v-for cycle
You inverted the order in your v-for, it should be
v-for="invoice_customer in invoice_customers"
in my Vuejs3 project, there is a form in which the new row will be generated by pressing a button, so I put an array to handle new rows then I need to validate inputs, but after validation of the input of the array, the value didn't pass to model, but it works without the validation.. please help me to understand the mistake that I did.
The Form:
<table class="table table-stripped table-border">
<thead>
<tr>
<th>#</th>
<th style="width: 18%">
Medikament <span class="text-danger">*</span>
</th>
<th style="width: 9%">Milligram</th>
<th style="width: 9%">
Packung <span class="text-danger">*</span>
</th>
<th style="width: 7%">
Stück <span class="text-danger">*</span>
</th>
<th style="width: 19%">Apothekenname</th>
<th style="width: 24%">Adresse der Apotheke</th>
<th style="width: 14%">Postleitzahl</th>
</tr>
</thead>
<tbody>
<tr v-for="(item, index) in patientRequestForCreationDtos" :key="index">
<td>{{ index + 1 }}</td>
<td>
<input type="text" v-model="item.drugName" class="form-control" />
</td>
<td>
<input type="number" v-model="item.milligram" class="form-control" />
</td>
<td>
<input type="number" v-model="item.box" class="form-control" />
</td>
<td>
<input type="number" v-model="item.total" class="form-control" />
</td>
<td>
<input type="text" class="form-control" v-model="item.drugStoreName" :readonly="patientDetails.isElga == false" />
</td>
<td>
<input type="text" class="form-control" v-model="item.drugStoreAddress" :readonly="patientDetails.isElga == false" />
</td>
<td>
<input type="text" class="form-control" v-model="item.drugStorePostalCode" :readonly="patientDetails.isElga == false" />
</td>
<td>
<button type="button" #click="deleteRequestItemRow(index)" class="btn btn-sm btn-danger">
-
</button>
</td>
</tr>
</tbody>
</table>
The Array:
patientRequestForCreationDtos: [{
milligram: null,
box: null,
total: null,
drugStoreName: "",
drugStoreAddress: "",
drugStorePostalCode: "",
drugName: "",
}, ],
The validation function:
checkValidation() {
if (!this.patientRequestForCreationDtos.drugName) {
Swal.fire("drug name is required...");
return;
}
return true;
},
```js
---
it always says => drug name is required..
this.patientRequestForCreationDtos is array. maybe you can do this.
checkValidation(patientRequestForCreationDto) {
if (!patientRequestForCreationDto.drugName) {
Swal.fire("drug name is required...");
return;
}
return true;
},
if you'll have only one element in patientRequestForCreationDtos then you gotta choose first element in the array and then check its property
checkValidation() {
if (!this.patientRequestForCreationDtos[0].drugName) {
Swal.fire("drug name is required...");
return;
}
return true
},
also if your patientRequestForCreationDtos is always gonna be an array then you might find this helpful
I am very new to vue and I am trying to validate an array using vuelidate which is used to render a dynamic table. The problem is with the validation() method as I can comprehend.
According to vuelidate docs, https://vuelidate.js.org/#sub-collections-validation, the $each method supports array. When I use it, the validation never fails. However, when I omit $each, and, try to validate first index of the array, it returns as corrected - validation fails.
To be more precise, I am trying to validate each added row(s), and if there's a problem with the validation, it'd add a class to the affected row.
Component App.vue,
This is the HTML code:
<template>
<div>
<br>
<div class="text-center">
<button type="button" class="btn btn-outline-primary" #click="addRow()">Shto</button>
</div>
<br>
<p
v-for="error of v$.$errors"
:key="error.$uid"
>
<strong>{{ error.$validator }}</strong>
<small> on property</small>
<strong>{{ error.$property }}</strong>
<small> says:</small>
<strong>{{ error.$message }}</strong>
</p>
<form name="articles" #submit.prevent="submitForm">
<table class="table table-hover table-responsive">
<thead class="thead-inverse">
<tr>
<th>Nr.</th>
<th class="col-3">Numri</th>
<th class="col-4">Përshkrimi</th>
<th class="col-1">Sasia</th>
<th class="col-1">Çmimi</th>
<th class="col-2">Shuma</th>
<th></th>
</tr>
</thead>
<tbody>
<tr v-for="(item, idx) in items_table" :key="item">
<td>
{{idx+1}}
</td>
<td>
<input v-model="item.part_no" name="part_no[]" class="form-control" type="text" />
</td>
<td>
<textarea v-model="item.part_name" name="part_name[]" class="form-control" type="text"></textarea>
</td>
<td>
<input v-model="item.part_qty" name="part_qty[]" class="form-control " type="number" step="0.01">
</td>
<td>
<input v-model="item.part_price" name="part_price[]" class="form-control" type="number" step="0.01">
</td>
<td>
<input :value="item.part_total" name="part_total[]" class="form-control text-center border-0" style="background-color: transparent; font-size: 18 px;" type="text" disabled>
</td>
<td>
<button type="button" #click="deleteRow(idx)" class="btn btn-danger btn-md btn-block">X</button>
</td>
</tr>
</tbody>
</table>
<div class="text-center">
<button type="submit" name="" id="" class="btn btn-primary btn-lg btn-block">Valido</button>
</div>
</form>
<div class="text-center">
<textarea name="" id="verbose_log" cols="70" rows="15" refs="logg"></textarea>
</div>
</div>
</template>
This is the content from script tag:
<script>
import useVuelidate from '#vuelidate/core'
import { required } from '#vuelidate/validators'
export default {
name: 'App',
setup: () => ({ v$: useVuelidate() }),
validation() {
return {
items_table: {
$each: {
part_no: {
required,
}
}
},
}
},
data() {
return {
items_table: [
{
part_no: '', part_name: '', part_qty: '', part_price: '', part_total: ''
}
],
items_subtotal: 0.00,
items_total: 0.00,
}
},
methods: {
deleteRow(index) {
if(this.items_table.length == 1) {
this.items_table.splice(index, 1);
this.items_subtotal = 0.00;
this.items_total = 0.00;
this.addRow();
} else if(this.items_table.length > 0) {
this.items_table.splice(index, 1);
}
},
addRow() {
this.items_table.push({part_no: '', part_name: '', part_qty: '', part_price: '', part_total: ''});
},
submitForm() {
this.v$.$touch();
//if (this.v$.$error) return;
console.log(this.v$);
document.getElementById('verbose_log').innerHTML = JSON.stringify(this.$data, null, 4);
}
},
computed: {
//
}
}
</script>
For the sake of clarity, I have excluded two methods which calculate line total and the total itself.
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);
});
}
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