Angular Custom Filtering by Date Quarter - javascript

I've got an array of objects, ng-repeated on the page. I've also got a list of date quarters arrayed in a dropdown select box. If the quarter selected in the dropdown comes later than an item in the ng-repeated list, that item should be filtered out.
Unfortunately, I can't get it to work. Here's my HTML:
<div ng-app="programApp" ng-controller="programController">
<select ng-model="advancedFiltersy">
<option ng-repeat="indexitem in quarters">{{indexitem}}</option>
</select>
<div ng-repeat="item in listing | advFilterName:advancedFiltersy:quarters">
{{item.name}}
</div>
</div>
Here's my Angular Script:
angular.module('programApp', ['programApp.controllers','programApp.filters']);
angular.module('programApp.controllers', [])
.controller('programController', ['$scope', '$filter',
function($scope, $filter){
$scope.advancedFiltersy = 'zeroeth';
$scope.quarters = ['zeroeth','first','second','third','fourth','fifth','sixth'];
$scope.listing = [{'name':'aa','aacApprovalIconQuarter':'zeroeth'
},{'name':'ab','aacApprovalIconQuarter':'first'
},{'name':'ac','aacApprovalIconQuarter':'second'
},{'name':'ad','aacApprovalIconQuarter':'third'
},{'name':'ae','aacApprovalIconQuarter':'fourth'
},{'name':'af','aacApprovalIconQuarter':'fifth'
},{'name':'ag','aacApprovalIconQuarter':'sixth'}];
}]);
angular.module('programApp.filters', []).filter('advFilterName', function(){
return function(entries, advancedFiltersy, quarters){
var advFiltered = [];
angular.forEach(entries, function (entry){
if(quarters.indexOf(advancedFiltersy) > quarters.indexOf(entry.aacApprovalIconQuarter)){
}else{
advFiltered.push(entry);
};
});
};
});
None of the ng-repeated items are ever showing, so the filter isn't working properly. What do I need to do to get the filter working?
Here's a Codepen of it: http://codepen.io/trueScript/pen/MwbVpO

You still need to return the value of the filtered results:
angular.module('programApp.filters', []).filter('advFilterName', function(){
return function(entries, advancedFiltersy, quarters){
var advFiltered = [];
angular.forEach(entries, function (entry){
if(quarters.indexOf(advancedFiltersy) > quarters.indexOf(entry.aacApprovalIconQuarter)){
}else{
advFiltered.push(entry);
};
});
// Fix
return advFiltered;
};
});
Fixed here: http://codepen.io/anon/pen/LVbdQo?editors=101

Related

How to use AngularJS custom filter and lodash

Using Angular v1.5.8 with lodash. I set up a custom filter on an array in ng-repeat. I have a checkbox too when it's checked, the filter will remove a certain element from the ng-repeat and when is unchecked, that element will be re-added to the ng-repeat.
Beside the checkbox condition, the filter contains applies angular's filter filter to always remove some elements.
The angular app:
angular.module('app', [])
.controller('appCtrl', ['$scope',
function($scope) {
$scope.newArray = [1,2,3,4,5];
}])
.filter('simpleFilter', function($filter){
return function(newArray,checked){
newArray = $filter('filter')(newArray, '!4');
if(checked){
_.remove(newArray, function(elem){
return elem == 2;
});
}
return newArray;
}
});
and the html:
<div ng-app="app">
<div ng-controller="appCtrl">
<span ng-repeat="el in newArray | simpleFilter:obj.checked">
{{el}}
</span>
<hr>
<input type="checkbox" ng-model="obj.checked">
</div>
</div>
The example above working smoothly, but if I remove the default filter from the custom filter (this line: newArray = $filter('filter')(newArray, '!4');) and the checkbox is rechecked, the element hidden by _.remove will not reappear.
Here is the issue: https://codepen.io/neptune01/pen/rzbLmp
You have to use _filter lodash method instead of _remove.
Unlike _.filter, _remove method mutates original array.
angular.module('app', [])
.controller('appCtrl', ['$scope',
function($scope) {
$scope.newArray = [1,2,3,4,5];
}])
.filter('simpleFilter', function($filter){
return function(newArray,checked){
//newArray = $filter('filter')(newArray, '!4');
if(checked){
newArray=_.filter(newArray, function(elem){
return elem != 2;
});
}
return newArray;
}
});
Here is working solution.
You can also use $filter method in order to obtain a more lighty solution.
if(checked)
newArray = $filter('filter')(newArray, '!2');
return newArray;

Display checkboxes in with AngularJS based on two object arrays

I know there are several similar topics already but I found none that really matches my problem.
When opening my AngularJS app/website I am loading two arrays of objects (both are of the same type). One list contains all possible values (called sources here) and the other list is a selection of elements from the first.
My goal is display all sources as checkboxes. The ones from the second list have to be preselected, the rest not. Now the user can select/deselect checkboxes. If he does so I need to inform the server (with the source.id).
What I got so far:
exampleApp.controller('testController', [ '$scope', '$http', function($scope, $http) {
$scope.sources = [];
$scope.selectedSources = [];
$scope.changeSource = function(source) {...};
})
and
<div ng-repeat="source in sources">
<input
type="checkbox"
name="source.name"
value="{{source.id}}"
ng-model="??"
ng-change="changeSource(source.id)"
> {{source.name}}
</div>
What I can't figure out is how I can get ng-model to preselect the right checkboxes and how to get the new (and old) values to changeSource(). Is there an elegant way of doing that?
Example (Pseudo code only):
Sources = [{id=1, name=test1},{id=2, name=test2}, ...]
SelectedSources = [{id=2, name=test2}]
Now what I need are checkboxes like this:
[ ] test1 [x] test2
where all elements from sources are checkboxes and the ones from selectedsources are preselected. Changes of the selection can be stored in selected sources (as objects) and have to trigger my changeSource() function so that I can inform my server.
Set the selected/unselected state in a property inside each of the objects in Sources array(initialize it based on whats present in selectedArray)
$scope.sources.forEach(function(source) {
source.selected = isSelected(source);
})
function isSelected(selectedSource) {
return !!$scope.selectedSources.find(function(s) {
return s === selectedSource || s.id == selectedSource.id;
})
}
Here's a working plunker link
I didn't understood your question very well, but if i'm not mistaken, you want to fill the second collection only with the selected items from the first one, right? If it's the case, you could turn your second collection into a returning function with a filter of the first inside, as follows:
In your controller:
exampleApp.controller('testController', [ '$scope', '$http', function ($scope, $http) {
$scope.sources = [];
/* ... */
$scope.getSelectedSources = function () {
return $scope.sources.filter(function (val) {
return val.selected;
});
};
})
In your template:
<div ng-repeat="source in sources">
<input
type="checkbox"
name="source.name"
value="{{source.id}}"
ng-model="source.selected"
ng-change="changeSource(source.id)"
> {{source.name}}
</div>
<div ng-repeat="source in getSelectedSources()">
<input
type="checkbox"
name="source.name"
value="{{source.id}}"
ng-model="source.selected"
ng-change="changeSource(source.id)"
> {{source.name}}
</div>
Hi this may be help you to get new & old value.
$scope.$watch('sources', function (oldval, newval) {
console.log(oldval + newval);
});

Semantic UI dropdown with angular not clear selected value

I've created a small sample of what is happening.
http://plnkr.co/edit/py9T0g2aGhTXFnjvlCLF
Basically, the HTML is:
<div data-ng-app="app" data-ng-controller="main">
<select class="ui dropdown" id="ddlState" data-ng-options="s.name for s in states track by s.id" data-ng-model="selectedState"></select>
<select class="ui dropdown" id="ddlCity" data-ng-options="c.name for c in cities track by c.id" data-ng-model="selectedCity"></select>
</div>
And the javascript is:
angular.module("app", [])
.controller("main", function($scope, $timeout) {
$scope.selectedState = {id:1,name:"A"};
$scope.selectedCity = {id:1,name:"A.1",stateId:1};
$scope.states = [{id:1,name:"A"},{id:2,name:"B"},{id:3,name:"C"}];
var fakeDataSource = [
{id:1,name:"A.1",stateId:1},
{id:2,name:"A.2",stateId:1},
{id:3,name:"A.3",stateId:1},
{id:4,name:"B.1",stateId:2},
{id:5,name:"B.2",stateId:2},
{id:6,name:"B.3",stateId:2},
{id:7,name:"C.1",stateId:3},
{id:8,name:"C.2",stateId:3},
{id:9,name:"C.3",stateId:3}
];
$scope.$watch("selectedState", function(n,o){
if (n !== o)
$scope.selectedCity = null;
$scope.cities = fakeDataSource.filter(function(x){
return n.id === x.stateId;
});
$timeout(function(){
$(".ui.dropdown").dropdown().dropdown("refresh");
});
})
$timeout(function(){
$(".ui.dropdown").dropdown();
})
})
The problem is when I change the first dropdown to value 'B' or 'C', the value of second dropdown does not change, even it is changed in angular model.
You guys can notice that I've the line $(".ui.dropdown").dropdown().dropdown("refresh") to refresh the values but does not work.
I tried destroy and recreate using $(".ui.dropdown").dropdown("destroy").dropdown() but still does not work.
Any help?
Simply using ngModel won't make the values change dynamically. Take a look at the documentation here: https://docs.angularjs.org/api/ng/directive/ngModel
You can bind the values using ngBind or what I have done is do an onChange to then check the value and change your second drop down accordingly. Something like:
$("#ddlState").on("change", function(e) {
//check $scope.selectedState for it's value, and change #ddlCity/$scope.selectedCity accordingly
});

collect filtered ng-repeat data to use in controller

I am trying to build a picture library in a responsive grid with data coming down from a Mongo DB. Data from db is in this form. name, image, keyword, bio, reference", searchable,
I start with an ng-repeat to display category selection checkboxes based on the picture keywords. This seems to work fine.
p CATEGORIES:
span.formgroup(data-ng-repeat='category in mongoController.catData')
input.checks( type='checkbox', ng-model='mongoController.filter[category]')
| {{category}}
Here is the factory that sorts and identifies the keyword checkboxes:
getCategories: function (cat) {
return (cat || []).map(function (pic) {
return pic.keyword;
}).filter(function (pic, idx, array) {
return array.indexOf(pic) === idx;
});
}
From there I filter an ng-repeat to display pictures based on the checkbox selection, and/or a search field which works well also.
input.form-control.input-med(placeholder="Search" type='text', ng-model="search.searchable")
br
div.light.imageItem(data-ng-repeat="picture in filtered=( mongoController.allData | filter:search | filter:mongoController.filterByCategory)")
a(data-toggle="modal", data-target="#myModal", data-backdrop="static", ng-click='mongoController.selectPicture(picture)')
img( ng-src='../images/{{picture.image}}_tn.jpg', alt='Photo of {{picture.image}}')
p Number of results: {{filtered.length}}
Functions to display picture lists:
//Returns pictures of checkboxes || calls the noFilter function to show all
mongoController.filterByCategory = function (picture) {
return mongoController.filter[picture.keyword] || noFilter(mongoController.filter);
};
function noFilter(filterObj) {
for (var key in filterObj) {
if (filterObj[key]) {
return false;
}
}
return true;
}
If you click one of the pictures a modal box pops up with all of the input fields where you can edit image specific fields.
The part I am really struggling with is how to gather the usable data from the filtered ng-repeat to use in the controller so when the modal box is up I can scroll right or left through the other pictures that met the criteria of the search.
Any suggestions would help, even why the hell are you doing it this way?
When you declare the ng-repeat that filters the pictures, your filtered variable belongs to the current $scope (which I cannot infer from the question, as it stands). You could associate the filtered variable to a specific controller by using Controller As syntax: (i.e. using <elem ng-repeat="picture in ctrl.filtered = (ctrl.data | filter1 | filterN)"/>)
Example: (also in jsfiddle)
var mod = angular.module('myapp', []);
mod.controller('ctrl', function() {
var vm = this;
vm.data = ['alice', 'bob', 'carol', 'david', 'ema'];
vm.onbutton = function() {
// access here the filtered data that mets the criteria of the search.
console.log(vm.filtered);
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myapp" ng-controller="ctrl as vm">
<input ng-model="search" type="text" />
<p data-ng-repeat="item in vm.filtered = (vm.data | filter:search)">
{{item}}
</p>
<p>Items: {{vm.filtered.length}}</p>
<button ng-click="vm.onbutton()">Show me in console</button>
</div>

JSON populated form elements not filtering using angularJs filter

The Select element does get populated by the http request, but the options in the select element are not updating as the ng-model is changed. I am new to angularJs so im assuming its a simple fix. I have tried many variation with no positive results.
<script>
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope, $http) {
$http.get('http://graph.facebook.com/platform')
.success(function(data) {
})
});
</script>
<body ng-controller="MainCtrl">
Search:
<input type="search" ng-model="searchText" />
<select>
<option ng-repeat="item in data | filter: searchText">{{item}}</option>
</select>
<br>
<pre>{{ data | json}}</pre>
</body>
http://plnkr.co/edit/C39yVDsG3OcfvwjVSxP9?p=preview
TarranJones, this Plunker should clear things up. Hard to give you a 100% clear answer without a look at your data. You should be able to figure it out from here.
http://plnkr.co/edit/UYm0SwtU6ePZkZLx2w2U?p=preview
To Answer your question in the comments I would replace:
app.controller('MainCtrl', function($scope) {
$scope.colors = [
{name:'black', shade:'dark'},
{name:'white', shade:'light'},
{name:'red', shade:'dark'},
{name:'blue', shade:'dark'},
{name:'yellow', shade:'light'}
];
});
With:
app.controller('MainCtrl', function($scope, $http) {
$http.get('http://www.foo.com')
.success(function(data) {
$scope.colors = data;
})
.error(function() {
console.log('My name is Error, now eat it!);
});
});
Make sure to inject the $http.
Plunker here. http://plnkr.co/edit/UYm0SwtU6ePZkZLx2w2U?p=preview
UPDATE:
Tarran also ran into the problem of filtering a single returned JSON object from an API. Angular Filters can only accept arrays and so would not accept the object. In order for Tarran to filter the object he must first iterate through the object and store the object properties to an array. Once the array is then returned to the $scope you can filter the results. The plunker and code is provided below: http://plnkr.co/edit/9M3zZFN5jyV8w7fg7EE3?p=preview
Controller:
$http.get('http://graph.facebook.com/4')
.success(function(data) {
//CREATE AN EMPTY ARRAY
result = [];
//ITERATES THROUGH THE OBJECT SAVING THE OBJECTS PROPERTIES TO ARRAY
for (var i in data) {
if (data.hasOwnProperty(i)) {
//PUSHES THE PROPERTIES ONTO THE ARRAY
result.push(data[i]);
}
}
//SETS THE NEW DATASET TO THE ARRAY AND RETURNS TO $SCOPE
$scope.dataset = result;
});
HTML:
{{dataset}}
<BR>
<BR>Search:
<input type="search" ng-model="searchText" />
<BR>
<BR>
<select>
<option ng-repeat="data in dataset | filter: searchText">{{data}}</option>
</select>
Try to init your data as object before all.
$scope.data = {}
Or in HTML :
<div ng-controller="FetchCtrl" data-ng-init="data={}; fetch()">

Categories

Resources