Datatables - Search Box outside datatable (Laravel/Vue .js) - laravel

I am using Datatables in my application (Bookstore created in laravel/vuejs) and I would like my search box to be outside of the table. the problem which I am facing is that the search box is not searching the data until I refresh/reload the page 1 or 2 times.
any kind of help will be highly appreciated.
Javascript code is below
$(document).ready(function() {
var tables = $("#datatable-fixed-header30").DataTable({
paging: false,
dom: "t"
});
// $(".dataTables_filter").hide();
$("#bookSearch").keyup(function() {
tables.search($(this).val()).draw();
});
});
Full Code in the vue page is like below
<template>
<div class="container">
<div class="col-md-12 col-sm-12 col-xs-12" v-for="User1 in Users.data" v-bind:key="User1.id">
<div class="x_panel" v-if="User1.type=='admin'">
<div class="x_content">
<div
id="datatable-buttons_wrapper"
class="dataTables_wrapper form-inline dt-bootstrap no-footer"
>
<div class="dt-buttons btn-group">
<button
class="btn btn-success buttons-copy buttons-html5 btn-sm"
tabindex="0"
aria-controls="datatable-buttons"
#click="newModal"
>ثبت کاربرد جدید</button>
</div>
<!-- /.row -->
<div class="row">
<div class="col-lg-6" style="margin-top:-31px;float:left;margin-left:-213px;">
<div class="input-group">
<span class="input-group-btn">
<button class="btn btn-info btn-flat" type="button">
<i class="fa fa-search"></i>
</button>
</span>
<input type="text" class="form-control" id="bookSearch" placeholder="لټون..." />
</div>
<!-- /input-group -->
</div>
<div class="col-sm-12">
<table
id="datatable-fixed-header30"
class="table table-striped table-bordered dataTable no-footer"
role="grid"
aria-describedby="datatable-fixed-header_info"
>
<thead>
<tr role="row">
<th style="width:1%">
<input type="checkbox" #click="selectAll" v-model="allSelected" />
</th>
<th
class="sorting"
tabindex="0"
aria-controls="datatable-buttons"
rowspan="1"
colspan="1"
aria-label="کود: activate to sort column ascending"
>کود</th>
<th
class="sorting_asc"
tabindex="0"
aria-controls="datatable-buttons"
rowspan="1"
colspan="1"
aria-sort="ascending"
aria-label="نام: activate to sort column descending"
>نام</th>
<th
class="sorting"
tabindex="0"
aria-controls="datatable-buttons"
rowspan="1"
colspan="1"
aria-label=" آدرس الکترونکی: activate to sort column ascending"
>آدرس الکترونکی</th>
<th
class="sorting"
tabindex="0"
aria-controls="datatable-buttons"
rowspan="1"
colspan="1"
aria-label=" : activate to sort column ascending"
>نوعیت کاربرد</th>
<th
class="sorting"
tabindex="0"
aria-controls="datatable-buttons"
rowspan="1"
colspan="1"
aria-label=" : activate to sort column ascending"
>تاریخ ورود</th>
<th
class="sorting"
tabindex="0"
aria-controls="datatable-buttons"
rowspan="1"
colspan="1"
aria-label=" تنظیمات : activate to sort column ascending"
>تنظیمات</th>
</tr>
</thead>
<tbody>
<tr
role="row"
class="odd"
v-if="Users.data!=undefined && Users.data.length == 0 || Users.data!=undefined && Users.data.length=='' "
>
<td colspan="7" align="center" :v-show="hidebutton=false">
<p class="text-center alert alert-danger">هیڅ مورد نشته</p>
</td>
</tr>
<tr
role="row"
class="even"
v-else
v-show="hidebutton=true"
v-for="User in Users.data"
v-bind:key="User.id"
>
<td>
<div class="custom-control custom-checkbox">
<input
class="form-check-input"
type="checkbox"
:value="User.id"
v-model="checkedRows"
id="chekboxs"
/>
<label class="form-check-label"></label>
</div>
</td>
<td>{{User.id}}</td>
<td>{{User.name}}</td>
<td>{{User.email}}</td>
<td>
<span class="tag tag-success">{{User.type}}</span>
</td>
<td>{{User.created_at|mydate}}</td>
<td>
<a href="#" class="btn btn-info btn-xs" #click="editModal(User)">
<i class="fa fa-pencil"></i> ویرایش
</a>
<a
v-if="User.type !='admin'"
href="#"
class="btn btn-danger btn-xs"
#click="deleteUser(User.id)"
>
<i class="fa fa-trash-o"></i> حذف
</a>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="card-footer">
<pagination :data="Users" #pagination-change-page="getResults"></pagination>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
components: {
},
data() {
return {
color: "#59c7f9",
isLoading: false,
fullPage: true,
hidebutton: true,
color: "blue",
editMode: false,
Users: {},
selected: [],
allSelected: false,
checkedRows: [],
data: [],
url: "api/getAllusers",
// selectAll: false,
form: new Form({
id: "",
name: "",
email: "",
password: "",
type: "",
bio: "",
photo: ""
})
};
},
computed: {},
methods: {
selectAll: function() {
this.checkedRows = [];
if (!this.allSelected) {
for (user in this.data) {
this.checkedRows.push(this.data[user].id);
}
}
},
doAjax() {
this.isLoading = true;
this.color = "blue";
// simulate AJAX
setTimeout(() => {
this.isLoading = false;
}, 1000);
},
onCancel() {
console.log("User cancelled the loader.");
},
refrash: function() {
$("#addNew").modal("hide");
},
loadallUsers() {
axios.get("api/user").then(({ data }) => (this.Users = data));
},
getResults(page = 1) {
this.isLoading = true;
this.color = "blue";
// simulate AJAX
setTimeout(() => {
this.isLoading = false;
}, 500);
axios
.get("api/user?page=" + page)
.then(response => {
this.Users = response.data;
})
.then(
function(response) {
this.Users = response.data.data;
}.bind(this)
);
},
loadUsers() {
if (this.$gate.isAdmin()) {
this.$Progress.start();
axios.get("api/user").then(({ data }) => (this.Users = data));
axios.get("api/getAllusers").then(({ data }) => (this.data = data));
this.$Progress.finish();
}
},
createUser() {
if (this.form.name == "") {
toast.fire({
type: "warning",
icon: "warning",
html: "<h5>نام لازم است.</h5>"
});
} else if (this.form.email == "") {
toast.fire({
type: "warning",
icon: "warning",
html: "<h5> آدرس الکترونکی لازم است.</h5>"
});
} else if (this.form.password == "") {
toast.fire({
type: "warning",
icon: "warning",
html: "<h5> رمز لازم است.</h5>"
});
} else if (this.form.type == "") {
toast.fire({
type: "warning",
icon: "warning",
html: "<h5> نوعیت کاربردد لازم است.</h5>"
});
} else {
this.form
.post("api/user")
.then(() => {
// the below function will be use to reload the page
// this.$emit("refreshPage");
$("#addNew").modal("hide");
toast.fire({
icon: "success",
type: "success",
html: "<h5> کاربردد موافقانه اجاد گردید</h5>"
});
Fire.$emit("refreshPage");
this.form.reset();
// this.$Progress.finish();
})
.catch(er => {
console.log(er);
});
}
}
},
created() {
this.loadUsers();
// load the page after 3 secound
Fire.$on("refreshPage", () => {
this.loadUsers();
});
}
};
$(document).ready(function() {
var tables = $("#datatable-fixed-header30").DataTable({
paging: false,
dom: "t"
});
// $(".dataTables_filter").hide();
$("#bookSearch").keyup(function() {
tables.search($(this).val()).draw();
});
});
</script>

The following approach will allow you to use a search box outside of the table. You should be able to adapt this to your specific code.
My data is in a table called "animals":
<table id="animals" class="display dataTable cell-border" style="width:100%">
...
</table>
1) Set up the search field:
<div id="external_filter" class="dataTables_filter" style="margin: 20px 0;">
<label>External Search:
<input id="external_search" type="search" class="" placeholder="" aria-controls="animals">
</label>
</div>
In this example, I use the same class (dataTables_filter) as the original filter box - you can use whatever you want.
2) Define a basic DataTable:
This is the minimum definition needed to show the technique - you can add all your extra controls, as you need:
$(document).ready(function() {
var table = $('#animals').DataTable({
"initComplete": function(settings, json) {
$('#animals_filter').remove();
}
});
$('#external_filter input').off().keyup(function () {
table.search(this.value).draw();
});
});
The initComplete function is used to hide the original search box. We want searching to still be enabled, so we can't use "searching": false.
The $('#external_filter input') code handles searching for you. The data you enter into the search box is captured by this.value and is passed to the table's search functionality.
The web page looks like this:
The overall code is as follows:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>External Search Box</title>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script src="https://cdn.datatables.net/1.10.20/js/jquery.dataTables.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.20/css/jquery.dataTables.min.css">
<link rel="stylesheet" type="text/css" href="https://datatables.net/media/css/site-examples.css">
</head>
<body>
<div style="margin: 20px;">
<div id="external_filter" class="dataTables_filter" style="margin: 20px 0;">
<label>External Search:
<input id="external_search" type="search" class="" placeholder="" aria-controls="animals">
</label>
</div>
<table id="animals" class="display dataTable cell-border" style="width:100%">
<thead>
<tr><th>Animal</th><th>Collective Noun</th><th>Language</th></tr>
</thead>
<tbody>
<tr><td>antelopes</td><td>herd</td><td>English</td></tr>
<tr><td>elephants</td><td>herd</td><td>English</td></tr>
<tr><td>éléphants</td><td>troupeau</td><td>French</td></tr>
<tr><td>Hounds</td><td>pack</td><td>English</td></tr>
<tr><td>kittens</td><td>kindle</td><td>English</td></tr>
<tr><td>lions</td><td>pride</td><td>English</td></tr>
<tr><td>pingouins</td><td>colonie</td><td>French</td></tr>
<tr><td>ravens</td><td>unkindness</td><td>English</td></tr>
<tr><td>whales</td><td>pod</td><td>English</td></tr>
<tr><td>zebras</td><td>herd</td><td>English</td></tr>
</tbody>
</table>
</div>
<script type="text/javascript">
$(document).ready(function() {
var table = $('#animals').DataTable({
"initComplete": function(settings, json) {
$('#animals_filter').remove();
}
});
$('#external_filter input').off().keyup(function () {
table.search(this.value).draw();
});
});
</script>
</body>
</html>

Related

Vue Laravel Dynamic Dependent Dropdown

I am trying to get the Decoration types according to the house area types. I got the house area types but failed to get the decoration types. In Vue dev tool the "houseTypes" are showing an array but the "decorTypes" are showing "Reactive". I am also dynamically creating rows and removing them. for that i took an array
my vue file is--
<template>
<div v-for="(tab,k) in tabs" :key="k" >
<table class="table table-borderless col-md-12">
<thead>
<th>HouseAreaType</th>
<th>DecorationType</th>
<th>Action</th>
</thead>
<tbody>
<td>
<select
v-model="tab.selectedHouseType"
class="form-control select2"
id="houseType1"
required
name="houseAreaTypeId"
>
<option
v-for="houseType in houseTypes"
:key="houseType.id"
:value="houseType.id"
>
{{ houseType.name }}
</option>
</select>
</td>
<td>
<select
v-model="selectedDecor"
#change="getDescription()"
class="form-control select2"
required
>
<option
selected
v-for="decorType in decorTypes"
:key="decorType.id"
:value="decorType.id"
>
{{ decorType.name }}
</option>
</select>
</td>
<input type="submit" class="btn btn-success" value="Save" />
</td>
<td>
<input
type="button"
class="btn btn-success"
value="Add More"
#click="addRow"
/>
</td>
<td >
<input
type="button"
class="btn btn-danger"
value="Remove"
#click="removeRow(k,tab)"
/>
</td>
</tbody>
</table>
</div>
</template>
<script type="module">
export default {
data() {
return {
tabs: [{
rate:"",
selectedHouseType: "",
selectedDecor: "",
}],
tabCounter: 0,
houseTypes: {},
decorTypes: {},
};
},
methods: {
getHouseTypes() {
axios.get("/api/houseTypes").then((response) => {
this.houseTypes = response.data;
// this.productForm.colors = response.data;
});
},
addRow() {
this.tabs.push(this.tabCounter++);
},
removeRow(index,tab) {
var idx = this.tabs.indexOf(tab);
console.log(idx, index);
this.tabs.splice(idx, 1);
},
},
watch: {
'tab.selectedHouseType': function (value){
axios.get('/api/decorTypes?houseAreaTypeId=' + value)
.then((response) => {
console.log(response.data);
this.decorTypes = response.data.data;
});
},
},
mounted() {
this.getHouseTypes();
},
};
</script>
my api.php---
Route::get('/houseTypes',[CartController::class,'getHouseTypes'])->name('houseTypes');
Route::get('/decorTypes',[CartController::class,'getDecorTypes'])->name('decorTypes');
my CartController--
public function getHouseTypes()
{
$houseTypes = HouseAreaType::all();
return response()->json($houseTypes);
}
public function getDecorTypes()
{
$houseAreaTypeId = request('houseAreaTypeId');
$decorTypes = DecorationType::where('houseAreaTypeId',$houseAreaTypeId)->get();
return response()->json($decorTypes);
}
solved iy.
created a method getDecor()..
<select
v-model="tab.selectedHouseType"
#change="getDecor()"
class="form-control select2"
id="houseType1"
required
name="houseAreaTypeId"
>
in the mthods--
getDecor(){
axios.get('/api/decorTypes', {
params: {
houseAreaTypeId: this.tabs[this.tabs.length-
1].selectedHouseType
}
}).then(function(response){
console.log(response.data);
}.bind(this));
}

Match player's entries with difference weight

I am making a matchmaking system. Currently, what my system does is that it matches the player's entries with the same weight. My target is to match a player's entries with a different weight based on what i will type on my textbox.
For example:
User typed "10" on the textbox. Player 1 has 1920 weight. Player 2 has 1930 weight. They will be matched. But If user typed "15" it means that they will not be matched because it exceeds.
HTML:
<div class="card-body">
<div class="tab-content" id="custom-tabs-two-tabContent">
<div class="tab-pane fade show active" id="custom-tabs-two-profile" role="tabpanel" aria-labelledby="custom-tabs-two-profile-tab">
<div class="card-body table-responsive py-3 px-3">
<table id="entry_list" class="table table-bordered" cellspacing="0" style="width: 100%;">
<input type="text" id="eventID" value="<?php echo $eventID?>">
<input type="text" name="Difference" id="Difference" placeholder="Difference"> // this textbox is where i need to put whether the difference is 10 or 15.
<thead>
<tr>
<th>Entry ID</th>
<!-- <th>Event ID</th> -->
<th>Player</th>
<th>weight</th>
<!-- <th>Status</th> -->
<!-- <th>lightBand</th> -->
<!-- <th>wingBand</th> -->
<!-- <th>noOfFight</th> -->
<!-- <th>score</th> -->
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
<button class="btn btn-success float-right" data-toggle="modal" data-target="#createModal" data-dismiss="modal"><i class="glyphicon glyphicon-plus"></i> Match</button>
<div class="modal fade" id="createModal" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h3 class="modal-title">Matching</h3>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<form id="insertMatching" enctype="multipart/form-data" >
<input type="text" name="status" id="status">
<h3>Are you sure that you want to match?</h3>
<table id="entry_list1" class="table table-bordered table-hover" cellspacing="0" hidden>
<thead>
<tr>
<th>Entry ID</th>
<!-- <th>Event ID</th> -->
<th>Player </th>
<th>weight</th>
<!-- <th>Status</th> -->
<!-- <th>lightBand</th> -->
<!-- <th>wingBand</th> -->
<!-- <th>noOfFight</th> -->
<!-- <th>score</th> -->
</tr>
</thead>
<tbody>
</tbody>
</table>
<div id="result"> </div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary pull-left" data-dismiss="modal">Close</button>
<button type="button" id="submitMatching" class="btn btn-primary">Match</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
Script(Ajax):
<script>
let ajaxResult = []; // the pushed data will be saved here
let save_method;
let table;
let base_url = "<?php echo base_url();?>";
let result = [];
var html = "";
// this function combines 2 players with the same weight, if there are entries who has no same weight, hence it'll be joker. (Joker means the player has no match)
const combine = (source) => {
return source.reduce((acc, curr) => {
if (acc[curr.weight]) {
const levelArr = acc[curr.weight];
const last = levelArr[levelArr.length - 1];
if (last.length === 2) {
levelArr.push([curr])
} else {
last.push(curr)
}
} else {
acc[curr.weight] = [
[curr]
];
}
return acc;
}, {})
};
// this function removes duplicates. Players' entries cannot be matched to themselves. P1 vs P1 is cannot be.
function removeDuplicates(result) {
return Object.values(result.reduce((acc, curr) => {
acc[curr.player] = acc[curr.player] || curr;
return acc;
}, {}))
}
const uniquePlayers = removeDuplicates(result);
$(document).ready(function() {
//datatables
table = $("#entry_list1").DataTable({
processing: false,
serverSide: true,
order: [],
searching: false,
paging: false,
info: false,
ajax: {
url: "<?php echo site_url('entry/ajax_list')?>",
type: "POST",
async: true,
dataType: "json",
success: function(data) {
result = combine(removeDuplicates(data.data2));
console.log(result);
var keys = Object.keys(result)
for (var i = 0; i < keys.length; i++) {
result[keys[i]].forEach(function(val) {
var length_ = val.length;
val.forEach(function(value, index) {
var entryIDs = index == 0 ? "entryIDM[]" : "entryIDW[]"
var players = index == 0 ? "playerM[]" : "playerW[]"
var weights = index == 0 ? "weightM[]" : "weightW[]"
html += `<input type="text" name="${entryIDs}" value="${value.entryID}">
<input type="text" name="${players}" value="${value.player}">
<input type="text" name="${weights}" value="${value.weight}">
`
if (length_ == 1) {
html += `<input type="text" name="entryIDW[]" value="joker"> <input type="text" name="playerW[]" value="joker"><input type="text" name="weightW[]" value="joker">`
}
})
})
}
document.getElementById("result").innerHTML = html //add html to div
},
},
"columnDefs": [{
"targets": [0], //first column
"orderable": false, //set not orderable
},
{
"targets": [-1], //last column
"orderable": false, //set not orderable
},
],
});
});
</script>

Cart with login in laravel 5.7

I am implement shopping cart with login & witout login i am using cart package from laravel but it will stored cart item on local storage now i want to login and add cart item in database. When i am not login then item adds in local storage but when i am login then items add in database i am confuse. how i am implement I am sharing my code that i am developed need solutions
Controller:
public function add_to_cart(Request $req)
{
$userId=Session::get('userid');
$qty=$req->qty;
$product_id=$req->product_id;
$product_info=DB::table('product_details')
->join('subcategory','subcategory.sub_id','=','product_details.sub_id')
->select('subcategory.image','subcategory.name_of_subcategory','product_details.*')
->where('product_details.product_id',$product_id)->first();
$sub_id=$product_info->sub_id;
//dd($product_info);
Cart::add(array(
'id'=>$product_info->product_id,
'name'=>$product_info->name_of_subcategory,
'price'=>$product_info->price,
'qty'=>$qty,
'options'=>array('image' =>$product_info->image,'description'=>$product_info->description_of_product)
));
if($userId)
{
$content=\Cart::Content();
}
// $content=\Cart::Content();
// dd($content);
//$data = DB::select('select * from product_details where sub_id = ?',[$sub_id]);
//return view('productdetails',['data'=>$data]);
return view('cart');
}
blade
#extends('layout.header')
#section('content')
<?php
$contents=\Cart::Content();
?>
<div class="container mt-5">
<table id="cart" class="table table-hover table-condensed">
<thead>
<tr>
<th>Product</th>
<th>Price</th>
<th>Quantity</th>
<th class="text-center">Subtotal</th>
<th></th>
</tr>
</thead>
<tbody>
#foreach($contents as $v_contents)
<tr>
<td data-th="Product">
<div class="row">
<div class="col-sm-4 hidden-xs"><img src="{{asset('images/'.$v_contents->options->image)}}" alt="..." class="img-responsive"/ height="100" width="100"></div>
<div class="col-sm-8">
<h4 class="nomargin">{{$v_contents->name}}</h4>
<p>{{$v_contents->options->description}}</p>
</div>
</div>
</td>
<td data-th="Price">{{$v_contents->price}}</td>
<td data-th="Quantity">
<div class="plus-minus" style="width:150px; ">
<div class="input-group">
<span class="input-group-btn">
<button type="button" class="btn btn-default btn-number" id="subs" >
<span class="fa fa-minus"></span>
</button>
</span>
<input type="text" id="qty" name="qty" class="form-control input-number" value="{{$v_contents->qty}}" min="1" max="10">
<span class="input-group-btn">
<button type="button" class="btn btn-default btn-number" data-type="plus" id="adds">
<span class="fa fa-plus"></span>
</button>
</span>
</div>
<input type="hidden" name="product_id" id="product_id" value="{{ $v_contents->rowId}}">
</div>
</td>
<td data-th="Subtotal" class="text-center">{{ $v_contents->total}}</td>
<td class="actions" data-th="">
<a class="btn btn-danger btn-sm" href="{{ URL::to('/delete-to-cart/'.$v_contents->rowId)}}"><i class="fa fa-trash-o"></i></a>
</td>
</tr>
#endforeach
</tbody>
<tfoot>
<!-- <tr class="visible-xs">
<td class="text-center"><strong>Total 1.99</strong></td>
</tr> -->
<tr>
<td><i class="fa fa-angle-left"></i> Continue Shopping</td>
<td colspan="2" class="hidden-xs"></td>
<td class="hidden-xs text-center"><strong>Total {{\Cart::subtotal()}}</strong></td>
<td>Checkout <i class="fa fa-angle-right"></i></td>
</tr>
</tfoot>
</table>
</div>
<script type="text/javascript">
/*$('#adds').click(function add() {
var $qty = $("#qty");
var a = $qty.val();
a++;
$("#subs").prop("disabled", !a);
$qty.val(a);
});
$("#subs").prop("disabled", !$("#qty").val());
$('#subs').click(function subst() {
var $qty = $("#qty");
var b = $qty.val();
if (b >= 1) {
b--;
$qty.val(b);
}
else {
$("#subs").prop("disabled", true);
}
});*/
</script>
<script>
$(document).ready(function(){
$(document).on('click', '#adds', function(e) {
var qty = $('#qty').val();
var product_id=$('#product_id').val();
//alert(qty);
e.preventDefault()
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="_token"]').attr('content')
}
});
jQuery.ajax({
url: "{{ url('/increment') }}",
method: 'get',
data: {
qty: qty,id:product_id
},
success: function(result){
jQuery('#qty').val(result.qty);
}});
});
});
</script>
<script>
$(document).ready(function(){
$(document).on('click', '#subs', function(e) {
var qty = $('#qty').val();
var product_id=$('#product_id').val();
//alert(qty);
e.preventDefault()
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="_token"]').attr('content')
}
});
jQuery.ajax({
url: "{{ url('/decrement') }}",
method: 'get',
data: {
qty: qty,id:product_id
},
success: function(result){
jQuery('#qty').val(result.qty);
}});
});
});
</script>
#endsection

How to reload a page in laravel vue after save?

I'm trying to reload the page after save in laravel and vue.js, I do this in "fetchGoals". Here is what I've tried and it works the first time, it saves the goal and refreshes the page. When I try to add another goal then the save button no longer works and the page will not refresh. Same goes for the edit button, it will work the first time and then the second time it will not. Regardless if is save or edit, the same problem exists where I can only perform one function where the pages refreshes. Any ideas what I'm doing wrong?
<template>
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<div class="panel panel-default">
<div class="panel-heading">
<form #submit.prevent="addGoal" class="mb-3">
<div class="form-group">
<input type="text" class="form-control" placeholder="Goal" v-model="goal.title">
</div>
<div class="form-group">
<textarea class="form-control" placeholder="Description" v-model="goal.description">
</textarea>
</div>
<button type="submit" class="btn btn-primary btn-block">Add New Goal</button>
</form>
<button #click="clearForm()" class="btn btn-danger btn-block">Cancel</button>
<div class="panel-body">
<table class="table">
<thead>
<tr>
<th scope="col">id</th>
<th scope="col">Title</th>
<th scope="col">Description</th>
</tr>
</thead>
<tbody>
<tr v-for="goal in goals" v-bind:key="goal.id">
<td>{{goal.id}}</td>
<td>{{goal.title}}</td>
<td>{{goal.description}}</td>
<td>
<button #click="editGoal(goal)" class="btn btn-warning btn-xs">Edit</button>
</td>
<td>
<button #click="deleteGoal(goal.id)" class="btn btn-danger btn-xs">Delete
</button>
</td>
</tr>
</tbody>
</table>
<nav aria-label="Page navigation example">
<ul class="pagination">
<li v-bind:class="[{disabled: !pagination.prev_page_url}]" class="page-item">
<a class="page-link" href="#" #click="fetchGoals(pagination.prev_page_url)">Previous</a>
</li>
<li class="page-item disabled">
<a class="page-link text-dark" href="#">Page {{ pagination.current_page }} of {{
pagination.last_page }}</a>
</li>
<li v-bind:class="[{disabled: !pagination.next_page_url}]" class="page-item">
<a class="page-link" href="#"
#click="fetchGoals(pagination.next_page_url)">Next</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
goals: [],
goal: {
id: '',
title: '',
description: '',
user_id: 1,
},
goal_id: '',
pagination: {},
edit: false
};
},
created() {
this.fetchGoals();
},
methods: {
//gets the data and the pagination
fetchGoals(page_url) {
let vm = this;
page_url = page_url || '/api/goals';
fetch(page_url)
.then(res => res.json())
.then(res => {
this.goals = res.data;
//this comes from res and res is the data from the Jason
vm.makePagination(res.meta, res.links);
})
.catch(err => console.log(err));
},
addGoal() {
if (this.edit === false) {
// Add
fetch(`/api/goal`, {
method: 'post',
body: JSON.stringify(this.goal),
headers: {
'content-type': 'application/json',
}
})
.then(res => res.json())
.then(data => {
this.clearForm();
alert('Article Added');
this.fetchGoals();
})
.catch(err => console.log(err));
} else {
//Edit save
fetch(`/api/goal`, {
method: 'put',
body: JSON.stringify(this.goal),
headers: {
'content-type': 'application/json',
}
})
.then(res => res.json())
.then(data => {
this.clearForm();
alert('Article Added');
this.fetchGoals();
})
.catch(err => console.log(err));
}
},
editGoal(goal) {
this.edit = true;
this.goal.id = goal.id;
this.goal.goal_id = goal.id;
this.goal.title = goal.title;
this.goal.description = goal.description;
},
clearForm() {
this.edit = false;
this.goal.id = null;
this.goal.goal_id = null;
this.goal.title = '';
this.goal.description = '';
this.goal.user_id = null;
}
}
};
</script>
You can use traditional JavaScript to solve your problem
// Reload the current page
window.location.reload();
Use window.location.reload(true); to force reload (ignore the browser cache)

Child component mounts faster than parent

I use Laravel and Vue. I have two components: parent and child.
Parent:
<template>
<div>
<sport-sites-add :applications-all-list="applicationsAll"></sport-sites-add>
<table class="table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Application id</th>
<th scope="col">Name</th>
<th scope="col">Description</th>
<th scope="col">Picture</th>
<th scope="col">URL</th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
<tr v-for="sportSite in sportSites">
<th scope="row">{{ sportSite.id }}</th>
<td>
<template v-for="application in sportSite.applications">
id {{ application.id }} => {{ application.name }} <br>
</template>
</td>
<td>{{ sportSite.name }}</td>
<td>{{ sportSite.description }}</td>
<td>
<img style="width: 100px; height: 100px;" :src="sportSite.image" >
</td>
<td>
<a :href="sportSite.url" target="_blank">{{ sportSite.url }}</a>
</td>
<td>
</td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
import { EventBus } from '../../app';
export default {
name: "SportSitesTable",
mounted(){
this.loadTable();
this.getApplications();
},
methods:{
loadTable: function () {
window.axios.get('/sport_sites_all')
.then(resp => {
this.sportSites = resp.data.data;
}).catch(err => {
console.error(err);
});
},
getApplications: function () {
window.axios.get('/applications/all')
.then(resp => {
this.applicationsAll = resp.data.applications.data;
}).catch(err => {
console.error(err);
});
}
},
data(){
return {
sportSites: [],
applicationsAll: [],
}
},
}
</script>
Child:
<template>
<div>
<button type="button" class="btn btn-primary my-2" data-toggle="modal" data-target="#sportSiteAdd">
Add
</button>
<div class="modal fade" id="sportSiteAdd" tabindex="-1" role="dialog" aria-labelledby="sportSiteAddLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="sportSiteAddLabel">Add sport site</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<ul class="alert-danger">
<li v-for="error in errors">
{{ error[0] }}
</li>
</ul>
<form>
<div class="form-group">
<label for="name">Title</label>
<input type="text" class="form-control" id="name" name="name" v-model="formFields.name">
</div>
<div class="form-group">
<label for="image">Picture</label>
<input type="text" class="form-control" id="image" name="image" v-model="formFields.image">
</div>
<div class="form-group">
<label for="url">URL</label>
<input type="text" class="form-control" id="url" name="url" v-model="formFields.url">
</div>
<div class="form-group">
<label for="description">Description</label>
<textarea class="form-control" id="description" name="description" v-model="formFields.description"></textarea>
</div>
<div>
<label class="typo__label">Applications </label>
<multiselect v-model="formFields.applications"
tag-placeholder="Applications"
placeholder="Search"
label="name"
track-by="id"
:options="applications"
:multiple="true"
:taggable="true">
</multiselect>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary" v-on:click="submit">Save</button>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import { EventBus } from '../../app';
import Multiselect from 'vue-multiselect'
export default {
name: "SportSitesAdd",
props: ['applicationsAllList'],
methods:{
submit: function (e) {
window.axios.post('/sport_site/add/', this.formFields)
.then(res => {
console.log('Saved!');
$('#sportSiteAdd').modal('hide');
this.formFields.name = '';
this.formFields.image = '';
this.formFields.url = '';
this.formFields.description = '';
EventBus.$emit('reloadApplicationsTable');
}).catch(err => {
if(err.response.status === 422){
this.errors = err.response.data.errors || [];
}
console.error('Error of saving!');
});
},
},
data(){
return {
formFields: {
name: '',
image: '',
url: '',
description: '',
applications: this.applicationsAllList,
},
errors: [],
}
},
components: {
Multiselect
},
}
</script>
The parent component is a table. Child component is a form for the table. I pass a data from the parent to the child via props:
<sport-sites-add :applications-all-list="applicationsAll"></sport-sites-add>
In the child component I have a plugin for creating a multiple select. The plugin requires 'options' and 'values' collections. It's very simple, documentation with my case is here https://vue-multiselect.js.org/#sub-tagging. At the result I want to see the following: all items on the select are selected. But I have just the empty collection during mounting of the child component. I have available items on the 'select' but I dont know how I can make it selected by default. Obviously, I need to copy the applicationsAllList into local data() of child component and use it. But it not available during mounted and beforeMounted.
console.log tells me that the child is faster.
you're missing #tag function & v-model, in this case, must be array, You need to use applicationsAllList props directly on options
<multiselect v-model="formFields.value"
tag-placeholder="Applications"
placeholder="Search"
label="name"
track-by="id"
:options="applicationsAllList"
:multiple="true"
#tag="addTag"
:taggable="true">
</multiselect>
in methods add addTag function and add value as array
data() {
return {
formFields: {
name: '',
value: [],
image: '',
url: '',
description: '',
},
errors: [],
}
},
methods: {
addTag (newTag) {
const tag = {
name: newTag,
code: newTag.substring(0, 2) + Math.floor((Math.random() * 10000000))
}
this.options.push(tag)
this.value.push(tag)
}
}

Resources