Angular Scope length not working - javascript

I have a scope dumping into a table via an ng-repeat. This data is filtered by 3 different things, 2 selects and a text box. All of this works fine, but I need to echo out how many results are in the table. Using {{ sounds.length }} obviously doesn't work because this is a count prior to the filtering and filtering has no effect on that. so i added a variable sound in soundsres = (sounds | filter: filters here) but doing {{ soundsres.length }} echos out nothing with no errors in the console.
Below is a complete set of code. What am I missing here. all indications (i even checked the docs and several older threads here on SO) indicate that this should be working. Thanks in advance.
Code:
<input type="text" ng-model="gearsearch">
<select ng-model="stypesearch"><option>1</option></select>
<select ng-model="stypesearch2"><option>2</option></select>
<span>{{ soundsres.length }}</span>
<table ng-controller="GearController">
<tr ng-repeat="sound in soundsres = (sounds | filter: gearsearch | filter: stypesearch | filter: stypesearch2)">
<td>{{ sound.id }}</td>
<td>{{ sound.model }}</td>
<td>{{ sound.make }}</td>
<td>{{ sound.type }}</td>
<td>{{ sound.class }}</td>
<td>{{ sound.status }}</td>
<td>{{ sound.cost | currency }}</td>
</tr>
</table>

You could use controllerAs syntax and add the soundRes to your MainController or you could use $parent.soundRes to add your filter result to parent scope. I think the controllerAs method is more clear but both will work.
Please have a look at the demo below or in this fiddle.
(Sorry for my poor data model in the demo but I don't have a better one. But it's OK to show that the length is correctly updated.)
angular.module('demoApp', [])
.controller('ViewController', function() {
var vm = this,
sameDate = new Date();
sameDate.setMinutes(sameDate.getMinutes() - 5);
var dateLimit = new Date(sameDate);
var dates = [
{
name: 'test1',
date: new Date(sameDate)
},
{
name: 'test2',
date: new Date(sameDate)
},
{
name: 'test3',
date: new Date()
}];
vm.dates = dates;
})
.controller('MainController', MainController);
function MainController() {
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="demoApp" ng-controller="MainController as mainCtrl">
<input ng-model="mainCtrl.searchText"/>
<select ng-model="mainCtrl.stypesearch"><option>1</option></select>
<select ng-model="mainCtrl.stypesearch2"><option>2</option></select>
<!--results: {{mainCtrl.filterRes.length}}-->
results: {{filterRes.length}}
<ul ng-controller="ViewController as viewCtrl">
<li ng-repeat="date in $parent.filterRes = ( viewCtrl.dates | filter:mainCtrl.searchText | filter: mainCtrl.stypesearch | filter: mainCtrl.stypesearch2 )">{{date}}</li>
</ul>
</div>

Related

How to call Laravel Model function with parameter into Vuejs template?

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

ng-repeat takes too much time to render data

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>

AngularJS filter on deep properties

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

angularjs - ngTable not sorting

im using ngTable. Sorting is not working.
Pagination works nice and it shows all my data as I need. But I can't sort.
I'm using $data (I dont know what is for) but still can't sort.
My html:
<div class="panel-heading">
<table ng-table="vm.tableParams">
<tbody>
<tr ng-repeat="event in $data">
<td data-title="'Nombre'" sortable="'name'"> {{ event.phone ? "Tex1" : Text2 }}</td>
<td data-title="'Dia Entero'" sortable="'entero'">{{ event.allDay ? '√' : 'X' }}</td>
<td data-title="'F. Inicio'" sortable="'inicio'">{{ event.start | date:'dd-MM-yyyy' }}</td>
<td data-title="'F. Fin'" sortable="'fin'"> {{ event.end | date:'dd-MM-yyyy' }}</td>
<td data-title="'Telf.'" sortable="'telf'"> {{ event.phone ? event.phone : '--' }}</td>
</tr>
</tbody>
</table>
</div>
My js:
// My data
[{
"title":"Cerrado",
"start":"2015-12-24T23:00:00.000Z",
"allDay":true,
"backgroundColor":"#f05050",
"borderColor":"#f05050"
},
{
"title":"Abierto",
"start":"2016-04-10T04:00:00.000Z",
"end":"2016-04-10T08:00:00.000Z",
"backgroundColor":"#43d967",
"borderColor":"#43d967"
},
{
"title":"Mi Guardia",
"start":"2015-12-24T01:00:00.000Z",
"end":"2015-12-24T08:00:00.000Z",
"backgroundColor":"#5d9cec",
"borderColor":"#5d9cec"
},
{
"title":"super farmacias",
"phone":"677889966",
"address":"Calle badajoz 200",
"start":"2016-01-06T02:00:00.000Z",
"end":"2016-01-06T09:00:00.000Z",
"backgroundColor":"#dde6e9",
"borderColor":"#dde6e9",
"textColor":"#555"
}]
var data = vm.events;
vm.tableParams = new ngTableParams({
page: 1, // show first page
count: 8, // count per page
sorting: {
name: 'asc'
}
},
{
total: data.length,
counts: [],
getData: function($defer, params) {
// use build-in angular filter
var orderedData = params.sorting() ?
$filter('orderBy')(data, params.orderBy()) :
data;
$defer.resolve(orderedData.slice((params.page() - 1) * params.count(), params.page() * params.count()));
}
});
I have been trying for 2 hours with a lot of examples and changing $data for vm.values and creating other variables and stuffs.
Any idea why sort is broken?
Thanks
After checking your data, you have to modified the HTML code sortable = the object key.
Because when you sort some data in the table using ng-table, it is based on what data is displaying in the table. In this case, it will be the data you just posted. And in your data, you don't have a field called name, entero and etc. Therefore, the sort function is not working for you.
<tr ng-repeat="event in $data">
<td data-title="'Nombre'" sortable="'title'"> {{ event.phone ? "Tex1" : Text2 }}</td>
<td data-title="'Dia Entero'" sortable="'allDay'">{{ event.allDay ? '√' : 'X' }}</td>
<td data-title="'F. Inicio'" sortable="'start'">{{ event.start | date:'dd-MM-yyyy' }}</td>
...
</tr>
Usually for sorting, reverseSort feature is handy, Please try this to sort
<th>Field Name</th>

AngularJS: page displays NaNs and displays data when it gets from server. How to prevent it?

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);
});

Categories