AngularJS show 2 random records - angularjs

I just started up learning AngularJS and I have no idea how to solve this problem. For example I have 4 records (car, plane, ship, train) and I only want to show 2 randomly in ng-repeat.
Examples:
1.st. plane, ship
2.nd. car, train
3.rd. train, plane
So how would syntax look like ?
JS:
app.controller('WorkCtrl', function($scope, $http) {
$http.get('work.json').success(function(work) {
$scope.work = work;
});
});
HTML:
<div class="work" ng-controller="WorkCtrl">
<ul class="grid">
<li ng-repeat="work in work">
<a href="#{{ work.link }}" target="blank_">
<div class="background"></div>
<h3 class="name">#{{ work.name }}</h3>
<p class="description">#{{ work.description }}</p>
<img ng-src="#{{ work.image_path }}">
</a>
</li>
</ul>
</div>

I created something like this:
var app = angular.module("myApp", []);
app.controller('myCtrl', ['$scope', function($scope){
$scope.records = ['plane', 'train', 'car', 'submarine'];
}]);
app.filter('randomSelection', function(){
return function(inputArray, numItemsToReturn){
// assuming you pass an array, not doing checking here
if(!inputArray)
return inputArray;
var numItems = inputArray.length;
var min = 0;
var max = numItems-1;
var random = Math.floor(Math.random() * (max - min + 1)) + min;
while (inputArray.length > numItemsToReturn){
inputArray.splice(random, 1);
}
return inputArray;
};
});
HTML:
<div ng-repeat="record in records | randomSelection : 2">
{{record}}
</div>
Seems to work, no infdigest loop. You may want to add another condition in the while loop to break out so as to avoid an infinite loop.
http://embed.plnkr.co/mJ5Q7n24uLnELSNPUB9z/script.js

<div ng-repeat="w in work = (work|orderBy:randomize).slice(0, 2)">
$scope.randomize = function () {
return 0.5 - Math.random();
};
Demo: http://jsfiddle.net/hmx2zqex/

Related

Filter the object in the array by dynamic filter - AngularJS

Right now my data structure is like
product = [{att1:'2',att2:'red',att3:'gold'},
{att1:'1',att2:'blue',att3:'wood'},
{att1:'2',att2:'green',att3:'plastic'},
{att1:'1',att2:'red',att3:'plastic'}]
And I have a filter on the web page, it has three parts: att1, att2, att3. The user doesn't have to choose options for every part.
For filter att1 it has 2 options: "1" and "2".
Filter att2 it has 2 options: "red" "blue" and "green"
Filter att3 it has 3 options: "gold", "wood" and "plastic".
I can get the options that are selected. For example:
{att1:['2'],att3:['gold','plastic']} or {att1:['1']}
My question is, how do I use product.filter to filter the product data?
Thanks!
You can use a custom filter function which is easy to use, I used att1 but you can expand it to all fields:
var app = angular.module("MyApp", []);
app.controller("MyCtrl", function($scope) {
$scope.products = [{att1:'2',att2:'red',att3:'gold'},
{att1:'1',att2:'blue',att3:'wood'},
{att1:'2',att2:'green',att3:'plastic'},
{att1:'1',att2:'red',att3:'plastic'}];
$scope.filterFunction = function(element) {
return element.att1.match(/^Ma/) ? true : false;
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="MyApp">
<div ng-controller="MyCtrl">
<form class="form-inline">
<input ng-model="query" type="text"
placeholder="Filter by" autofocus>
</form>
<ul ng-repeat="product in products | filter:query">
<li>{{product}}</li>
</ul>
<ul ng-repeat="product in products | filter:filterFunction">
<li>{{product}}</li>
</ul>
</div>
</div>
I banged out the particular logic for this one, using the three nested loops isn't super great but it does do the job. I'm sure you can optimize this further by using some maps or something but I just went with the get it done by brute force approach :)
angular.module('myApp',[])
.service('ProductService', function(){
return {
products:[
{att1:'2',att2:'red',att3:'gold'},
{att1:'1',att2:'blue',att3:'wood'},
{att1:'2',att2:'green',att3:'plastic'},
{att1:'1',att2:'red',att3:'plastic'}
]
}
})
.controller('TestCtrl', function(ProductService){
this.ProductService = ProductService;
this.filterObject1 = {att1:['2'],att3:['gold','plastic']};
this.filterObject2 = {att1:['1']};
})
.filter('productFilter', function(){
return function(input,filterObj){
if(!filterObj){
return input;
}
var newArray = [];
var filterKeys = Object.keys(filterObj);
for(var i=0;i<input.length;i++){
var curElement = input[i];
innerLoops:
for(var j=0;j<filterKeys.length;j++){
var curKey= filterKeys[j];
for(var k=0;k<filterObj[curKey].length;k++){
var curFilterValue = filterObj[curKey][k];
if(curElement[curKey].match(curFilterValue)){
//We found a match keep this element and move on to checking the next one by breaking out of the inner loops that are checking particular keys/values
newArray.push(curElement);
break innerLoops;
}
}
}
}
return newArray;
};
})
;
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.6/angular.js"></script>
<div ng-app="myApp" ng-controller="TestCtrl as ctrl">
Unfiltered
<div ng-repeat="product in ctrl.ProductService.products|productFilter">
{{product}}
</div>
<hr/>
<strong>Filtered with: {{ctrl.filterObject1}}</strong>
<div ng-repeat="product in ctrl.ProductService.products|productFilter:ctrl.filterObject1">
{{product}}
</div>
<hr/>
<strong>Filtered with {{ctrl.filterObject2}}</strong>
<div ng-repeat="product in ctrl.ProductService.products|productFilter:ctrl.filterObject2">
{{product}}
</div>
</div>

Repeat a div or span according to the json value using angularjs

Suppose i have a json file as
{
"count":"3"
}
how to show 3 span or "n" number of span according to json value
here is my Plunker url
CONTROLLER
var app = angular.module('myapp',[]);
app.controller('ctrlParent',function($scope){
$scope.count =3;
$scope.getNumber = function(num) {
return new Array(num);
}
});
HTML
<li ng-repeat="i in getNumber(myNumber) track by $index"><span>{{$index+1}}</span></li>
JSFIDDLE
$scope.number = 5;
$scope.getNumber = function(num) {
return new Array(num);
}
<ul>
<li ng-repeat="i in getNumber(number)"><span>{{$index+1}}</span></li>
</ul>
Not sure what you mean. But according to my view, you have 2 problems:
1. Read count in json file
2. Show n span in view.
To read a json file, you can create a service to get it. Follow this Reading data from JSON file in Angularjs
Show show those span, use ng-repeat:
Hello world
count is $scope variable in ur controller.
Hope this help
You could simply do this.
var app = angular.module("sampleApp", []);
app.controller("sampleController", ["$scope",
function($scope) {
$scope.pro = [{
product: "chicken",
rating: 3
}, {
product: "fish",
rating: 1
}, {
product: "pizza",
rating: 4
}];
$scope.repeat = function(rating) {
return new Array(rating);
}
}
]);
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular.min.js"></script>
<div ng-app="sampleApp">
<div ng-controller="sampleController">
<div ng-repeat="array in pro">
<div>{{array.product}}
<span ng-repeat="number in repeat(array.rating) track by $index" ng-init="">*</span>
</div>
</div>
</body>
</div>
</div>

sum of values in a list using angular way

I have a short piece of sample here where myself trying to get total of values in angular way as,
<div id="app" ng-app="myApp" ng-controller="myCtrl" ng-init="total = 0">
<ul>
<li ng-repeat="x in myarr" > {{x.val}}
<span ng-if="$last">, Total - {{total = total+x.val}}</span>
</li>
</ul>
</div>
But total is incorrect. How can it be achieved?
EDIT: Myself trying to get total within the ng-repeat loop beside last element. There is an accepted answer in this question and below answer also work in same logic. But In that method, the function getTotal() will call myarr.length times and each time the array loops in controller right? So as per example in the question, array will loop completely 6 times (myarr.length + once in ng-repeat ie, 5+1). Do i wrong?
Try this method, no function used in controller , using ng-init in ng-repeat
angular.module('myApp', []).controller('myCtrl', function($scope) {
$scope.myarr = [{id: 1, val: 500},{id: 2,val: 300},{id: 3,val: 200},{id: 4,val: 600},{id: 5,val: 100}];
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div id="app" ng-app="myApp" ng-controller="myCtrl" ng-init="total=0">
<ul >
<li ng-repeat="x in myarr" ng-init="$parent.total = $parent.total + (x.val)"> {{x.val}}
<span ng-if="$last">{{total}}</span>
</li>
</ul>
</div>
Another method ,
Use array.reduce to add sum of array Link
angular.module('myApp', []).controller('myCtrl', function($scope) {
$scope.myarr = [{id: 1, val: 500},{id: 2,val: 300},{id: 3,val: 200},{id: 4,val: 600},{id: 5,val: 100}];
$scope.addTotal = function(){
var sum = $scope.myarr.reduce($scope.add);
return sum.val;
}
$scope.add = function(a,b){
return {val:a.val + b.val};
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div id="app" ng-app="myApp" ng-controller="myCtrl" ng-init="total=0">
<ul >
<li ng-repeat="x in myarr" > {{x.val}}
<span ng-if="$last">{{addTotal()}}</span>
</li>
</ul>
</div>
Try doing all calculations in angular controller itself and storing it in varaible. But if you are worried about values in array constantly changing you can also use a calcTotal function in your controller. Also ng-repeat should be on li and not ul.
<div id="app" ng-app="myApp" ng-controller="myCtrl" ng-init="total = 0">
<ul >
<li ng-repeat="x in myarr"> {{x.val}}
<span ng-if="$last">, Total - {{getTotal()}} or {{totalValue}}</span>
</li>
</ul>
</div>
Your controller will be like
angular.module('myApp', []).controller('myCtrl', function($scope) {
$scope.myarr = [{id: 1, val: 500},{id: 2,val: 300},{id: 3,val: 200},{id: 4,val: 600},{id: 5,val: 100}];
//first approach
$scope.totalValue = 0;
for(i=0;i<$scope.myarr.length;i++){
if($scope.myarr[i] && $scope.myarr[i].val)
$scope.totalValue+=$scope.myarr[i].val;
}
//OR
//second approach
$scope.getTotal = function(){
var total = 0;
for(i=0;i<$scope.myarr.length;i++){
if($scope.myarr[i] && $scope.myarr[i].val)
total+=$scope.myarr[i].val;
}
return total;
}
});
If you are using variable approach, you will have to explicitly calculate $scope.getTotal everytime the array values change. By the function approach it will happen itself, but binding functions on UI is little expensive as they keep re-calculating on every digest cycle.
You can use angular.forEach to loop and have you total count.
angular.module('myApp', []).controller('myCtrl', function($scope) {
$scope.total = 0;
$scope.myarr = [{id: 1, val: 500},{id: 2,val: 300},{id: 3,val: 200},{id: 4,val: 600},{id: 5,val: 100}];
angular.forEach($scope.myarr, function(value){$scope.total+=value.val});
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div id="app" ng-app="myApp" ng-controller="myCtrl">
<ul >
<li ng-repeat="x in myarr" > {{x.val}}
<span ng-if="$last">{{total}}</span>
</li>
</ul>
</div>

Dropdown Option is not selected - angularjs

I am binding numbers to a dropdown.
When page loads, the default number selected is 3. It should be 1.
Also, when I select other options like 2 & 1 in the dropdown, there are not selected. It just remains 3. Why is this happening.
Issue:
The problem is with the ng-class. If I remove the ng-class expression for Next, it works fine. But I want the Next & Last to be disabled, when user selects the last page.
I guess, $scope.LastPageNumber is assigned in a promise and hence the value doesnt stay. That's the reason for the bug.Isn't it. But then how to fix this.
HTML:
<ul class="pagination custom-pagination">
<li ng-class="{disabled: SelectedPage<=1}">First</li>
<li ng-class="{disabled: SelectedPage<=1}">Prev</li>
<li>
<select ng-model="SelectedPage" ng-options="Number for Number in PageNumbers">
</select>
</li>
<li ng-class="{disabled: SelectedPage=LastPageNumber}">Next</li>
<li>Last</li>
</ul>
JS:
$scope.SelectedPage;
$scope.LastPageNumber;
$scope.PageNumbers = [];
$scope.UserReport = [];
GetReport();
console.log($scope.SelectedPage); //print undefined
console.log($scope.LastPageNumber); //print undefined
function GetReport() {
var promise = Factory.GetReport();
promise.then(function (success) {
if (success.data != null && success.data != '') {
$scope.UserReport = JSON.parse(success.data);
BindPageNumbers(9);
}
else {
$scope.UserResponsesReport = [];
}
},
function (error) {
console.log(error);
});
}
function BindPageNumbers(totalRows) {
$scope.LastPageNumber = Math.ceil((totalRows / 3));
for (var i = 1; i <= $scope.LastPageNumber ; i++) {
$scope.PageNumbers.push(i);
}
$scope.SelectedPage = $scope.PageNumbers[0]; //set default page number as 1
console.log($scope.PageNumbers[0]); //prints 1
}
You can do it like this:
var app = angular.module('App',[]);
app.controller("ctrl",function($scope){
$scope.SelectedPage;
$scope.LastPageNumber;
$scope.PageNumbers = [];
BindPageNumbers(9);
function BindPageNumbers(totalRows) {
$scope.LastPageNumber = Math.ceil((totalRows / 3));
for (var i = 1; i <= $scope.LastPageNumber ; i++) {
$scope.PageNumbers.push(i);
}
$scope.SelectedPage = $scope.PageNumbers[0]; //set default page number as 1
}
});
And in HTML:
<body ng-app="App" ng-controller="ctrl">
<select ng-model="SelectedPage" ng-options="number for number in PageNumbers"></select>
Here is the plunker
You should use the ng-options directive:
HTML:
<div ng-app="app">
<div ng-controller="mainController">
<select ng-model="SelectedPage" ng-options="PageNumber for PageNumber in PageNumbers">
</select>
{{SelectedPage}}
</div>
</div>
JS:
angular.module('app', [])
.controller('mainController', function($scope) {
$scope.PageNumbers = [1, 2, 3];
$scope.SelectedPage = $scope.PageNumbers[0];
});
Working fiddle here: http://jsfiddle.net/ben1729/daL8r5b9/1/
<body>
<div ng-app="myApp" ng-controller="myCtrl">
<select ng-model="selected" ng-options="number for number in PageNumbers">
<option>{{number}}</option>
</select>
</div>
<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.PageNumbers = [1,2,3];
$scope.selected=$scope.PageNumbers[0];
});
</script>
</body>

AngularJS Filter not playing ball

Being new to the Angular framework I started my project using the angularSeed download. I have services and directives working fine but today I needed a filter and I just can't seem to get one working.
I have set up JSFiddle with a basic example of my setup and commented out my filter call because its causing errors. I simply want to filter out qty = 0, your experience would be much appreciated; :-)
<div ng:app="myApp">
<div ng-controller="myCtrl">
<!-- div ng-repeat="item in items | {filter : notZero}" -->
<div ng-repeat="item in items" >
<strong>{{item.title}}</strong> {{item.qty}}
</div>
</div>
</div>
and the JS
angular.module('myApp', [
'myApp.controllers',
'myApp.filters'
]);
angular.module('myApp.filters', [])
.filter('notZero', function() {
return function( items, condition) {
console.log( items, condition);
};
});
angular.module('myApp.controllers', [])
.controller('myCtrl', function($scope) {
$scope.items = [
{
"title":"40cm",
"qty":3
},
{
"title":"55cm",
"qty":2
},
{
"title":"60cm",
"qty":0
},
{
"title":"70cm",
"qty":4
}
];
});
Couple of ways to approach this:
You can have ng-repeat modified as: ng-repeat="item in
items|filter:{qty: '!0'}"
Write your own filter which checks the qty is greater than zero.
Use ng-if: <div ng-if="item.qty > 0"><strong>{{item.title}}</strong> {{item.qty}}</div>
EDIT:
define an app filter this way:
myApp.filter('qtyNotZero', function() {
return function(items) {
var afterFilter = [];
for (var i = 0; i < items.length; i++){
if(item[i].qty != 0)
afterFilter.push(item[i]);
}
return afterFilter;
};
});
and then simply:
<div ng-repeat="item in items | filter: qtyNotZero>
The filter should be applied for the qty:
<div ng-repeat="item in items | filter: {qty: '!0'}">
Or, if you have a more complicated filter, this way you can filter with your own logic:
<div ng-repeat="item in items" | filter: PositiveQty>
...
$scope.PositiveQty = function(item) {
return item.qty > 0;
}
Anyway, you could also use:
<div ng-show="item.qty">
<strong>{{item.title}}</strong> {{item.qty}}
</div>

Resources