Angularjs Price Range Slider dynamically manipulate content based on Min-Max - angularjs

I am new to AngularJS & I am using angular-slider for specifying a price range. I want to display the only elements specified by the range.
Here's the AngularJS Code-
var app = angular.module('myApp', ['rzModule']);
app.controller('SampleController', function($scope, $http) {
$scope.elements = [1530,2100,2780,3323,3420,4680,5020,5300,5402];
});
app.controller('RangeController', RangeController);
function RangeController() {
var vm = this;
vm.changeListener = function() {
minPrice = vm.slider.minValue;
maxPrice = vm.slider.maxValue;
console.log(minPrice + " " +maxPrice);
};
vm.slider = {
minValue: 1500,
maxValue: 5500,
options: {
floor: 1500,
ceil: 5500,
step: 500,
translate: function(value) {
return '₹' + value;
},
onChange:vm.changeListener
}
}
}
HTML-
<body ng-app="myApp">
<div ng-controller="RangeController as vm">
<rzslider rz-slider-model="vm.slider.minValue" rz-slider-high="vm.slider.maxValue" rz-slider-options="vm.slider.options"></rzslider>
</div>
<div ng-controller="SampleController">
<div ng-repeat="x in elements">
{{x}}
</div>
</div>
I think it can be done using filters but I am not sure. Any Solutions?

You can write a Custom AngularJS filter for this.
angular.module('myModule', [])
.filter('inRange', function() {
return function(array, min, max) {
array = array.filter(function(element) {
return element >= min && element <= max;
});
};
});
});
<div ng-repeat="x in elements | inRange:vm.slider.minValue:vm.slider.maxValue">

Related

AngularJs ng-repeat does not order time list after scope change

I try to reorder ng-repeat list after $scope change
<div ng-repeat="item in model.itemList | orderBy:order">
<input ng-blur="setOrder('start')"
ng-change="timeSpanChange(item.start,start.newTime);"
ng-model="start.newTime" ng-value="item.start|showTimeSpan"
type="time" />
</div>
And I have angular code:
app.controller('ctl', function ($scope, $http, $timeout) {
$scope.order = 'start';
$scope.model = {
"itemList": [
{ "start":new Date(2000,01,01,10,00,00) },
{ "start":new Date(2000,01,01,11,00,00) },
{ "start":new Date(2000,01,01,12,00,00) }
]
}
$scope.setOrder = function (order) {
$scope.order = order;
};
$scope.timeSpanChange = function (item, time) {
item.Hours = time.getHours();
item.Minutes = time.getMinutes();
};
}).filter('showTimeSpan', function () {
return function (time) {
return String(time.Hours).padStart(2, '0') + ":" + String(time.Minutes).padStart(2, '0');
};
});
I see that model has change after ng-blur, but ng-repeat is still ordered as on first load
What i'm doing wrong, should I refresh scope before reorder?
order should be a property in the itemList. I'm assuming you are not changing the sort order.
<div ng-repeat="item in model.itemList | orderBy:'start'">
The orderBy filter sorts JavaScript Date objects by date and time. Use a custom predicate function to sort by time only:
$scope.timeOnlyFn = function(item) {
var timeOnly = item.datetime.valueOf() % (24*60*60*1000);
return timeOnly;
}
The DEMO
angular.module("app",[])
.controller('ctrl', function ($scope, $http, $timeout) {
$scope.order = 'datetime';
$scope.model = {
"itemList": [
{ "datetime": new Date("2019-02-07T09:00"), name: "Baker" },
{ "datetime": new Date("2019-07-07T08:00"), name: "Charlie" },
{ "datetime": new Date("2019-02-07T10:00"), name: "Adam" }
]
}
$scope.timeOnlyFn = function(item) {
var timeOnly = item.datetime.valueOf() % (24*60*60*1000);
return timeOnly;
}
$scope.setOrder = function (order) {
$scope.order = order;
};
});
<script src="//unpkg.com/angular/angular.js"></script>
<body ng-app="app" ng-controller="ctrl">
<div ng-repeat="item in model.itemList | orderBy:order">
<input ng-model="item.datetime" type="date" />
<input ng-model="item.datetime" type="time" />
{{item.name}}
</div>
<br>
<button ng-click="order='name'">Order by Name</button>
<button ng-click="order='datetime'">Order by DateTime</button>
<button ng-click="order=timeOnlyFn">Order by TimeOnly</button>
</body>
Thanks a lot georgeawg, that's exactly what I need, but I suppose my problem starts in the model.
In fact I'm getting json from controller and it isn't UTC but C# TimeSpan object {"Hours":16,"Minutes":8,"Seconds":45,"Milliseconds":....., that's why i used ng filter to map it with <input type='time'>
Is the properly way to make two-way binding model property with C# time span; or
should I convert it in controller?

AngularJS - Watch filtered list for changes

Within angular I have a filtered list of people that takes the filter criteria from a predicate function. I want to watch a variable of the filtered list (called filteredPeople) every time the filtered list changes. But I am unable to see when that variable changes.
My code is below:
HTML:
<ul>
<li ng-repeat="person in ($ctrl.filteredPeople = ($ctrl.people | filter: $ctrl.filter))">
...
</li>
</ul>
JS:
controller: ['$scope',
function ($scope) {
var $ctrl = this;
$ctrl.people = {...}
$ctrl.filteredPeople = [];
$scope.$watch($ctrl.filteredPeople, function () {
console.log("called"); //not being called
});
$ctrl.filter = function (p) {
//custom filter function for each item in the array of people
}
}]
I can answer any questions of provide more code if needed
angular.module('app', []).controller('ctrl', function($scope) {
var vm = this;
vm.items = [
{ name: 'Sam' },
{ name: 'Max' },
{ name: 'Tom' },
{ name: 'Henry' },
{ name: 'Jack' },
{ name: 'Kate' }
]
var counter = 1;
$scope.$watchCollection('vm.filtered', function(){
console.log('Changed' + counter++);
})
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js">
</script>
<div ng-app='app' ng-controller='ctrl as vm'>
<input type='text' ng-model='vm.filter' />
<ul>
<li ng-repeat='item in vm.filtered = (vm.items | filter : vm.filter)'>{{item}}</li>
</ul>
</div>

How to count the number of elements selected in a directive?

If you have a career-box directive like this:
<div ng-repeat='career in careers' career-box ng-click="toggleSelected()"> {{ career.name }} </div>
The directive:
app.directive('careerBox', function() {
return {
restrict: 'A',
link: function(scope, element, attrs) {
scope.selected = false,
scope.toggleSelected = function() {
element.toggleClass('selected');
if(scope.selected) {
scope.selected = false;
} else {
scope.selected = true;
}
}
}
};
});
Every time a career-box is selected I would like to count the total number of career-boxes selected (selected=true) and enable a button if they are more than 0.
How can I do that in the code?
There is no need to write a custom directive. It can be done with Angular core directives:
vm.selectedCount = function(item) {
var count=0;
for (let i=0; i<vm.careers.length; i++) {
if (vm.careers[i].selected) count++;
}
return count;
}
<div ng-repeat='career in careers'
ng-click="career.selected = !career.selected"
ng-style="{'background-color': career.selected?'yellow':''}">
{{ career.name }}
</div>
<hr>Selected count: {{selectedCount()}}
The DEMO on PLNKR
The DEMO
angular.module("myApp",[]);
angular.module("myApp").controller("myVm", function($scope) {
var vm = $scope;
vm.careers = [ {name: "Police Officer", value: 1},
{name: "Nurse", value:2},
{name: "Doctor", value:3},
];
vm.selectedCount = function(item) {
var count=0;
for (let i=0; i<vm.careers.length; i++) {
if (vm.careers[i].selected) count++;
}
return count;
}
})
<script src="//unpkg.com/angular/angular.js"></script>
<body ng-app="myApp" ng-controller="myVm">
<h1>Selected Div Example</h1>
<div ng-repeat='career in careers'
ng-click="career.selected = !career.selected"
ng-style="{'background-color': career.selected?'yellow':''}">
{{ career.name }}
</div>
<hr>Selected count: {{selectedCount()}}
</body>
First, you need to have a select element with the multiple property:
<select name="carers" multiple id="multipleCarers" ng-model="data.multipleCarers">
<option ng-repeat="career in careers" value="{{career.value}}">
{{career.name}}
</option>
</select>
After of that, you can get the count of options selected:
{{data.multipleCarers.length}}

Angular Google Maps, Directive inside Info Window isn't binding data

I'm using Angular google Maps trying to get an info window working. When a marker is selected, the window is placed there and shown. Its content is some text and also some directives. The directives inside even work, except for when I try to bind some data its attributes.
In this case I'm having a rating directive (shows a bunch of stars) that takes a number attribute, as so:
<div stars number="person.rating"></div>
Note that this directives works just fine in a couple of other places in my app. Also, when I replace person.rating' for3, the directive renders perfectly. when I useperson.rating` outside of this div, it returns a number as expected.
Only when I combine the person.rating inside the number attribute, inside the window directive, do things go awry:
<ui-gmap-google-map center='map.center' class="big-maps" options='map.options' events="map.events" zoom='map.zoom'>
<ui-gmap-window coords="selectedCoords" show="windowOptions.visible" closeClick="closeWindow">
<div>
Name: {{person.firstName}}, Rating: {{person.rating}} <!-- these work just fine. -->
<div> So here we are. {{person.rating}}</div> <!-- this also works just fine. -->
<div stars number="3"></div> <!-- Even this works fine. -->
<div stars number="person.rating"></div> <!-- But this doesn't... -->
</div>
</ui-gmap-window>
<ui-gmap-markers
models='markers'
idKey='id'
coords="'coords'"
icon="'icon'"
options="'options'"
doCluster="false"
click="showWindow"
>
</ui-gmap-markers>
</ui-gmap-google-map>
The directive:
ndtApp.directive('stars', stars);
function stars() {
return {
restrict: "AE",
replace: 'true',
scope: {
number: "=",
size: "#"
},
templateUrl: "shared/stars/stars.html",
controller: controller
};
}
function controller($scope){
$scope.getEmptyStarsArray = getEmptyStarsArray;
$scope.getStarsArray = getStarsArray;
$scope.ratingSize = "";
activate();
function activate(){
if ($scope.size == 'sm'){
$scope.ratingSize = 'rating-sm';
} else if ($scope.size == 'lg'){
$scope.ratingSize = 'rating-lg';
}
console.log($scope.number);
}
function getEmptyStarsArray(){
if ($scope.number === undefined) return 0;
var rating = Math.round($scope.number);
if (rating > 4) return null;
return new Array(5 - rating);
}
function getStarsArray(){
if ($scope.number === undefined) return 0;
var rating = Math.round($scope.number);
if (rating === 0) return null;
if (rating > 5) return new Array(5);
return new Array(rating);
}
}
stars.html:
<div class="stars">
<span ng-repeat="i in getStarsArray() track by $index" class="{{ratingSize}} rating glyphicon glyphicon-star"></span><span ng-repeat="i in getEmptyStarsArray() track by $index" class="{{ratingSize}} rating glyphicon glyphicon-star-empty"></span>
</div>
Any help is highly appreciated!
It seems directive scope property is not getting bound, try to change scope for number property from number: "=" to number: "#" and directive initialization from <div stars number="person.rating"></div> to <div stars number="{{person.rating}}"></div>
Below is provided a working similar example:
var appMaps = angular.module('appMaps', ['uiGmapgoogle-maps']);
appMaps.controller('mainCtrl', function($scope,uiGmapIsReady) {
$scope.map = {
center: { latitude: 40.1451, longitude: -99.6680 },
zoom: 4,
options: { scrollwheel: false }
};
$scope.windowOptions = { visible: false };
var getRandomLat = function() {
return Math.random() * (90.0 + 90.0) - 90.0;
};
var getRandomLng = function () {
return Math.random() * (180.0 + 180.0) - 180.0;
};
var getRandomRating = function() {
return Math.floor(Math.random() * 11);
};
var createRandomMarker = function(i) {
var ret = {
latitude: getRandomLat(),
longitude: getRandomLng(),
title: 'Hotel #' + i,
show: false,
id: i
};
return ret;
};
$scope.onClick = function(marker, eventName, model) {
$scope.windowOptions.visible = true;
$scope.selectedHotel = model;
$scope.rating = { number: getRandomRating()};
};
$scope.closeWindow = function () {
$scope.windowOptions.visible = false;
};
$scope.hotels = [];
for (var i = 0; i < 256; i++) {
$scope.hotels.push(createRandomMarker(i));
}
});
appMaps.directive('rating',
function() {
return {
restrict: "AE",
replace: true,
scope: {
//number: "=",
number: "#"
},
controller: ratingController,
//template: '<div >Rating: {{ ::number }}</div>',
template: function(tElem, tAttrs){
return '<div class="rating"> Rating:' + tAttrs.number + '</div>';
}
};
});
function ratingController($scope){
console.log($scope.number);
}
html, body, #map_canvas {
height: 100%;
width: 100%;
margin: 0px;
}
#map_canvas {
position: relative;
}
.angular-google-map-container {
position: absolute;
top: 0;
bottom: 0;
right: 0;
left: 0;
}
<script src="https://code.angularjs.org/1.3.14/angular.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/lodash.js/2.4.1/lodash.js"></script>
<script src="http://rawgit.com/angular-ui/angular-google-maps/2.0.X/dist/angular-google-maps.js"></script>
<div id="map_canvas" ng-app="appMaps" ng-controller="mainCtrl">
<ui-gmap-google-map center="map.center" zoom="map.zoom" draggable="true" options="options" events="map.events">
<ui-gmap-window coords="selectedHotel" show="windowOptions.visible" closeclick="closeWindow">
<div>
<div>{{selectedHotel.title}}</div>
<div rating number="{{rating.number}}"></div>
</div>
</ui-gmap-window>
<ui-gmap-markers models="hotels" coords="'self'" icon="'icon'" click="onClick">
</ui-gmap-markers>
</ui-gmap-google-map>
</div>

AngularJS - Access $scope from controller in custom filter

I have a controller with various $scopes. I need to access one of these $scopes in a custom filter:
app.controller('AppController',
function($scope) {
$scope.var1 = 'Some data1';
$scope.var2 = 'Some data2';
}
);
app.filter('myCustomFilter', function ($filter) {
return function (date) {
var date = date;
};
});
<tr ng-repeat="data in MyData" ng-class="{true: 'green', false:'red'}[data.Date | myCustomFilter]">
</tr>
How can i pass $scope.var1 into my myCustomFilter??
app.filter('myCustomFilter', function ($filter) {
return function (date, scope) { // add scope here
var date = date;
};
});
ng-class="{true: 'green', false:'red'}[data.Date | myCustomFilter:this]">
You must provide the wanted scope attribute to the filter.
You can do it like that:
Filter:
app.filter('myCustomFilter', function ($filter) {
return function (date,myVar1) {
/* Do some stuff with myVar1 */
};
});
HTML:
<tr ng-repeat="data in MyData" ng-class="{true: 'green', false:'red'}[data.Date | myCustomFilter:var1]">
</tr>
var app = angular.module('app', []);
app.controller('AppController',
function($scope) {
$scope.var1 = 2;
$scope.var2 = 3;
$scope.MyData = [{
Date: 1
}, {
Date: 2
}, {
Date: 3
}]
}
);
app.filter('myCustomFilter', function($filter) {
return function(date, scopeValue) {
var date = date;
return date * scopeValue
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body>
<div ng-app="app">
<div ng-controller="AppController">
<li ng-repeat="data in MyData">
Date: {{data.Date}} | Date after myCustomFilter: {{data.Date | myCustomFilter : var1}}
</li>
</div>
</div>
</body>

Resources