I am trying to update view_count column on every #click. but couldn't figure out the right way of it.
First made the controller --resources and fetch datas via api.
controller:
public function index()
{
$articles = Article::all();
return response()->json([
"articles" => $articles
], 200);
}
public function show($id)
{
$article = Article::whereId($id)->first();
return response()->json([
"article" => $article
], 200);
}
also set the update function too.
public function update(Request $request, $id)
{
$view = Article::find($id);
$view->update($request->where("view_count"));
return response()->json(["message" => "view_count updated"]);
}
I set the api routes:
Route::get('/articles', 'ArticlesController#index');
Route::get('/articles/{id}', 'ArticlesController#show');
Route::get('/articles/{id}', 'ArticlesController#update');
And finally in Vue.js
<p class="button">
<i #click.prevent="count" class="fas fa-chevron-right"></i>
</p>
data(){
return {
view: 0,
};
},
methods: {
count: function(){
axios.post("/api/articles" + this.item.id).then(response => {
this.view++;
})
window.location.href = "pages/" + this.item.id
}
}
it's counting but not update the col. also, when I refresh the page of course it will start to count from 0... it's not really efficient way to it. what is the best and right way to do it?
Thank you.
Not: By the way I am fetching and iterating api in the parent component:
<div class="listWrap" :key="item.id" v-for="item in filterArticles">
<list :item="item" />
</div>
your workflow to update views is wrong.
first, we should change our uri method of the update method to GET like below :
Route::get('/articles/update/{id}', 'ArticlesController#update');
then, our update method within ArticlesController to increment view_count value:
public function update(int $id)
{
// i have changed the $view by $article
$article = Article::find($id);
$article->view_count++;
$article->save();
return response()->json(["message" => "view_count updated", 201]);
}
and within our Vue component, we should update the URI of the update method and the HTTP method name because we should use the same HTTP verb in both client and server sides.
<p class="button">
<i #click.prevent="count" class="fas fa-chevron-right"></i>
</p>
<script>
export default {
// as you are using parent/child relationship betwen components, you should use props.
props: { item: Object },
data(){
return {
view: 0,
};
},
methods: {
count: function(){
axios.get(`/api/articles/update/${this.item.id}`).then(response => {
this.view++;
})
window.location.href = "pages/" + this.item.id;
}
}
}
</script>
Related
layoutchange() {
this.layout = !this.layout;
if (this.layout === true) {
this.perPage = this.layout ? 8 : 12;
this.listProducts();
} else {
this.perPage = !this.layout ? 12 : 8;
this.gridProducts();
}
},
<a class="list-icon" v-bind:class="{ active: layout == true }" v-on:click="layoutchange"></a>
<a class="grid-icon" v-bind:class="{ active: layout == false }" v-on:click="layoutchange"></a>
<ul v-if="layout == true">
//code for product display
<b-pagination v-model="currentPage" :total-rows="rows" :per-page="perPage"></b-pagination>
</ul>
<ul v-if="layout == false">
//code for product display
<b-pagination v-model="currentPage" :total-rows="rows" :per-page="perPage"></b-pagination>
</ul
Basically i am trying to add the api call for the each page,(i have a api which need to call) for suppose if i click on pagination page no 1, i need to fire api, and same page 2 need to call api. Now i have a doubt, Now i am using the b-pagination (bootstrap-vue) are there any event to call for each page? like next previous or any event based. so with same name, i can call api using that.
I am using fr grid and list view, For both i have pagination
Reference document https://bootstrap-vue.org/docs/components/pagination
If there is no event provided by b-pagination that you can use, in that specific usecase, you can just watch the currentPage property.
https://v2.vuejs.org/v2/guide/computed.html#Watchers
export default {
data() {
return {
currentPage: null,
}
},
watch: {
currentPage(newVal) {
if(newVal) {
// Call the api
// Random api endpoint as example
const endpoint = 'https://jsonplaceholder.typicode.com/todos/'
fetch(endpoint + newVal).then((res) => {
console.log(res)
// update corresponding data
})
}
}
},
mounted() {
// Initialise currentPage to your route or 1 by default as example
this.currentPage = 1
}
}
I am developing an online store for a client using Angular/Spring Boot. To keep things simple and to the point, I am storing the users shopping cart data in localStorage which is working fine. However, for the shopping cart to be updated with the users products, I have to refresh the page. I would like the app to just update without having to refresh the page. Im sure this is probably very trivial, but I cant get it to work!
I have tried looking at a few different sources :
Refreshing Page with Angular
Angular Source
I have tried using the this.router.routeReuseStrategy.shouldReuseRoute = function () { return false; }; within the components constructor but again didnt have any luck.
The main bits of code are as follows:
CartService - On construction we fetch the data from localStorage:
constructor(private http: HttpServiceService) {
this.getCartDetailsByUser();
}
getCartDetailsByUser() {
let data = JSON.parse(localStorage.getItem("products"));
this.cartObj = data;
if (data !== null) {
this.cartQty = data.length;
console.log(data);
}
}
When the user clicks "Add to Cart", this function is called, which adds the data to the local storage, but i need to update the DOM with whats in the cart and the cart length!
addCart(product) {
let products = [];
console.log(product);
if (localStorage.getItem("products")) {
products = JSON.parse(localStorage.getItem("products"));
}
products.push({
productId: product.productId,
image: product.image,
price: product.price,
});
localStorage.setItem("products", JSON.stringify(products));
}
I dont want to manually refresh the whole page for something so simple, I would just like the DOM to update with no need to refresh.
The header.component.html is what displays the shopping cart with its quantity etc
<div class="cart cart box_1 checkout-count-wrap">
<form action="#" method="post" class="last">
<button
class="w3view-cart"
type="submit"
(click)="openCheckoutModel()"
name="submit"
value=""
>
<p class="total_count_checkout">{{cart_qty}}</p>
<i class="fa fa-cart-arrow-down" aria-hidden="true"></i>
</button>
</form>
</div>
With the linked .ts class (header.component.ts). In the constructor, I get the qty which gets passed to the html above.
constructor(
private router: Router,
private cartService: CartServiceService,
private http: HttpServiceService
) {
this.cartService.cartServiceEvent.subscribe((data) => {
this.cart_qty = this.cartService.getQty();
});
}
When the user clicks on the shopping cart on the DOM, the following code is executed which gives a popup with the products etc in the cart:
openCheckoutModel() {
this.cartObj = this.cartService.getCartOBj();
this.cartTotalPrice = this.cartService.cartTotalPrice;
this.mainDialogType = "checkout";
}
Which in turn then displays the data in the shopping cart.
ALL of this works correctly apart from the cart not updating on the fly!!
Any help would be greatly appreciated!! :D
**** EDITED ANSWER ****
OK, so from the answer on the question, I have made a few small changes with the Observable pattern.. This half works - It updates the quantity of the cart on the fly (incrementing the number + 1 when a user clicks 'Add to Cart'). It also stores the product in the json object in localStorage as it did before. However, the actual items in the cart now do not show on the DOM, where as they did before. The data definitely exists with the correct products added being stored in localStorage, but now there seems to be some issues with the DOM displaying what's in it (productName, price etc)
Will this be due to another Observable being needed to track the item data in the cart? This may become clearer when I share my code (full classes)..
So here is the checkout-component.ts with the method being highlighted with *****
import { Component, OnInit } from "#angular/core";
import { CartServiceService } from "../service/cart-service.service";
import { HttpServiceService } from "../http-service.service";
import { Router } from "#angular/router";
#Component({
selector: "app-checkout",
templateUrl: "./checkout.component.html",
styleUrls: ["./checkout.component.css"],
})
export class CheckoutComponent implements OnInit {
cartObj = [];
cartTotalPrice: any;
pay_type = "cash_on_delivery";
delivery_address = "";
constructor(
private router: Router,
private cartService: CartServiceService,
private http: HttpServiceService
) {}
ngOnInit() {
this.getCartDetailsByUser();
//below function will be triggerd from when removing and qty is changing..
this.cartService.cartServiceEvent.subscribe((data) => {
this.cartObj = this.cartService.getCartOBj();
this.cartTotalPrice = this.cartService.cartTotalPrice;
});
}
qtyChange(qty, cartObj) {
var request = {
cartId: cartObj.id,
quantity: qty,
price: cartObj.price * qty,
};
this.http
.postRequestWithToken("api/addtocart/updateQtyForCart", request)
.subscribe(
(data: any) => {
this.cartService.getCartDetailsByUser(); //for updating in the application..
},
(error) => {
alert("Error while fetching the cart Details");
}
);
}
getCartDetailsByUser() {
let data = JSON.parse(localStorage.getItem("products"));
this.cartObj = data;
this.cartTotalPrice = this.getTotalAmounOfTheCart();
console.log("Cart Obj", this.cartObj);
console.log("Total", this.cartTotalPrice);
}
// getCartDetailsByUser(){
// this.http.postRequestWithToken("api/addtocart/getCartsByUserId",{}).subscribe((data:any)=>{
// this.cartObj = data;
// this.cartTotalPrice = this.getTotalAmounOfTheCart();
// },error=>{
// alert("Error while fetching the cart Details");
// })
// }
getTotalAmounOfTheCart() {
let obj = this.cartObj;
let totalPrice = 0;
for (var o in obj) {
totalPrice = totalPrice + parseFloat(obj[o].price);
}
return totalPrice.toFixed(2);
}
removeCartById(cartObj) {
if (confirm("Are you sure want to delete..?")) {
let id = cartObj.id;
this.cartService.removeCart(id);
}
}
checkoutCart() {
if (this.delivery_address == "") {
alert("Delivery address should not be empty");
return;
}
if (this.pay_type == "cash_on_delivery") {
let request = {
total_price: this.cartTotalPrice,
pay_type: "COD",
deliveryAddress: this.delivery_address,
};
this.http
.postRequestWithToken("api/order/checkout_order", request)
.subscribe(
(data: any) => {
alert("checkout process completed.Your Order is processed..");
this.cartService.getCartDetailsByUser();
this.router.navigate([""]);
},
(error) => {
alert("Error while fetching the cart Details");
}
);
} else {
alert("Payment Integration is not yet completed.");
}
}
}
Then the corresponding checkout-component.html
<div style="display: block;" id="w3lssbmincart">
<ul>
<li *ngFor="let cart of cartObj" class="sbmincart-item sbmincart-item-changed">
<div class="sbmincart-details-name">
<a class="sbmincart-name">{{cart.name}}</a>
</div>
<div class="sbmincart-details-quantity">
<select [(ngModel)]="cart.qty" (change)="qtyChange($event.target.value,cart)">
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
<option>5</option>
<option>6</option>
<option>7</option>
<option>8</option>
<option>9</option>
<option>10</option>
</select>
</div>
<div class="sbmincart-details-remove">
<button (click)="removeCartById(cart)" type="button" class="sbmincart-remove" data-sbmincart-idx="0">×</button>
</div>
<div class="sbmincart-details-price">
<span class="sbmincart-price">{{cart.price}}</span>
</div>
</li>
</ul>
<div class="sbmincart-footer">
<div class="sbmincart-subtotal radio-wrap">
<span><input [(ngModel)]="pay_type" value="cash_on_delivery" type="radio" name="pay_type" /><span class="radio_text">Cash on Delivery</span></span>
<span><input [(ngModel)]="pay_type" value="online" name="pay_type" type="radio"/><span class="radio_text">Online</span></span>
</div>
<div class="sbmincart-subtotal">
<textarea placeholder="Enter the Delivery address" [(ngModel)]="delivery_address"></textarea>
</div>
<div class="sbmincart-subtotal">
Subtotal: <span class="price">${{cartTotalPrice}}</span>
</div>
<div>
<button (click)="checkoutCart()">Place Order</button>
</div>
</div>
<input type="hidden" name="bn" value="sbmincart_AddToCart_WPS_US">
</div>
</div>
</div>
</div>
Which simply loops over the cartObj stored within the service class.
I modified the header-component.ts (where the cart exists) to look like this:
import { Component, OnInit } from "#angular/core";
import { HttpServiceService } from "../http-service.service";
import { CartServiceService } from "../service/cart-service.service";
import { timingSafeEqual } from "crypto";
import { Router } from "#angular/router";
#Component({
selector: "app-header",
templateUrl: "./header.component.html",
styleUrls: ["./header.component.css"],
})
export class HeaderComponent implements OnInit {
isOpenLoginDialog = false;
currentDropDownMenu = "";
dialogType = "login";
mainDialogType = "";
isLogin = false;
mobile = "123456789";
password = "test";
cartObj = [];
cart_qty = 0;
cartTotalPrice = 0;
register = { name: "", email: "", mobile: "", password: "", re_password: "" };
welcomeUsername = "";
items$ = this.cartService.items$;
constructor(
private router: Router,
private cartService: CartServiceService,
private http: HttpServiceService
) {
let request = {};
this.http.postRequest("api/status", request).subscribe(
(data) => {
console.log("test", data);
},
(error) => {
alert("Server connection error " + error);
}
);
this.cartService.cartServiceEvent.subscribe((data) => {
this.cart_qty = this.cartService.getQty();
this.cartObj = this.cartService.getCartOBj();
});
}
logout() {
this.http.logout();
this.isLogin = false;
}
ngOnInit() {}
checkout_btn() {
this.router.navigate(["checkout"]);
}
openCheckoutModel() {
this.cartObj = this.cartService.getCartOBj();
this.cartTotalPrice = this.cartService.cartTotalPrice;
this.mainDialogType = "checkout";
}
openDialog() {
this.mainDialogType = "login";
}
dialogTypeInside(type) {
if (this.dialogType != type) this.dialogType = type;
}
closeDialog() {
this.mainDialogType = "";
}
curentDropDown(currentDropdownMenuName) {
if (this.currentDropDownMenu == currentDropdownMenuName) {
this.currentDropDownMenu = "";
} else {
this.currentDropDownMenu = currentDropdownMenuName;
}
}
}
Notice the openCheckoutModel() method which gets called which should pass the data down into the html component.
The data definitely exists as I am printing it out via console.log in the service class. The screen shot is below:
The front end DOM also shows there are 4 items in the cart:
However, the html does not display the actual data on the cart page:
From what I can see, i am looping over the data that definitely exists, however it does not show on the browser. I also get no errors :(
I hope this makes sense!
For peace of mind and for performance reasons, I would recommend you to go the RxJS way and turn things observable.
Short answer:
Here is a stackblitz example I could quickly make for you:
https://stackblitz.com/edit/angular-ivy-kgpicq
Long Answer:
I would recommend you structure your class as:
class CartService {
constructor() {
let cartItems = JSON.parse(localstorage.getItem('products'));
if (!cartItems) {
cartItems = []
}
this.itemsSubject.next(cartItems);
}
private itemsSubject = new BehaviorSubject<Product[]>([]);
items$ = itemsSubject.asObservable();
addToCart(item: Product) {
this.items$.pipe(
take(1),
map((products) => {
products.push(item);
localstorage.setItem('products', JSON.stringify(products));
},
).subscribe();
}
}
In your component class:
class ProductsPageComponent {
constructor(private cartService: CartService) {}
items$ = this.cartService.items$;
}
In your template:
<div class="cart cart box_1 checkout-count-wrap">
<form action="#" method="post" class="last">
<button class="w3view-cart" type="submit" (click)="openCheckoutModel()" name="submit" value="">
<p class="total_count_checkout">{{(items$ | async).length}}</p>
<i class="fa fa-cart-arrow-down" aria-hidden="true"></i>
</button>
</form>
</div>
AJAX
You can achieve this with ajax in plain javascript or with jQuery. My preference would go to jQuery.
Some code:
$.get( "/your_link", function( data ) {
$( ".result" ).html( data );
});
I would say you could write a another function in your controller that responds with the cart items. Then you could call the $.get whenever you would like to refresh your items. There's a lot of info on this so don't hesitate to look it up :)
https://api.jquery.com/jQuery.get/
Subscribe
Another solution might be to put a timeout on your subscribe. (this is some code from a project of mine which needed similar functionality to yours.)
In component.ts:
getUsers(): void {
// polling
timer(0, 2500)
.subscribe(() => {
this.userService.getUsers()
.subscribe(data => this.users = data);
});
}
In service.ts:
getUsers(): Observable<User[]> {
return this.http.get<User[]>(this.usersUrl);
}
I am new to laravel and vue.js. I am fetching data from API using resources. The idea is am using 2 div's GOAL and VALUE.
The Value should be updated when there is a change in the value from the server through PUSHER..
without refreshing the page.
here is my code
1.model
class Progress extends Model
{
protected $fillable = [
'id', 'name', 'goal', 'description'
];
public $timestamps = false;
}
2.Controller
class ProgressController extends Controller
{
public function index()
{
return ProgressResource::collection(Progress::paginate(4));
event(new UpdatedValue());
}
}
3.Resource.php
class ProgressResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
public function toArray($request)
{
return[
'the_custom_id' => $this->id,
'name' => $this->name,
'goal' => $this->goal,
'description' => $this->description,
'value' => ProgressResource::mockData($this->goal),
];
}
public static function mockData($goal=1000)
{
// 0 to $goal takes 17 minutes
$multiplier = ($goal + 7) / 1000;
$count = substr(time(), -3);
return intval(round($multiplier * $count, 0));
}
}
4.Events
class UpdatedValue implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $value, $goal;
/**
* Create a new event instance.
*
* #return void
*/
public function __construct($value)
{
//$this->progress = ProgressResource::collection(Progress::paginate(4));
$this->value = ProgressResource::mockData($this->goal);
}
/**
* Get the channels the event should broadcast on.
*
* #return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new Channel('progress');
}
}
5.Components/Front.vue
<template>
<div class="container">
<h1> Progress </h1>
<div class= "progress" v-for = "progressdata in progress" v-bind:id="progressdata.id">
<div id="div1">{{ progressdata.goal }}</div>
<div id="div2" class="value">{{ progressdata.value }}</div>
</div>
</div>
</template>
<script>
export default {
data: function() {
return {
progress: [],
}
},
mounted() {
this.loadContents();
this.listen();
},
methods: {
loadContents: function() {
//load Api
axios.get('/api/progress')
.then((response) => {
this.progress = response.data.data;
})
.catch(function (error) {
console.log(error);
});
},
listen(){
Echo.channel('progress')
.listen('UpdatedValue', (e) =>{
this.value = e.value;
console.log(this.value);
//console.log(e);
});
}
}
}
</script>
6.BLade.php
<div id ="app">
<front-page ></front-page>
</div>
<script src = "{{ mix('js/app.js') }}"></script>
</body>
Once the event has been triggered, the value should be updated in the front end without refreshing the page. I have installed PUSHER PACKAGES , PUSHER-JS AND Laravel Echo THROUGH NPM.I couldn't get the value which is updated through event in the front end..Could anyone help to solve this issue?.
Thanks.
loadContents: function() {
//load Api
let self = this ; // we are storing VueComponent object here.Cause this wont work in callback it will be undefined.
axios.get('/api/progress')
.then((response) => {
self.progress = response.data.data;
})
.catch(function (error) {
console.log(error);
});
You didn't define value in data properties. Define Value there and use self object to store this(object).
data: function() {
return {
progress: [],
value:null,
}
},
For some reason, I can't quite figure out how to get an 'autocomplete' style multiselect with Vue working properly.
I properly set the route that is being called in my axios block, and the controller is set to use the query as a way to hit the database with a LIKE clause, but something is going wrong somewhere and my multiselect is not being filled with results from database that would make it searchable.
What am I doing wrong here?
Route:
Route::get('search', 'Controller#searchTags')
->name('search');
Controller:
public function searchTags(Request $request)
{
if ($request->get('query')) {
$query = $request->get('query');
$data = TAGS::where('TAG_DATA', 'LIKE', "%{$query}%")->get();
$output = '<ul class="dropdown-menu" style="display:block; position:relative">';
foreach ($data as $row) {
$output .= '<li>' . $row->tag_data . '</li>';
}
$output .= '</ul>';
return $output;
}
}
Blade:
<div id="tagContent">
<multiselect v-model="value" open-direction="bottom" :options="options" :multiple="true" :close-on-select="false" :taggable="true" :clear-on-select="false" :preserve-search="true" placeholder="Add Tag(s)" label="name" track-by="name">
<template slot="selection" slot-scope="{ values, search, isOpen }"><span class="multiselect__single" v-if="values.length && !isOpen">{{ values.length }} options selected</span></template>
</multiselect>
</div>
new Vue({
components: {
Multiselect: window.VueMultiselect.default
},
data () {
return {
value: [],
options: []
}
},
methods: {
read(){
window.axios.get('campaigns/search').then(({ data }) =>{
console.log(data)
});
},
addTag (newTag) {
const tag = {
name: newTag,
code: newTag.substring(0, 2) + Math.floor((Math.random() * 10000000))
}
this.options.push(tag)
this.value.push(tag)
}
}
}).$mount('#tagContent');
There are a few things missing from your example, I believe.
You need to trigger the read function when the search input changes - use the #search-change event for that
You need to make use of the results of your axios request by sending them to this.options, so that the multiselect component can make use of them.
In this example, I've mocked the data request using a timeout, but you should get the idea. You can also make use of the loading property to let your users know something is happening behind the scenes.
I'm using Laravel 5.7 & VueJs 2.5.* ...
I have invoices table, i need to display specific invoice in a new component, so user can see whatever invoice he wants or print that invoice.
I don't know how to do that, i'm just playing around, if you could help me out, i'll be very grateful to you.
<router-link> to the component
<router-link to="/ct-invoice-view" #click="openInvoice(ctInvoice)">
<i class="fas fa-eye fa-lg text-blue"></i>
</router-link>
Displaying Customer information here like this:
<div class="col-sm-4 invoice-col">
<address v-for="ctInvoice in ctInvoices" :key="ctInvoice.id">
<strong>Customer Info</strong><br>
Name: <span>{{ ctInvoice.customer.customer_name }}</span>
Invoice view component data() & method{}
data() {
return {
ctInvoices: {},
customers: null
};
},
methods: {
openInvoice(ctInvoice) {
axios
.get("api/ct-invoice/show/" + this.viewInvoice)
.then(({
data
}) => (this.ctInvoices = data.data));
},
Image for Better Understanding
You need to look at Dynamic Route matching: https://router.vuejs.org/guide/essentials/dynamic-matching.html#reacting-to-params-changes
Then you need to use axios.get in invoice views beforeMount function where this.$route.params.id will hold the invoice ID you want to load if the link is applied like so:
<router-link :to="`/ct-invoice-view/${ctInvoice.id}`">
<i class="fas fa-eye fa-lg text-blue"></i>
</router-link>
Alternatively...
I suggest not navigating away from the list, it can be irritating for users having filtered the list then returning to it to look at more invoices and having to filter again unless the filter options and current results are sticky
There are a number of ways of doing this and they are lengthy to example, Typically I would make proper use of a modal and the invoice view load the data on display but to get you started a basic in page solution to experiment with, then try adapting in a reusable modal component later:
<button #click="showInvoice = ctInvoice.id">
<i class="fas fa-eye fa-lg text-blue"></i>
</button>
data() {
return {
loading: false,
invoice: {},
customers: null
};
},
computed: {
showInvoice: {
get: function() {
return this.invoice.hasOwnProperty('id');
},
set: function(value) {
if(value === false) {
this.invoice = {};
return;
}
// could check a cache first and push the cached item into this.invoice else load it:
this.loading = true;
axios.get("api/ct-invoice/show/" + value).then(response => {
// you could push the invoice into a cache
this.invoice = response.data;
}).cache(error => {
// handle error
}).finally(() => {
this.loading = false;
});
}
}
}
In view-invoice component have a close button with bind #click="$emit('close')"
Check this article for how $emit works: https://v2.vuejs.org/v2/guide/components-custom-events.html
<div v-if="loading" class="loading-overlay"></div>
<view-invoice v-if="showInvoice" :invoice="invoice" #close="showInvoice = false" />
<table v-else>....</table>
Hide the table when displaying the invoice, experiment with using v-show instead of v-if upon loosing table content state.
Inside your invoice view, property called invoice will contain the invoice data.
Check this article for how to use props: https://v2.vuejs.org/v2/guide/components-props.html
Hint: The #close listens to the $emit('close')
Could also make use of when switching between table and invoice view.
https://v2.vuejs.org/v2/guide/transitions.html
#MarcNewton
I did something like this, it's working for me, can u just review it for me:
<router-link> to the Invoice View component
<router-link v-bind:to="{name: 'ctInvoiceView', params: {id: ctInvoice.id}}">
<i class="fas fa-eye fa-lg text-blue"></i>
</router-link>
Getting Data of Specific Invoice ID Like This:
created: function() {
axios
.get("/api/ct-invoice/" + this.$route.params.id)
.then(({
data
}) => {
console.log(data);
this.form = new Form(data);
})
.catch(error => {
console.log(error.response);
});
},