Call method other component in vue - laravel-5

How to call method other component in Vue?
I have component HeaderSearch
<template>
<form action="">
<div class="form-group">
<div class="input-group">
<span class="input-group-btn">
<button class="btn" type="button">
<i class="fa fa-search"></i>
</button>
</span>
<input type="text" #keyup="search(keyword)" v-model="keyword" class="form-control" placeholder="Search...">
</div>
</div>
</form>
</template>
<script>
export default {
data(){
return { keyword: "" };
},
methods: {
search: function(keyword){
if(keyword == ''){
// Want call method fetchPost in PostHome component here
}else{
}
}
}
}
</script>
And I have component PostHome
<template>
<div>
<div class="box r_8 box_shadow" v-for="post in posts">
<div class="box_header">
<a :href="post.url">
<h3 class="mg_bottom_10" v-text="post.title"></h3>
</a>
<small v-text="post.description"></small>
<a :href="post.url" class="box_header_readmore">Read more</a>
</div>
<div class="box_body">
<a :href="post.url" v-show="post.thumbnail">
<img :src="post.thumbnail" class="img_responsive" style="min-height: 300px;background-color: #f1f1f1;
">
</a>
</div>
<div class="box_footer" v-show="post.tags.length > 0">
<ul>
<li v-for="tag in post.tags">
<a v-text="tag.name" href="javascript:void(0)"></a>
</li>
</ul>
</div>
</div>
</div>
</template>
<script>
export default {
data(){
return {
posts: null,
}
},
methods: {
fetchPosts: function(){
var url = base_url + '/user/posts'
this.$http.get(url).then(res => {
this.posts = res.data;
});
}
},
created: function(){
this.fetchPosts();
}
}
</script>
I want when user type keyup to search then if
keyword == ''
call method fetchPost method in PostHome component

You can use Mixins if that method is reusable.
Reference: https://v2.vuejs.org/v2/guide/mixins.html

Related

Laravel Ajax Add To Cart Not working 500 internal error

I have code I am working on. I will list the page, the route, and the controller code. When I inspect and click on the add to cart button I get 500 internal server error and I cannot figure out what I did. It should be giving a message checking to see if the item is already in the cart and if not send a message saying item is in the cart but I can't get past the 500 internal server error.
Page
#extends('layouts.frontend.frontend')
#section('title')
Distinctly Mine - {{$products->name}}
#endsection
#section('content')
<div class="py-3 mb-4 shadow-sm babyblue border-top">
<div class="container">
<h6 class="mb-0">Collections / {{$products->category->name}} / {{$products->name}}</h6>
</div>
</div>
<div class="container">
<div class="card-shadow shadow-sm product_data">
<div class="card-body">
<div class="row">
<div class="col-md-4 border-right">
<div class="img-hover-zoom img-hover-zoom--xyz card-img-top">
<img src="{{ asset('backend/uploads/products/'.$products->image) }}" class="w-100 h-100" alt="{{$products->name}}">
</div>
</div>
<div class="col-md-8">
<h2 class="mb-0">{{ $products->name}}</h2>
<hr>
<label for="" class="me-3">Price: ${{$products->original_price}}</label>
<p class="mt-3">{!! $products->small_description !!}</p>
<hr>
#if($products->qty > 0)
<label for="" class="badge bg-success text-dark fw-bold">In Stock</label>
#else
<label for="" class="badge bg-danger text dark fw-bold">Out of Stock</label>
#endif
<div class="row mt-2">
<div class="col-md-2">
<input type="hidden" value="{{$products->id}}" class="prod_id">
<label for="Quantity">Quantity</label>
<div class="input-group text-center mb-3" style="width:130px">
<button type="button" class="input-group-text decrement-btn">-</button>
<input type="text" name="quantity" value="1" class="form-control qty-input" />
<button type="button" class="input-group-text increment-btn">+</button>
</div>
</div>
<div class="col-md-10">
<br />
<button type="button" class="btn btn-warning text-dark fw-bold ms-3 float-start"><i class=" me-1 fa fa-heart text-danger me-1"></i>Add To Wishlist</button>
<button type="button" class="btn btn-success ms-3 float-start text-dark fw-bold addToCartBtn"><i class="me-1 fa fa-shopping-cart text-dark me-1"></i>Add to Cart</button>
</div>
<hr>
<h2>Description</h2>
{{$products->description}}
</div>
</div>
</div>
</div>
</div>
</div>
#endsection
#section('scripts')
<script>
$(document).ready(function (){
$('.addToCartBtn').click(function (e){
e.preventDefault();
var product_id = $(this).closest('.product_data').find('.prod_id').val();
var product_qty = $(this).closest('.product_data').find('.qty-input').val();
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$.ajax({
method: "POST",
url: "/add-to-cart",
data: {
'product_id': product_id,
'product_qty': product_qty,
},
dataType: "dataType",
success: function (response){
alert(response.status);
}
});
});
$('.increment-btn').click(function (e){
e.preventDefault();
var inc_value = $('.qty-input').val();
var value = parseInt(inc_value,10);
value = isNaN(value) ? 0 :value;
if(value < 10)
{
value++;
$('.qty-input').val(value);
}
});
$('.decrement-btn').click(function (e){
e.preventDefault();
var dec_value = $('.qty-input').val();
var value = parseInt(dec_value,10);
value = isNaN(value) ? 0 :value;
if(value > 1)
{
value--;
$('.qty-input').val(value);
}
});
});
</script>
#endsection
Route
Route::middleware(['auth'])->group(function (){
Route::post('/add-to-cart',[CartController::class,'addProduct']);
});
Controller
<?php
namespace App\Http\Controllers\Frontend;
use App\Models\Product;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;
class CartController extends Controller
{
public function addProduct(Request $request)
{
$product_id = $request->input('product_id');
$product_qty = $request->input('product_qty');
if(Auth::check())
{
$prod_check = Product::where('id',$product_id)->first();
if($prod_check)
{
if(Cart::where('prod_id',$product_id)->where('user_id',Auth::id())->exists())
{
return response()->json(['status' => $prod_check->name." Already Added to cart"]);
}else{
$cartItem = new Cart();
$cartItem->prod_id = $product_id;
$cartItem->user_id = Auth::id();
$cartItem->prod_qty = $product_qty;
$cartItem->save();
return response()->json(['status'=>$prod_check->name." Added to cart"]);
}
}
}
else{
return response()->json(['status'=> "Login To Continue"]);
}
}
}

Expand Collapse Icons with Vue Js and Bootstrap

I have a Bootstrap accordion with the expand collapse panels,which works fine.
But when expanded it should display minus icon which is not working well for me.
When I click to expand all the panel's icons are changed to minus instead of just changing the one which was expanded.
I have my code in the Vue JS template as below
Am calling the toggle function onclick to toggle the icons, but its doing it for all the other panels too.
How can I fix this? Thanks in advance.
Vue.component('accordion', {
data: function () {
return {
alerts: [],
sound: '',
collapsed:true
}
},
template: `
<div>
<div v-for="(alert, index ) in alerts" class="panel panel-default">
<div class="panel-heading" v-bind:style="'background-color:'+alert.color" role="tab" v-bind:id="'heading'+index" >
<a role="button" data-toggle="collapse" data-parent="#accordion"
v-bind:href="'#collapse'+index" aria-expanded="true" v-on:click="toggle">
<i id="collapseExpand" v-show="collapsed" class="more-less fa fa-plus"></i>
<i id="collapseExpand" v-show="!collapsed" class="more-less fa fa-minus"></i>
<h4 class="panel-title">#{{ alert.description }}</h4></a>
</div>
<div v-bind:id="'collapse'+index" class="panel-collapse collapse" role="tabpanel">
<div class="panel-body">
<div>#{{ alert.comment }}</div>
<div class="row">
<form v-bind:id="'form_'+index" v-bind:name="'form_'+index" v-bind:action="route" method="POST" style="display: inline;">
<input type="hidden" name="_token" :value="csrf">
<input type ="hidden" v-bind:id="'trigger_id_'+alert.triggerid" name = "trigger_id" v-bind:value="alert.triggerid">
<div class="col-lg-12">
<div class="input-group">
<input type="text" v-bind:id="'ack_msg_'+alert.triggerid" name="ack_msg" class="form-control"
placeholder="Acknowledge Message...">
<span class="input-group-btn">
<button class="btn btn-primary" type="submit">Save</button>
</span>
</div>
</div>
</form>
</div>
</div>
<div class="panel-footer">#{{ alert.timestamp }}</div>
</div>
</div>
<input type="hidden" id="audioFile" name="audioFile" v-bind:value="sound">
</div>`,
mounted: function () {
this.loadData();
setInterval(function () {
this.loadData();
}.bind(this), 1000);
},
methods: {
loadData: function () {
$.get('{{ route('getAlertsPersistent') }}', function (response) {
this.alerts = response;
this.sound = this.alerts[0].sound
}.bind(this));
},
toggle(){
this.collapsed = !this.collapsed ;
}
},
});
new Vue({el: '#accordion'});
You want to separate your accordion item that you want to loop. In that way you can have isolated states in each component.
<div>
<accordion-item
v-for="(alert, index) in alerts"
:alert="alert"
:key="index">
</accordion-item>
</div>
inside your <accordion-item/> you should have collapsed inside your data
The other way around is storing the toggled items in array.
export default {
data: () => ({
toggled: []
}),
methods: {
isActive (item) {
return this.toggled.indexOf(item) >= 0
},
toggleItem (item) {
const index = this.toggled.indexOf(item)
if (index >= 0) {
this.toggled.splice(index, 1)
return
}
this.toggled.push(item)
}
}
}
So you can use it now as follows
<a
role="button"
data-toggle="collapse"
data-parent="#accordion"
v-bind:href="'#collapse'+index"
aria-expanded="true"
v-on:click="toggleItem(index)">
<i
:class="[isActive(index) ? 'fa-minus' : 'fa-plus']"
class="more-less fa"></i>
<h4 class="panel-title">#{{ alert.description }}</h4>
</a>
btw you're looping an id=collapseExpand which will cause you problem. instead try :id="'collapseExpand' + index"

Laravel/VueJs. How can I display button with different color based on column value passed in?

I'm looping through user table. And each user table has a button that toggle(update:Boolean type) user status on user table. And I want the button for each user to have red color when the status value for the user is 0 and green when the status is 1. Also I want the button to change the color(LIVE) based on the status value each time it clicked.
component: ToggleStatus.vue
<template>
<div>
<button type="button" v-bind:class="buttonStatus" #click="goOnline">
<span class="ion-ios-wifi" ></span>
</button>
</div>
</template>
<script>
export default {
props: ['userId', 'onlinestat'],
mounted() {
console.log('Component mounted.')
},
data: function() {
return {
status: this.onlinestat,
}
},
methods: {
goOnline() {
axios.post('/reservation/online/' + this.userId )
.then(response => {
this.status =! this.status;
console.log(response.data);
})
.catch(errors => {
if (errors.response.status == 401){
window.location = '/login';
}
});
}
},
computed: {
buttonStatus() {
return(this.status) ? 'btn btn-outline-danger text-danger' : 'btn btn-success ';
}
}
}
</script>
Controller:
$authUser = Auth::user()->business_id;
$employee = User::where('business_id', $authUser)->get()->sortBy('name');
return view('backend.reservation.index', compact('employee'));
View/Blade
<div class="container-fluid flex-grow-1 container-p-y">
<div class="uikit-example">
<div class="row">
#foreach ($employee as $key => $emp)
<div class="col-lg-4 col-md-4 col-sm-12">
<div class="card mb-4">
<div class="card-body">
<div class="media align-items-center">
<img src="{{ asset('Upload/Images/Media/Avatar/Thumb/'.$emp->image) }}" alt class="ui-w-60 rounded-circle">
<div class="media-body pt-2 ml-3">
<h5 class="mb-2">{{ $emp->name }}</h5>
<div class="text-muted small mb-2">{{ $emp->phone }}</div>
<div class="text-muted small mb-2">{{ $emp->email }}</div>
<div class="text-muted small mb-2"><span>ID: </span>{{ $emp->user_code }}</div>
</div>
<div class="">
<toggleonline user-id="{{ $emp->id }}" onlinestat="{{ $emp->onlinestatus }}"></toggleonline>
</div>
</div>
</div>
<div class="card-footer text-center py-3">
{{-- + Go Online --}}
{{-- <span class="ion ion-md-mail"></span> --}}
{{-- <div class="float-right"> --}}
My Reservations
{{-- </div> --}}
</div>
</div>
</div>
#endforeach
</div>
</div>
</div>
The result I'm getting is that the button does toggle but the toggle button of all the user come red after on refresh page or when the page loads.
try
buttonStatus() {
return(this.status==0) ? 'btn btn-outline-danger text-danger' : 'btn btn-success ';
}

Vue2 trigger render on an independent component over vuex

Inside of a Laravel app I have two independent vue components and I would like to trigger a re-render on the second component.
I use vuex where I already trigger a store mutation and I can see that the data is updated but the component will not re-render.
export default {
store: store,
. //code logic
.
.
methods: {
store: {
//axios async request where on success I trigger store mutation
self.$store.dispatch('getApprovals', 'testing/approvals'); //I can see in console the store request response
}
}
}
than the second component which should re-render
<template>
<div class="portlet light">
<div class="portlet-title tabbable-line">
<div class="caption">
<i class="icon-social-twitter font-dark hide"></i>
<span class="caption-subject bold uppercase">Approvals</span>
</div>
<div class="caption" style="float: right;">
</div>
<ul class="nav nav-tabs">
<li class="active">
Pending
</li>
</li>
</ul>
</div>
<div class="portlet-body">
<div class="tab-content">
<div class="tab-pane active" id="tab_actions_pending">
<div class="mt-actions">
<div class="mt-action" v-for="approval in $store.state.approvals.approvals"
v-show="approval.status === 'pending'">
<div class="mt-action-body">
<div class="mt-action-row">
<div class="mt-action-info ">
<div class="mt-action-icon ">
<i class="icon-magnet"></i>
</div>
<div class="mt-action-details ">
<span class="mt-action-author"
v-show="approval.request_type == 'Timeoff Request'">{{ approval.request_type }} - {{ approval.type }}</span>
<span class="mt-action-author"
v-show="approval.request_type !== 'Timeoff Request'">{{ approval.request_type }} </span>
<p class="mt-action-desc"
v-show="approval.request_type == 'Timeoff Request'">{{
parseFloat(approval.days).toFixed(1) }} day/s requested</p>
<p class="mt-action-desc"
v-show="approval.request_type == 'Timeoff Request'">{{ approval.from}} -
{{ approval.to}}</p>
</div>
</div>
<div class="mt-action-datetime ">
</div>
<div class="mt-action-buttons ">
<span class="label label-warning"> Pending </span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import store from './store';
import {editItem} from './actions';
export default {
vuex: {
getters: {
getApprovals: state => {
return state.approvals
}
}
},
store: store,
created() {
this.$store.dispatch('getApprovals', 'testing/approvals');
},
data() {
return {
approvals: {},
alert: {
show: false,
type: null,
title: null,
message: null,
}
};
}
}
</script>
How do we deal with this cases?

laravel 5.4/ vue js dont iterate my array

Hello I want to make a loop to iterate an array of data retrieve from a controller but I have an error message in vue js I can not find where is my error help me please I start with a vue js
here is my code
controller.php
public function index(){
$post= Posts::with('likes','comments', 'user')->orderBy('created_at','DESC')->get();
return $post ;
}
vue.js
const root = new Vue({
el: '#root',
data: {
msg: 'Update New Post:',
content: '',
posts: []
},
ready: function ready() {
this.created();
},
created: function created() {
var _this = this;
axios.get('http://localhost:8000/mur/posts')
.then(response => {
_this.posts = response.data;
//we are putting data into our posts array
console.log(response.data);
// show if success
Vue.filter('myOwnTime', function(value){
return moment(value).fromNow();
});
})
.catch(function (error) {
console.log(error); // run if we have error
});
}
},
view
<div v-for="post, key in posts">
<div class="col-md-12 col-sm-12 col-xs-12 all_posts">
<div class="col-md-1 pull-left">
<img :src="'{{asset('storage/avatar')}}/' + post.avatar"
style="width:50px;">
</div>
<div class="col-md-10" style="margin-left:10px">
<div class="row">
<div class="col-md-11">
<p><a :href="'{{url('profile')}}/' + post.slug" class="user_name"> #{{post.user.name}}</a> <br>
<span style="color:#AAADB3"> #{{ post.created_at }}
<i class="fa fa-globe"></i></span></p>
</div>
<div class="col-md-1 pull-right">
#if(Auth::check())
<!-- delete button goes here -->
<a href="#" data-toggle="dropdown" aria-haspopup="true">
{{--<img src="{{Config::get('app.url')}}/public/img/settings.png" width="20">--}}
</a>
<div class="dropdown-menu">
<li><a>some action here</a></li>
<li><a>some more action</a></li>
<div class="dropdown-divider"></div>
<li v-if="post.user_id == '{{Auth::user()->id}}'">
<a #click="deletePost(post.id)">
<i class="fa fa-trash"></i> Delete </a>
</li>
</div>
#endif
</div>
</div>
</div>
<p class="col-md-12" style="color:#000; margin-top:15px; font-family:inherit" >
#{{post.content}}
</p>
<div style="padding:10px; border-top:1px solid #ddd" class="col-md-12">
<!-- like button goes here -->
#if(Auth::check())
<div v-for="">
<div v-if="">
<p class="likeBtn" #click="likePost(post.id)">
<i class="fa fa-heart-o"></i>
</p>
</div>
</div>
data : #{{ post.likes.length }}
#endif
</div>
</div>
</div>
web.php
Route::get('mur/posts', 'PostController#index');
posts [ ] return this
[{"id":8,
"user_id":3,
"content":"content 1",
"status":0,
"created_at":"2017-12-27 22:43:20",
"updated_at":"2017-12-27 22:43:20",
"likes":[{"id":2,"posts_id":7,"user_id":3,"created_at":"2017-12-27 16:38:33","updated_at":null}],
"comments":[],
"user":{
"id":3,"name":"toto","sulg":"toto","email":"toto#hotmail.fr","avatar":"215563.jpg","is_actif":"activ\u00e9","created_at":"2017-12-06 15:30:42","updated_at":"2017-12-06 17:04:41"}
},
{"id":7,
"user_id":9,
"content":"coucou",
"status":0,
"created_at":"2017-12-27 16:07:01",
"updated_at":"2017-12-27 16:07:01",
"likes":[{"id":2,"posts_id":7,"user_id":4,"created_at":"2017-12-27 16:38:33","updated_at":null}],
"comments":[],
"user":{"id":9,"name":"blop","sulg":"blop","email":"blop#gmail.com","avatar":"logoBee.png","is_actif":"activ\u00e9","created_at":"2017-12-17 14:37:29","updated_at":"2017-12-17 14:37:29"}}
error in console

Resources