I have a product table and stock table. In stock table data about product sale and purchase are stored. I need to show the stock of every product base on purchase and sale. So I need to call a model function with product Id in vuejs template to calculate the stock quantity of the product. How to do this, or is there any alternative way? please help me out.
My product controller function is-
public function stock() {
return Product::with(['category', 'stock'])->get();
}
My product model function is-
public function stock($id){
$purchase_quantity = Stock::where([['product_id', $id], ['stock_type', 'purchase']])->sum('quantity');
$sale_quantity = Stock::where([['product_id', $id], ['stock_type', 'sale']])->sum('quantity');
return $purchase_quantity - $sale_quantity;
}
My vuejs template code where in every v-for iteration I want to call the model function-
<tr v-for="product in products.data" :key="product.id">
<td>{{ product.id }}</td>
<td>{{ product.category.name }}</td>
<td>{{ product.name }}</td>
<td>{{ product.unit }}</td>
<td>{{ product.stock(product.id) }}</td>
</tr>
Here product.stock(product.id) is not working.
It shows the error-
Too few arguments to function App\Models\Product::stock(), 0 passed
you need to use accessor in this case so
in Product.php
protected $appends = ['stocks'];
/**
* Get the Product's stock
*
* #return int
*/
public function getStocksAttribute()
{
$purchase_quantity = Stock::where([['product_id', $this->id], ['stock_type', 'purchase']])->sum('quantity');
$sale_quantity = Stock::where([['product_id', $this->id], ['stock_type', 'sale']])->sum('quantity');
return $purchase_quantity - $sale_quantity;
}
then in side javascript you can you can get stock in each product row like product.stocks
your vuejs code will be like this
<tr v-for="product in products.data" :key="product.id">
<td>{{ product.id }}</td>
<td>{{ product.category.name }}</td>
<td>{{ product.name }}</td>
<td>{{ product.unit }}</td>
<td>{{ product.stocks }}</td>
</tr>
ref link https://laravel.com/docs/8.x/eloquent-mutators#defining-an-accessor
Related
I have a table for fetching data from the database. I used the "status" field for managing this table.
if the status is = 1, it means "Active" else if the status is = 2, it means "Completed" else if the status is = 0, t means "Deleted".
Then I need to show the above status word in the web page table.
I used the below to show the status number.
<tr v-for="(depAcc, index) in depAccs" :key="index">
<td>{{ index + 1 }}</td>
<td>{{ depAcc.created_at }}</td>
<td>{{ depAcc.name }}</td>
<td>{{ depAcc.status }}</td>
Please instruct me to show the status word on the table.
I would create a data property containing the status map, like this:
data() {
return {
statusNames: {
0: 'Deleted',
1: 'Active',
2: 'Completed'
}
}
}
Then you can reference that in your markup:
<td>{{ statusNames[depAcc.status] }}</td>
In Vue, anything inside double braces {{ //this }} is evaluated as JS. You can therefore write a method to return strings based on your status, then put a function into your double braces.
<tr v-for="(depAcc, index) in depAccs" :key="index">
<td>{{ index + 1 }}</td>
<td>{{ depAcc.created_at }}</td>
<td>{{ depAcc.name }}</td>
<td>{{ statusText(depAcc.status) }}</td>
</tr>
Then in your page script, add this method
var app = new Vue({
el: '#app',
methods:{
statusText(status){
let message = "Unknown Status"
if (status == 0) message = "Deleted"
if (status == 1) message = "Active"
if (status == 2) message = "Completed"
return message
}
}
});
I've found many resources for sorting data that is already in an array but can't find anything on sorting dynamically generated data.
<table>
<thead>
<tr>
<th>Program</th>
<th>Rewards</th>
</tr>
</thead>
<tbody>
<tr v-for="program in programs" :key="program.id">
<td>{{ program.program_name }}</td>
<td>{{ pointValue(program) | percent }}</td>
</tr>
</tbody>
</table>
pointValue() is a method which calculates and returns a value which is displayed as a %. this is the Rewards column. i would like the table to be sortable by Programs and by Rewards. (Program is just a string).
Create computed array for programs using map and sort method and iterate it instead
computed: {
computedPrograms() {
return this.programs
.map(program => {
return {
...program,
value: this.pointValue(program)
}
})
.sort((a, b) => a.value - b.value)
}
}
<tr v-for="program in computedPrograms" :key="program.id">
<td>{{ program.program_name }}</td>
<td>{{ program.value | percent }}</td>
</tr>
I know there are many questions already posted for the same issue but none of the solutions work in my case.
On calling a web service I get JSON response. In this JSON, there are around 2000+ objects from which I need to display data on the table. I want to display all (2000+) records in the table and Yes, I cannot limit or paginate, need to display it on a single page (I know it's stupid but it's the business requirement). I don't need sorting or searching.
Data transfer is about 2MB and the request completes in about 2-4 secs approx. but it takes around 10-15 secs to data render on the page.
Now, what I am looking for is either speed ng-repeat binding things up (if possible) or display the data as soon as I receive it and keep on adding it until all rows are displayed.
Check out the code below :
HTML
<table class="table table-bordered table-striped cf">
<thead style="color: #333;">
<tr>
<td>Asset Name</td>
<td>Date/ Time</td>
<td>Location</td>
<td>Ignition</td>
<td>Speed</td>
<td>Heading</td>
<td>Direction</td>
</tr>
</thead>
<tbody>
<tr ng-repeat="cols in tableData">
<td>{{ cols.aN }}</td>
<td>{{ cols.dT }}</td>
<td>{{ cols.Lat }}, {{ cols.Lon }}</td>
<td>{{ cols.I }}</td>
<td>{{ cols.S }}</td>
<td>{{ cols.H }}</td>
<td>{{ cols.D }}</td>
</tr>
</tbody>
</table>
JS
var ignition_text = '';
var lat = '';
var lon = '';
for (var i = 0; i < data.length; i++) {
if (data[i].ignition = 1) {
ignition_text = "On";
} else {
ignition_text = "Off";
}
$scope.$apply(function() {
$scope.tableData.push({
aN: name,
dT: data[i].eventUTCTime,
Lat: data[i].latitudeDegrees,
Lon: data[i].longitudeDegrees,
I: ignition_text,
S: data[i].speedMPH,
H: data[i].longitudeDegrees,
D: data[i].latitudeDegrees
});
});
}
Thanks in advance!
You probably wont need $scope.$apply at all. And even if you need it, you should only use it once you pushed all data to the table. Otherwise, every added entry will force an digest-cycle. Just build your array and assign the finished array to the scope-variable. Then angular will only build the table once.
Depending on the nature of your variable name you may be able to eliminate the array building as well and just use the data you are downloading. Apart from nameyou just use that data anyway.
Here is a plunk that has a similar data size but loads much faster http://plnkr.co/edit/I4rN1ZMaR3e1mbcsJ9Ka. If you were to make a quick plunk I could use your data and edit your code but from the looks you just need the main assignment to the scope without the apply for the data and add a track by to the ng-repeat. SN: You would want to manipulate your data inside the for loop then do the assignment to the scope.
for (var i = 0; i < data.length; i++) {
if (data[i].ignition = 1) {
ignition_text = "On";
} else {
ignition_text = "Off";
}
}
$scope.tableData=data;
JS
$http.get("largeData.json").then(function(response) {
vm.test = response.data;
});
HTML
<tbody>
<tr ng-repeat="(key, value) in main.test track by $index ">
<td>{{ value.ask }}</td>
<td>{{ value.bid }}</td>
<td>{{ value.volume_btc }}, {{ value.volume_percent }}</td>
<td>{{ value.last }}</td>
<td>{{ value.timestamp }}</td>
</tr>
</tbody>
I am trying to filter some data on a string value but I can't get the syntax right. Here is my code :
<tbody ng-repeat="qbRating in vm.scope.qbRatings | filter:'tournament.season.seasonName':'2022' | ratingFilter | orderBy:'-rating'">
<tr class="qbrating2022">
<td>{{ qbRating.tournament.season.seasonName }}</td>
<td>{{ qbRating.team.teamName }}</td>
<td>{{ qbRating.completion }}</td>
<td>{{ qbRating.gain }}</td>
<td>{{ qbRating.touchdown }}</td>
<td>{{ qbRating.interception }}</td>
<td>{{ qbRating.rating }}</td>
</tr>
</tbody>
The filter does not return any data even though it should do, but there is no error returned in the console.
Can anybody help me get the syntax right?
You should put filter on specific property by specifying object to be match like filter: {'tournament': {season : {seasonName:'2022'}}}
ng-repeat="qbRating in vm.scope.qbRatings | filter: {'tournament': {season : {seasonName:'2022'}}} | ratingFilter | orderBy:'-rating'"
filter takes a string, object or function, not an array filter api
Consider this conroller
$scope.transaction = {};
$scope.transactions = Transaction.query();
$scope.save = function() {
var transaction = new Transaction();
transaction.name = $scope.transaction['name'];
transaction.debit = $scope.transaction['debit'];
transaction.date = $scope.transaction['date'];
transaction.amount = $scope.transaction['amount'];
transaction.category = $scope.transaction['category'].uuid;
//noinspection JSUnresolvedFunction
transaction.$save();
$scope.transactions.push(transaction);
console.log('transaction saved successfully', transaction);
};
and this HTML
<tbody ng-repeat="transaction in transactions | orderBy: transaction.created_on">
<td>{{ transaction.name }}</td>
<td>{{ transaction.amount | currency }}</td>
<!-- custom filter to display type of transaction -->
<td>{{ transaction.debit | transactionType }}</td>
<!-- added dateInMillis to pass to date to filter Angular way -->
<td>{{ transaction.created_on | dateInMillis | date: 'medium'}}</td>
<td>{{ transaction.category.name }}</td>
<td>
</tbody>
Problem
When I add transaction, it immediately displays bunch of NaNs and then once the server comes back with saved data, it replaces those NaNs with actual data
How can I prevent that from happening? Its not a good UX
Without seeing all the code related to the Transaction object its hard to know for sure what the problem could be. At a glance I think you need a callback function attached to transaction.$save() method.
transaction.$save(function(u, putResponseHeaders) {
// This is $save's success callback
$scope.transactions.push(transaction);
console.log('transaction saved successfully', transaction);
});