Vuejs: show data with day index on schedule - vue.js

I want to show the schedule, with if condition. If the index in the loop is the same as the index day, then display 'index' else is '-'.
for now, this is my view:
My code:
<td v-for="(n, i) in 7" :key="i">
<span :key="index" v-for="(item, index) in item.schedule_detail">
<span v-if="item.day === i">
<span>{{ item.day }}</span>
</span>
<span v-else>-</span>
</span>
</td>
My expectations:
Thanks a lot.

This v-if logic should work fine. See the below code
new Vue({
el: '#app',
data: {
item: {
schedule_detail: [{
"id": 1,
"doctor_schedule_id": 1,
"day": 0,
"from_time": "08:00:00",
"until_time": "12:00:00",
"from_time_2": "17:00:00",
"until_time_2": "21:00:00",
},
{
"id": 2,
"doctor_schedule_id": 1,
"day": 2,
"from_time": "08:00:00",
"until_time": "21:00:00",
"from_time_2": null,
"until_time_2": null,
}
]
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id='app'>
<td><span :key="index" v-for="(i, index) in 7">
<span v-if= "(i=item.schedule_detail.findIndex(x=>x.day===index)) >=0 ">
{{item.schedule_detail[i].day}}
</span>
<span v-else>-</span>
</span>
</td>
</div>

Related

Vue shopping cart add to cart not working

I cannot see what i have done wrong, i am trying to add my products to my cart but i am not having any luck. How do i add to cart? i can figure out the delete and clear from understanding how to add to cart. i have read through some documentation and managed to get this far but now i am stuck.
i am not sure if i am targeting wrong or i have named something wrong. I used a normal array and it worked alright but i am trying to do it with an api now, does this change the methods?
<section>
<div class ="container" >
<div id="app" >
<div class="row">
<div class="col-md-12" >
<div class="card">
<div class="card-body">
<!-- Cart -->
<table>
<tr>
<th>Product</th>
<th>Price</th>
<th>Quantity</th>
<th>Total</th>
</tr>
<tr v-for="(product, index) in cart">
<td>{{ item.productName }}</td>
<td>{{ item.price }}</td>
<td>{{ item.quantity }}</td>
<td>{{ item.price * item.quantity }} Coins</td>
</tr>
</table>
</div>
</div>
<!-- Shop -->
<div class="row">
<div class="col-md-3" v-for="product in products" :key="product.id" >
<div class="card" >
<div class="card-body">
<div class="product">
<img :src="product.productImage" alt="Product Img">
<h4 class="text-info">{{ product.productName }}</h4>
<h4 class="text-muted">{{ product.price }} Coins</h4>
<p class="text-muted">{{ product.productDescription }}</p>
<input type="number" name="quantity" class="form-control" value="1">
<input type="hidden" name="productName" value="{{productID}}">
<input type="hidden" name="price" value="{{productID.price}}">
<input type="submit" name="add_to_cart" #click="addToCart" class="btn btn-primary btn-block fa-lg gradient-custom-2 mb-3" value="Add to Cart">
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<script>
var app = new Vue({
el: '#app',
data: {
products: '',
cart: []
},
methods: {
getproducts: function () {
axios.get('http://localhost:8888/DevsDev2022/productAPI/products')
.then(function (response) {
app.products = response.data;
})
.catch(function (error) {
console.log(error);
});
},
addToCart: function (product) {
var cartItem = this.cart.find(item => item.productName === product.productName);
if (cartItem) {
cartItem.quantity++;
} else {
this.cart.push({
productName: product.productName,
price: product.price,
quantity: 1
});
}
},
removeFromCart: function (product) {
var cartItem = this.cart.find(item => item.productName === product.productName);
if (cartItem.quantity > 1) {
cartItem.quantity--;
} else {
this.cart.splice(this.cart.indexOf(cartItem), 1);
}
},
clearCart: function () {
this.cart = [];
}
},
mounted: function () {
this.getproducts();
}
});
</script>
You are missing your template tag around your template
Please take a look at following snippet:
new Vue({
el: '#app',
data() {
return {
products: [{id: 1, productName: 'aaa', price: 25, productDescription: 'rrrrrrr'}, {id: 2, productName: 'bbb', price: 35, productDescription: 'eeeee'}],
cart: []
}
},
methods: {
getproducts() {
/*axios.get('http://localhost:8888/DevsDev2022/productAPI/products')
.then(function (response) {
app.products = response.data;
})
.catch(function (error) {
console.log(error);
});*/
},
addToCart(product) {
var cartItem = this.cart.find(item => item.productName === product.productName);
if (cartItem) {
cartItem.quantity++;
} else {
this.cart.push({
productName: product.productName,
price: product.price,
quantity: 1
});
}
},
removeFromCart(product) {
var cartItem = this.cart.find(item => item.productName === product.productName);
if (cartItem.quantity > 1) {
cartItem.quantity--;
} else {
this.cart.splice(this.cart.indexOf(cartItem), 1);
}
},
clearCart() {
this.cart = [];
}
},
mounted: function () {
this.getproducts();
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<section>
<div class ="container" >
<div class="row">
<div class="col-md-12" >
<div class="card">
<div class="card-body">
<!-- Cart -->
<table>
<tr>
<th>Product</th>
<th>Price</th>
<th>Quantity</th>
<th>Total</th>
</tr>
<tr v-for="(product, index) in cart">
<td>{{ product.productName }}</td>
<td>{{ product.price }}</td>
<td>{{ product.quantity }}</td>
<td>{{ product.price * product.quantity }} Coins</td>
</tr>
</table>
</div>
</div>
<!-- Shop -->
<div class="row">
<div class="col-md-3" v-for="product in products" :key="product.id" >
<div class="card" >
<div class="card-body">
<div class="product">
<img :src="product.productImage" alt="Product Img">
<h4 class="text-info">{{ product.productName }}</h4>
<h4 class="text-muted">{{ product.price }} Coins</h4>
<p class="text-muted">{{ product.productDescription }}</p>
<input type="number" name="quantity" class="form-control" value="1">
<input type="hidden" name="productName" :value="product.name">
<input type="hidden" name="price" :value="product.price">
<input type="submit" name="add_to_cart" #click="addToCart(product)" class="btn btn-primary btn-block fa-lg gradient-custom-2 mb-3" value="Add to Cart">
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
</div>

Array of objects with a particular styling in vue

new Vue({
el: '#app1',
data: {
objects:[
{
object: {
title: 'C',
author: 'Denis',
publishedAt: '1960'
}
},
{
object: {
title: 'Vue',
author: 'Yet To Find',
publishedAt: '2010'
}
}]}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.0/vue.js"></script>
<div id="app1">
<ol>
<div v-for="object in objects">
{{index}}
<li v-for="value in object">
{{value}}
</li>
</div>
</ol>
</div>
new Vue({
el: '#app1',
data: {
objects:[
{
title: 'C',
author: 'Denis',
publishedAt: '1960'
},
{
title: 'Vue',
author: 'Yet To Find',
publishedAt: '2010'
}]}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.0/vue.js"></script>
<div id="app1">
<ol>
<div v-for="object in objects">
{{index}}
<li v-for="value in object">
{{value}}
</li>
</div>
</ol>
</div>
I am able to achieve these two variations. But I am trying to achieve the below
1.
.C
.Denis
.1960
2.
.
.
.
How can I do it from what I have? I am trying to express bullet/number by Dot(.).
new Vue({
el: '#app',
data: {
objects: [{
title: 'C',
author: 'Denis',
publishedAt: '1960'
},
{
title: 'Vue',
author: 'Yet To Find',
publishedAt: '2010'
}
]
}
})
/*ignore - hide snippets console */
.as-console-wrapper {
max-height: 0px !important;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.0/vue.js"></script>
<div id="app">
<ul>
<div v-for="(object, index) in objects">
{{ index + 1 }}
<li v-for="(value, key, index) in object" style="list-style-type:none">
{{ index + 1 }}. {{ key }} = {{ value }}
</li>
</div>
</ul>
</div>
Maybe so...
<ul v-for="(object,index) in objects"
:key="index">
{{index +1}}
<li v-for="(prop, index) in object" :key="index">
{{prop.author}}
{{prop.title}}
{{prop.publishedAt}}
</li>
</ul>

Vue JS passing variable names and using them

I am trying to build a fairly simple program but maybe I am not really understanding how vue does things.
I need to add inventory to the top and than use it in any of the two options. So when I press + for clearance it removes from Inventory and when I press - it add to inventory until 0.
This works if I create only one with static variables, but since there will be more location I am trying to pass this ID of the location via on-click. I used words but there will be ID in the end. The issue is that I cant get them to work once I pass them. When I console log them I can see them but they still dont work. What am I missing here?
<tr>
<td>New</td>
<td>
<div class="row">
<div class="col">
<h1>#{{ inventory }}</h1>
</div>
<div class="col">
<button type="button" class="btn btn-danger" v-on:click.prevent="addInventory($event, 'inventory')">+</button>
</div>
</div>
</tr>
<tr>
<td>Floor Model</td>
<td>
<div class="row">
<div class="col">
<button type="button" class="btn btn-success" v-on:click.prevent="removeInventory($event, 'floor')">-</button>
</div>
<div class="col">
<h1>#{{ floor }}</h1>
</div>
<div class="col">
<button type="button" class="btn btn-danger" v-on:click.prevent="addInventory($event, 'floor')">+</button>
</div>
</div>
</td>
</tr>
<tr>
<td>Clearance</td>
<td>
<div class="row">
<div class="col">
<button type="button" class="btn btn-success" v-on:click.prevent="removeInventory($event, 'clearance')">-</button>
</div>
<div class="col">
<h1>#{{ clearance }}</h1>
</div>
<div class="col">
<button type="button" class="btn btn-danger" v-on:click.prevent="addInventory($event, 'clearance')">+</button>
</div>
</div>
</td>
</tr>
</tbody>
The Vue Code
<script>
var app = new Vue({
el: '#app',
data: {
inventory: 4,
clearance: 1,
floor: 0,
},
methods: {
addInventory: function (event, id){
if(this.inventory > 0){
this.id++ ;
this.inventory-- ;
console.log(id);
}
},
removeInventory: function (event, id){
if(this.id > 0){
this.id-- ;
this.inventory++ ;
console.log(id);
}
},
}
})
</script>
Thank you
Data must be returned as an object to avoid all components referring to the same data property.
data: () => ({
//properties here
})
or
data: () => {
return {
//properties here
}
}
For setting those values dynamically and avoiding a bunch of methods, look at this example:
https://codepen.io/arcaster42/pen/PooVYVE
Your data field should be a function that returns an object. This solves the problem of all copies of this component accessing the same data:
data() {
return {
inventory: 4,
clearance: 1,
floor: 0,
}
}
Edit: forgot return statement
First there is no point trying to use a single method, You can create multiple which handle it. If you want to use a single method you could but you would be using keys to find which one was selected.
You can also disable the button when a value is at 0, so you wont have to do any if statements inside of that method.
I'm not entirely sure if below is what you are after but it will give you a heads up.
<tbody>
<tr>
<td>New</td>
<td>
<div class="row">
<div class="col">
<h1>#{{ inventory }}</h1>
</div>
<div class="col">
<button
type="button"
class="btn btn-danger"
v-on:click.prevent="addInventory"
>
+
</button>
</div>
</div>
</td>
</tr>
<tr>
<td>Floor Model</td>
<td>
<div class="row">
<div class="col">
<button
type="button"
class="btn btn-success"
:disabled="floor <= 0"
v-on:click.prevent="removeFloorStock"
>
-
</button>
</div>
<div class="col">
<h1>#{{ floor }}</h1>
</div>
<div class="col">
<button
type="button"
class="btn btn-danger"
v-on:click.prevent="addFloorStock"
>
+
</button>
</div>
</div>
</td>
</tr>
<tr>
<td>Clearance</td>
<td>
<div class="row">
<div class="col">
<button
type="button"
class="btn btn-success"
:disabled="clearance <= 0"
v-on:click.prevent="removeClearanceStock"
>
-
</button>
</div>
<div class="col">
<h1>#{{ clearance }}</h1>
</div>
<div class="col">
<button
type="button"
class="btn btn-danger"
v-on:click.prevent="addClearanceStock"
>
+
</button>
</div>
</div>
</td>
</tr>
</tbody>
<script>
var app = new Vue({
el: '#app',
data: {
inventory: 4,
clearance: 1,
floor: 0,
},
methods: {
addFlorStock() {
this.floor = this.floor++;
},
removeFloorStock() {
this.floor = this.floor--;
},
addClearanceStock() {
this.clearance = this.clearance++;
},
removeClearanceStock() {
this.clearance = this.clearance--;
},
addInventory() {
this.inventory = this.inventory++;
},
removeInventory() {
this.inventory = this.inventory--;
},
}
})
</script>
Ok here is the answer I was looking for if anybody else needs it.
In short I wanted the code to work for any number of items in the array.
InventoryTotal is an array like this.
[
{
"id": 16,
"product_id": 504,
"location_id": 1,
"stock": 22,
"status_id": 1,
"created_at": "2019-12-02 00:00:00",
"updated_at": "2019-12-02 00:00:00",
"status": {
"id": 1,
"name": "New Stock"
}
},
{
"id": 17,
"product_id": 504,
"location_id": 2,
"stock": 3,
"status_id": 2,
"created_at": "2019-12-02 00:00:00",
"updated_at": "2019-12-02 00:00:00",
"status": {
"id": 2,
"name": "Clearance"
}
}
]
<td v-text="location.status.name"></td>
<td>
<div class="row">
<div class="col">
<button type="button" v-if="location.status.name != 'New Stock'" class="btn btn-warning" v-on:click.prevent="removeInventory(location.status.name , index , location.stock)">-</button>
</div>
<div class="col">
<h1 v-text="location.stock"></h1>
</div>
<div class="col">
<button type="button" v-if="location.status.name != 'New Stock'" class="btn btn-danger" v-on:click.prevent="addInventory(location.status.name , index , location.stock)">+</button>
</div>
</div>
</tr>
Script
var vm = new Vue({
el: '#app',
data() {
return {
inventoryTotal: '',
}
},
methods: {
addInventory: function (name ,index, item){
if(0 == index){
this.inventoryTotal[0].stock++ ;
}else if(this.inventoryTotal[0].stock > 0){
this.inventoryTotal[0].stock-- ;
this.inventoryTotal[index].stock++ ;
}
},
removeInventory: function (name, index, item){
if(0 == index && this.inventoryTotal[0].stock > 0){
this.inventoryTotal[0].stock-- ;
}else if(this.inventoryTotal[index].stock != 0){
this.inventoryTotal[index].stock-- ;
this.inventoryTotal[0].stock++ ;
}
},
}
})

Pagiantion with server table is not working on vue js

I am creating a table using a ServerTable from 'vue-tables-2' to render a the data with axios and create a pagination, but the problem in the pagination the table show all the records together in the first page
I tried to fixe it but i didn't find any solution
Here you can find the component that i am using to create that table and the pagination
<template>
<div class="mt-5">
<div class="card-header purple-background bord-top-lr-5">
<h4 class="title-align font-montserrat text-light white-text-color">
{{ items.count + ' results found' }}
</h4>
</div>
<div class="card-body white-bg">
<div class="grid-x grid-padding-x m-2 border-0">
<div class="border-0 mb-2">
<v-server-table
url="/companies/search"
:columns="columns"
:options="options"
class="table-header"
>
<div slot="company_name" class="m-3" slot-scope="props">
<h5 class="title-align font-montserrat" style="color: #5b2557">
<a :href="props.row.url" :title="props.row.name">
{{ props.row.name }}
</a>
({{ $t('labels.frontend.companies.demontage') }})
</h5>
<div class="row">
<div class="col">
<p
class="gray-text-color font-montserrat-thin font-weight-bold"
>
{{ props.row.address.street }}
{{ props.row.address.building_nr }},
{{ props.row.address.postal }},
{{ props.row.address.city }}, {{ props.row.address.state }},
{{ props.row.address.country }}
</p>
</div>
<div class="col ml-lg-5">
<p
class="font-montserrat-thin blue-light-color font-weight-bold"
>
T. {{ props.row.address.phone }}<br />
<a
:href="props.row.website"
target="_blank"
:title="props.row.name"
class="gray-text-color"
>
{{ $t('labels.frontend.companies.goTo') }}
</a>
</p>
</div>
<div class="col ml-lg-5">
<a
class="font-montserrat-regular"
href="#"
style="color: #74aee0"
>
{{ $t('labels.frontend.companies.moreInfo') }} ยป
</a>
</div>
</div>
<button
class="mb-3 blue-light-bg btn bord-rad-5 white-text-color font-montserrat-regular"
href="#"
>
{{ $t('labels.frontend.companies.stock') }}
</button>
<br />
</div>
</v-server-table>
</div>
</div>
</div>
</div>
</template>
<script>
import Vue from 'vue'
import { ServerTable } from 'vue-tables-2'
Vue.use(ServerTable, {}, false, 'bootstrap4', 'default')
export default {
name: 'SearchCompaniesTable',
props: {
companyName: {
type: String,
required: false,
default: () => ''
}
},
data() {
return {
total: 0,
items: [],
columns: ['company_name'],
options: {
headings: {
remote_id: 'Document'
},
highlightMatches: true,
pagination: {
chunk: 10,
edge: true,
dropdown: false,
nav: 'fixed'
},
perPage: 10,
perPageValues: [10],
preserveState: true,
sortable: ['company_name'],
filterable: ['company_name'],
skin: 'table-bordered table-hover'
},
page: 1
}
},
computed: {
rows() {
return Object.keys(this.items).length
}
},
mounted() {
axios.get('/companies/search').then(response => {
this.items = response.data
})
}
}
Could you please check what mistake did i make?

Selecting a single row is Selecting all other rows in Vue.js

I am calculating estimated cost. Selecting a product fetch the details about the product and showing it's description and price on the input box. And then upon clicking in add button a new row will appear for another selection. But the problem is the new row appears with the older row data. And changing a single row affects all other rows. Here is my code so far:
<tbody v-for="row in rows" :key="index">
<tr>
<td>
<select #change="selected" v-model="product_id" class="form-control" name="product_id" id="product_id">
<option value="">Select Product</option>
<option v-for="item in items" :value="item.id" v-text="item.product_name"></option>
</select>
</td>
<td>
<textarea type="text" v-model="product.product_details" name="product_details" id="product_details" class="form-control" rows="1" placeholder="Product Details"></textarea>
</td>
<td>
<input v-model.number="product.product_sellPrice" type="number" step="any" class="form-control" name="rate" id="rate" placeholder="Rate">
</td>
<td>
<input v-model.number="product.product_tax" type="number" step="any" class="form-control" name="tax" id="tax" placeholder="Tax">
</td>
<td>
<input v-model="quantity" type="number" class="form-control" name="quantity" id="quantity" placeholder="Quantity">
</td>
<td>
<input :value="total" type="number" step="any" class="form-control" name="total" id="total" placeholder="Total Price">
</td>
<td>
<button class="btn btn-secondary" v-on:click="addrow" >
<i class="fa fa-plus" aria-hidden="true"></i>
</button>
<button v-show="length > 1" class="btn btn-secondary" #click.prevent="removerow(index)">
<i class="fa fa-minus" aria-hidden="true"></i>
</button>
</td>
</tr>
</tbody>
Vue Part
<script>
export default{
props: ['products'],
data() {
return {
rows: [{
}],
items: this.products,
product: '',
product_id: '',
quantity: '',
index: '',
total_price: '',
}
},
methods: {
addrow: function (event) {
event.preventDefault();
this.rows.push({
});
},
removerow: function (index) {
this.rows.splice(index, 1);
},
selected(e){
var id = this.product_id;
console.log(id);
axios.get('/estimate/product/' + id)
.then((response)=>{
this.product = '';
this.product = response.data;
})
.catch((error) => {
console.log(error);
});
},
}
}
</script>
Where am I doing wrong?
key should be a unique identifier for each row. You have index defined in the data object and you use it for all the rows as key, that causes problems.
Also it is not recommended to use the row index as a key since it changes when you add/remove rows.
So you need to add some identifier to each row item and use it as the key, here is a simple example of how to do it:
<div id="vue-instance">
<ul>
<li v-for="(index,item) in inventory" :key="item.name">
{{ item.name }} - ${{ item.price }}
<button #click="add">Add</button>
<button #click="remove(index)">Remove</button>
</li>
</ul>
</div>
var vm = new Vue({
el: '#vue-instance',
data: {
counter: 1,
inventory: [{
name: 'MacBook Air',
price: 1000
}, {
name: 'MacBook Pro',
price: 1800
}, {
name: 'Lenovo W530',
price: 1400
}, {
name: 'Acer Aspire One',
price: 300
}]
},
methods: {
add: function() {
this.inventory.push({
name: 'item' + this.counter++,
price: this.counter * 1000
})
},
remove: function(index) {
this.inventory.splice(index, 1);
}
}
});
https://jsfiddle.net/1rancd5g/