Conditional Component variable value increment Vue/Laravel - laravel

[1]so i have a laravel project going on, and i want to increment the value of the variable deliver_later_num, depending on the "deliver_today" present in the same component in the items[] array, which i am outputting in the template file, i cannot figure how to do it, i do not know if i can increment the value on the template side or on the component side. here is the component code:
cartContent = new Vue({
el: '#cartList',
data: {
items: [], //array containing all the items
deliver_later_num: 0, //value to increment
},
methods: {
remove: function (product_id) {
removeProductIfFromCart(product_id);
},
incQuantity: function (product_id){
incCart(product_id)
},
decQuantity: function (product_id){
decCart(product_id)
},
}
})
here is the template file :
<div id="cartList">
<div v-for="item in items" class="items col-xs-12 col-sm-12 col-md-12 col-lg-12 clearfix">
<div class="info-block block-info clearfix" v-cloak>
<div class="square-box pull-left">
<img :src="item.attributes.image" class="productImage" width="100" height="105" alt="">
</div>
<h6 class="product-item_title">#{{ item.name }}</h6>
<p class="product-item_quantity">#{{ item.quantity }} x #{{ item.attributes.friendly_price }}</p>
<ul class="pagination">
<li class="page-item">
<button v-on:click="decQuantity(item.id)" :value="item.id" class="page-link" tabindex="-1">
<i class="fa fa-minus"></i>
</button>
</li>
<li class="page-item">
<button v-on:click="incQuantity(item.id)" :value="item.id" class="page-link" >
<i class="fa fa-plus"></i>
</button>
</li>
<li class="page-item">
<button v-on:click="remove(item.id)" :value="item.id" class="page-link" >
<i class="fa fa-trash"></i>
</button>
</li>
<input hidden class="delivers_today_state" type="text" :value=" item.attributes.delivers_today "> // if this equals 0 i want to increment the deliver_later_num value
</ul>
</div>
</div>
</div>
laravel controller code :
public function add(Request $request){
$item = Items::find($request->id);
$restID=$item->category->restorant->id;
//Check if added item is from the same restorant as previus items in cart
$canAdd = false;
if(Cart::getContent()->isEmpty()){
$canAdd = true;
}else{
$canAdd = true;
foreach (Cart::getContent() as $key => $cartItem) {
if($cartItem->attributes->restorant_id."" != $restID.""){
$canAdd = false;
break;
}
}
}
//TODO - check if cart contains, if so, check if restorant is same as pervious one
// Cart::clear();
if($item && $canAdd){
//are there any extras
$cartItemPrice=$item->price;
$cartItemName=$item->name;
$theElement="";
//Is there a varaint
//variantID
if($request->variantID){
//Get the variant
$variant=Variants::findOrFail($request->variantID);
$cartItemPrice=$variant->price;
$cartItemName=$item->name." ".$variant->optionsList;
//$theElement.=$value." -- ".$item->extras()->findOrFail($value)->name." --> ". $cartItemPrice." ->- ";
}
foreach ($request->extras as $key => $value) {
$cartItemName.="\n+ ".$item->extras()->findOrFail($value)->name;
$cartItemPrice+=$item->extras()->findOrFail($value)->price;
$theElement.=$value." -- ".$item->extras()->findOrFail($value)->name." --> ". $cartItemPrice." ->- ";
}
Cart::add((new \DateTime())->getTimestamp(), $cartItemName, $cartItemPrice, $request->quantity, array('id'=>$item->id,'variant'=>$request->variantID, 'extras'=>$request->extras,'restorant_id'=>$restID,'image'=>$item->icon,'friendly_price'=> Money($cartItemPrice, env('CASHIER_CURRENCY','usd'),true)->format(),'delivers_today' => $item->deliverstoday ));
return response()->json([
'status' => true,
'errMsg' => $theElement
]);
}else{
return response()->json([
'status' => false,
'errMsg' => __("You can't add items from other restaurant!")
]);
//], 401);
}
}
public function getContent(){
//Cart::clear();
return response()->json([
'data' => Cart::getContent(),
'total' => Cart::getSubTotal(),
'status' => true,
'errMsg' => ''
]);
}
link to the items array vue dev tools screenshot
[1]: https://i.stack.imgur.com/smLRV.png
thanks for your precious help and time.

A computed property can be used if the deliver_later_num is only dependent on the presence/absence of deliver_today on elements of items array
cartContent = new Vue({
el: '#cartList',
data: {
items: {}
},
computed: {
deliver_later_num() {
let num = 0;
Object.keys(this.items).forEach(key => {
let item = this.items[key];
Object.keys(item).forEach(k => {
if(k === 'deliver_today' && item[k]) {
num++;
}
});
});
return num;
},
}

Related

Splice doesn't delete any item from array - Angular12

I am trying create a function for deleting specific items from a shopping cart.
It doesn't give any errors, but when I click the button nothing happens. Any idea what might be the problem?
See the codes below about my issue.
service.ts
removeCartItem(product: Product){
this.cartItemList.map((a:any, index:any)=>{
if(product.id=== a.id){
this.cartItemList.splice(index,1);
}
})
cartitem.component.html
<div class="cartitem">
<div class="container">
<div class="row">
<div class="col">
{{ cartItem.name }}
</div>
<div class="col">
<img [src]="cartItem.imageUrl" class="card-img-top" alt="..." />
</div>
<div class="col-5">
{{ cartItem.description }}
</div>
<div class="col">{{ cartItem.price | currency: "EUR" }}</div>
<div class="col">{{ cartItem.qty }}</div>
<div>
<button (click)="removeItem(item)" class="btn btn-primary">
Remove from cart
</button>
</div>
</div>
</div>
</div>
cartitem.component.ts
constructor(public service: MessengerService) { }
ngOnInit(): void {
}
removeItem(item: Product){
this.service.removeCartItem(item);
}
cart.component.ts
cartItems: Product[] = [];
cartTotal = 0;
product: any;
constructor(private msg: MessengerService, public dialog: MatDialog) {}
ngOnInit() {
this.msg.getMsg().subscribe((product: Product) => {
this.addProductToCart(product);
});
}
addProductToCart(product: Product) {
let productExists = false;
for (let i in this.cartItems) {
if (this.cartItems[i].id === product.id) {
this.cartItems[i].qty++;
productExists = true;
break;
}
}
if (!productExists) {
this.cartItems.push({
id: product.id,
name: product.name,
description: product.description,
qty: 1,
price: product.price,
imageUrl: product.imageUrl,
purchased:product.purchased
});
}
this.cartItems.forEach((item) => {
this.cartTotal += item.qty * item.price;
});
}
cart.component.html
<ul *ngIf="cartItems.length > 0" class="list-group">
<li class="list-group-item">
<h3>My Cart</h3>
</li>
<li class="list-group-item" *ngFor="let item of cartItems">
<app-cartitem [cartItem]="item"></app-cartitem>
</li>
<li class="list-group-item">
<span>Total: {{ cartTotal | currency: "EUR" }} </span>
</li>
<li class="list-group-item">
<button
id="btnFinalize"
class="btn btn-primary"
(click)="purchaseDisabled(product)"
>
Finalize purchase
</button>
</li>
</ul>
The problem is that you are trying to splice inside map. Changing to the following will work:
removeCartItem(product: Product){
let indexToRemove: number = -1;
this.cartItemList.map((a:any, index:any)=>{
if(product.id === a.id){
indexToRemove = index;
}
return a;
});
if(indexToRemove !== -1){
this.cartItemList.splice(indexToRemove,1);
}
}
But notice there is no need to use map here. It's a waste of time and memory to copy the entire array again. Just a loop through the array to find the index to remove would be enough:
removeCartItem(product: Product){
let indexToRemove: number = -1;
let index: number = 0;
for(const cardItem of this.cartItemList){
if(product.id === cardItem.id){
indexToRemove = index;
}
index++;
}
if(indexToRemove !== -1){
this.cartItemList.splice(indexToRemove,1);
}
}

I want to show a first category product when i reload my page using laravel?

currently when i click to any category related to product is showing perfectly but i need to show first category product when i reload my page first time Does anyone have an idea please help me thanks.
Controller
public function getproduct(Request $request)
{
$category_id = $request->data;
if ($category_id) {
$product = Product::with('productColorGallary')->whereHas('productCategory', function (Builder $query) use ($category_id) {
$query->where('mf_product_category_id', $category_id);
})->get();
} else {
$product = Product::with('productColorGallary')->get();
}
$data = [
'products' => $product
];
return response()->json($data, 200);
}
jquery script
<script>
$(document).ready(function(){
$('.productcategory').click(function () {
let url = "{{route('products.getproduct')}}";
let path = '{{config('wall_master_furishing.file_url')}}';
axios.get(url, {
params:{
data: $(this).data('id'),
}
}).then((res)=>{
let product =res.data.products;
$('#product').html("");
product.forEach(element => {
console.log(element);
$('#product').append(
`<div class="col-md-4 col-sm-6 col-6">
<div class="wallprodCard">
<div class="prodcardImage">
<img src="${path}${element.product_color_gallary.featured_image}" alt="">
<a class="prodcardFancy" href="${path}${element.product_color_gallary.featured_image}" data-fancybox="images" data-caption="Flooring">
<i class="fa fa-search-plus">
</i>
</a>
</div>
<div class="prodcardDescp">
<a href="{{url('')}}/wallpaper-details">
<h4 class="prodcardtitle">${element.name}
</h4>
</a>
<p class="text">${element.description}
</p>
</div>
</div>
</div>
`);
});
});
});
</script>

Active user does not show in real time chat app

I am following up this guide https://www.codechief.org/article/real-time-chat-app-with-laravel-6-vue-js-and-pusher#gsc.tab=0 to create real-time chat app in Laravel and Vue.
But it does not show list of active user.
Also this span never shows
<span class="text-muted" v-if="activeUser" >{{ activeUser.first_name }}` is typing...</span>
Also, this method does not work properly because in console log it shows undefined is typing...
sendTypingEvent() {
Echo.join('chat')
.whisper('typing', this.user);
console.log(this.user.fist_name + ' is typing now')
}
And it is not actually real time, because I see new messages only if I reload page.
This is Vue component
<template>
<div class="row">
<div class="col-8">
<div class="card card-default">
<div class="card-header">Messages</div>
<div class="card-body p-0">
<ul class="list-unstyled" style="height:300px; overflow-y:scroll" v-chat-scroll>
<li class="p-2" v-for="(message, index) in messages" :key="index" >
<strong>{{ message.user.first_name }}</strong>
{{ message.message }}
</li>
</ul>
</div>
<input
#keydown="sendTypingEvent"
#keyup.enter="sendMessage"
v-model="newMessage"
type="text"
name="message"
placeholder="Enter your message..."
class="form-control">
</div>
<span class="text-muted" v-if="activeUser" >{{ activeUser.first_name }} is typing...</span>
</div>
<div class="col-4">
<div class="card card-default">
<div class="card-header">Active Users</div>
<div class="card-body">
<ul>
<li class="py-2" v-for="(user, index) in users" :key="index">
{{ user.first_name }}
</li>
</ul>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
props:['user'],
data() {
return {
messages: [],
newMessage: '',
users:[],
activeUser: false,
typingTimer: false,
}
},
created() {
this.fetchMessages();
Echo.join('chat')
.here(user => {
this.users = user;
})
.joining(user => {
this.users.push(user);
})
.leaving(user => {
this.users = this.users.filter(u => u.id != user.id);
})
.listen('ChatEvent',(event) => {
this.messages.push(event.chat);
})
.listenForWhisper('typing', user => {
this.activeUser = user;
if(this.typingTimer) {
clearTimeout(this.typingTimer);
}
this.typingTimer = setTimeout(() => {
this.activeUser = false;
}, 1000);
})
},
methods: {
fetchMessages() {
axios.get('messages').then(response => {
this.messages = response.data;
})
},
sendMessage() {
this.messages.push({
user: this.user,
message: this.newMessage
});
axios.post('messages', {message: this.newMessage});
this.newMessage = '';
},
sendTypingEvent() {
Echo.join('chat')
.whisper('typing', this.user);
console.log(this.user.fist_name + ' is typing now')
}
}
}
</script>
"Also, this method does not work properly because in console log it shows undefined is typing..."
i assume you made a typo in your console.log, you probably meant:
this.user.first_name
Concerning your "realtime" problem, i suspect it might be because your broadcasted Event is being queued, so you might want to use the ShouldBroadcastNow instead of ShouldBroadcast

Display content from AJAX request using setState

I'm doing a webapp using github search API. I want the info for each repo to be displayed under the specific repo.
I want the content from the AJAX request to be displayed when the specific button is being pressed. I am using React. Since I'm using item.x to access the information I need to get that item and I assume I need to use map but when doing that it will display all the results and not just the specific repository's. Anyway that I can get the Item since it currently says it's undefined?
let searchTerm;
class SearchBox extends React.Component {
constructor(props) {
super(props);
this.onClick = this.onClick.bind(this);
this.state = { repositories: [],
showInfo: false };
}
render() {
let moreDetail;
if(this.state.showInfo){
moreDetail= <div className="info"> <li>
<p>Open issue count </p>:{item.open_issues_count}
</li>
<li>
<p>Number of forks </p>:{item.forks}
</li>
<li>
<p>Language </p>:{item.language}
</li></div>;
}
return(
<div>
<form>
<input type="text" className="searchbox" ref={(input) => { this.searchBox = input; }}/>
<button onClick={this.onClick}>Search</button>
</form>
<h2>Repositories</h2>
<ul>
{ this.state.repositories.map( ( item, index ) => (
<div key={ index }>
<a href={item.html_url}> <li >
{ item.name }
</li>
</a>
{moreDetail}
<button onClick={this._handleClick.bind(this)}>Detailed view</button>
</div>
)) }
</ul>
</div>
);
}
_handleClick(){
this.setState({
showInfo: !this.state.showInfo
});
}
onClick(event) {
searchTerm = this.searchBox.value;
let endpoint = 'https://api.github.com/search/repositories?sort=stars&order=desc&q=' + searchTerm;
console.log(searchTerm);
fetch(endpoint)
.then(blob => blob.json())
.then(response => {
this.setState({ repositories: response.items });
});
event.preventDefault();
}
}
The problem is with context. When you define the moreDetail variable, you don't have item in your context (only during the map function you have that.)
One option is to use the variable moreDetail as a function that receives the item you want to show.
Your render method should look something like:
render() {
const moreDetail = (item) => ( !this.state.showInfo ? <span /> :
<div className="info">
<li>
<p>Open issue count </p>:{item.open_issues_count}
</li>
<li>
<p>Number of forks </p>:{item.forks}
</li>
<li>
<p>Language </p>:{item.language}
</li>
</div>
);
return (
<div>
<form>
<input type="text" className="searchbox" ref={(input) => { this.searchBox = input; }}/>
<button onClick={this.onClick}>Search</button>
</form>
<h2>Repositories</h2>
<ul>
{ this.state.repositories.map( ( item, index ) => (
<div key={ index }>
<a href={item.html_url}> <li >
{ item.name }
</li>
</a>
{moreDetail(item)}
<button onClick={this._handleClick.bind(this)}>Detailed view</button>
</div>
)) }
</ul>
</div>
);
}

Vue.js sorting is not working when fetching from Laravel

Currently this is for listing customer data from database. Data is fetching using Laravel 5. At present data is fetching and listing properly. This page contains pagination, filter search and sorting functionality. My problem is sorting is not working properly. Could you please help me to sort out this issue? I am using Vue.js version 1.0.25
Here is the short code, only the sorting part
View
<th v-for="key in columns" #click="sortBy(key)" :class="{active: sortKey == key}">
#{{ colTitles[key] }}
</th>
<tr v-for="(index, item) in items | filterBy searchQuery | orderBy sortKey reverse">
........
JS
data: {
sortKey: '',
reverse: false,
.........
sortBy: function(sortKey) {
this.reverse = (this.sortKey == sortKey) ? ! this.reverse : false;
this.sortKey = sortKey;
}
Full code
dashboard.blade.php
<div class="container">
<div class="row">
<h1 class="page-header">{{ trans('messages.customerListPageHeadingLabel') }}</h1>
<div id="app">
<div class="form-group col-md-4">
<form id="search" class="form-inline">
<label for="query">{{ trans('messages.customerListPageSearchBox') }} </label>
<input name="query" class="form-control" v-model="searchQuery">
</form>
</div>
<br>
<table class="table table-hover table-bordered">
<thead>
<tr>
<th v-for="column in columns" #click="sortBy(column)">
#{{ colTitles[column] }}
</th>
</tr>
</thead>
<tbody>
<tr v-for="(index, item) in items | filterBy searchQuery | orderBy sortKey reverse">
<td>#{{ item.erp_id }}</td>
<td>#{{item.firstname}}</td>
<td>#{{item.lastname}}</td>
<td>#{{item.email}}</td>
<td>#{{item.phone_1}}</td>
<td>#{{item.status}}</td>
<td>#{{item.created_on}}</td>
</tr>
</tbody>
</table>
<nav>
<ul class="pagination">
<li v-if="pagination.current_page > 1">
<a href="#" aria-label="Previous"
#click.prevent="changePage(pagination.current_page - 1)">
<span aria-hidden="true">«</span>
</a>
</li>
<li v-for="page in pagesNumber"
v-bind:class="[ page == isActived ? 'active' : '']">
<a href="#"
#click.prevent="changePage(page)">#{{ page }}</a>
</li>
<li v-if="pagination.current_page < pagination.last_page">
<a href="#" aria-label="Next"
#click.prevent="changePage(pagination.current_page + 1)">
<span aria-hidden="true">»</span>
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
Laravel Controller
public function listCustomers()
{
$results = Customer::select('id', 'erp_id', 'firstname', 'lastname', 'email', 'phone_1', 'status', DB::raw("DATE_FORMAT(created_at, '%d.%m.%Y %H:%i') AS created_on"))
->orderBy('id', 'desc')->latest()->paginate(25);
$response = [
'pagination' => [
'total' => $results->total(),
'per_page' => $results->perPage(),
'current_page' => $results->currentPage(),
'last_page' => $results->lastPage(),
'from' => $results->firstItem(),
'to' => $results->lastItem()
],
'data' => $results
];
return $response;
}
Vue JS
new Vue({
el: '#app',
data: {
sortKey: '',
reverse: false,
columns: ['erp_id', 'firstname', 'lastname', 'email', 'phone_1', 'status', 'created_on'],
colTitles: {'erp_id':'#lang('messages.customerListPageTableCustomerNo')', 'firstname':'#lang('messages.customerListPageTableFirstname')', 'lastname':'#lang('messages.customerListPageTableLastname')', 'email':'E-Mail', 'phone_1':'#lang('messages.customerListPageTablePhone')', 'status':'Status', 'created_on':'#lang('messages.customerListPageTableAddedDate')'},
pagination: {
total: 0,
per_page: 7,
from: 1,
to: 0,
current_page: 1
},
offset: 4,// left and right padding from the pagination <span>,just change it to see effects
items: []
},
ready: function () {
this.fetchItems(this.pagination.current_page);
},
computed: {
isActived: function () {
return this.pagination.current_page;
},
pagesNumber: function () {
if (!this.pagination.to) {
return [];
}
var from = this.pagination.current_page - this.offset;
if (from < 1) {
from = 1;
}
var to = from + (this.offset * 2);
if (to >= this.pagination.last_page) {
to = this.pagination.last_page;
}
var pagesArray = [];
while (from <= to) {
pagesArray.push(from);
from++;
}
return pagesArray;
}
},
methods: {
fetchItems: function (page) {
var data = {page: page};
this.$http.get('/list/customers', data).then(function (response) {
//look into the routes file and format your response
this.$set('items', response.data.data.data);
this.$set('pagination', response.data.pagination);
}, function (error) {
// handle error
});
},
changePage: function (page) {
this.pagination.current_page = page;
this.fetchItems(page);
},
sortBy: function(sortKey) {
this.reverse = (this.sortKey == sortKey) ? ! this.reverse : false;
this.sortKey = sortKey;
}
}
});
the last parameter of orderBy should be 1 or -1, while you provide either true or false with the value of reverse
https://jsfiddle.net/Linusborg/spwwxLvy/
change this:
this.reverse = (this.sortKey == sortKey) ? ! this.reverse : false;
to this:
this.reverse = (this.sortKey == sortKey) ? 1 : -1;
also change the initial value in data() accordingly.

Resources