Chaining multiple filters with AngularJS - javascript

I am working on chaining multiple filters, but while thinking it through i realised that it creates an extreme amount of code (redudancy would be the best term in this use-case), which made me wonder if this could be done more dynamically/generalized. Basically i have 5-6 dropdown menu where a user can select one or more options to filter the data with. I have made this based on one dropdown menu but i want to extend this further. In this code sample i have one dropdown menu which sorts out based on one column.
JavaScript:
<script>
'use strict';
var App = angular.module('App',['ngResource','App.filters']);
App.controller('ExerciseCtrl', ['$scope','$http', function($scope, $http) {
$scope.selectedMainMuscle = [];
$http.get('/rest/exercises/')
.then(function(res){
$scope.exercises = res.data;
});
$scope.orderProp = 'name';
$http.get('/rest/muscles/')
.then(function(res){
$scope.muscles = res.data;
});
$scope.isChecked = function () {
if (_.contains($scope.selectedMainMuscle, this.muscle.id)) {
return 'glyphicon glyphicon-ok pull-right';
}
return false;
};
$scope.setSelectedMainMuscle = function () {
var id = this.muscle.id;
if (_.contains($scope.selectedMainMuscle, id)) {
$scope.selectedMainMuscle = _.without($scope.selectedMainMuscle, id);
} else {
$scope.selectedMainMuscle.push(id);
}
return false;
};
}]);
angular.module('App.filters', []).filter('mainMuscleFilter', [function () {
return function (exercises, selectedMainMuscle) {
if (!angular.isUndefined(exercises) && !angular.isUndefined(selectedMainMuscle) && selectedMainMuscle.length > 0) {
var tempClients = [];
angular.forEach(selectedMainMuscle, function (id) {
angular.forEach(exercises, function (exercise) {
if (angular.equals(exercise.main_muscle.id, id)) {
tempClients.push(exercise);
}
});
});
return tempClients;
} else {
return exercises;
}
};
}]);
</script>
HTML:
<div class="btn-group" ng-class="{open: dd2}">
<button type="button" class="btn btn-default dropdown-toggle" ng-click="dd2=!dd2">Main muscle <span class="caret"></span></button>
<ul class="dropdown-menu">
<li ng-repeat="muscle in muscles">
<a href ng-click="setSelectedMainMuscle()">{%verbatim%}{{muscle.name}}{%endverbatim%} <span data-ng-class="isChecked()"></span></a>
</li>
</ul>
</div>
<table class="table table-hover" >
<tr><td><strong>Name</strong></td><td><strong>Main muscle</strong></td><td><strong>Equipment</strong></td></tr>
<tr ng-repeat="exercise in filtered = (exercises | mainMuscleFilter:selectedMainMuscle)">
{%verbatim%}<td>{{exercise.name}}</td><td>{{exercise.main_muscle.name}}</td><td>{{exercise.equipment.name}}</td>{%endverbatim%}
</tr>
</table>

I would do all the checks in one filter, I don't see how a mainMuscleFilter would be reusable enough to warrant separation, let alone inclusion in a separate module. You can generalize your methods to toggle the inclusion of an id in an array and to check for the inclusion though:
$scope.selected = {
muscle: [],
equipment: []
};
$scope.isChecked = function (arr, id) {
if (_.contains(arr, id)) {
return 'glyphicon glyphicon-ok pull-right';
}
return false;
};
$scope.toggleInclusion = function (arr, id) {
var index = arr.indexOf(id);
if (index >= 0) {
arr.splice(index, 1);
} else {
arr.push(id);
}
return false;
};
HTML:
<li ng-repeat="muscle in muscles">
<a href ng-click="toggleInclusion(selected.muscle, muscle.id)">
{{muscle.name}}
<span data-ng-class="isChecked(selected.muscle, muscle.id)"></span>
</a>
</li>

Related

How to prevent multiple time click on anchor tag in AngularJS?

I have created sharing functionality it will be work but
//HERE WE CREATE THE CONTOLLER FOR SHARING
$scope.selectedSharedBuyerKeyList = [];
$scope.selectedSharedBuyerObjectList = [];
$scope.productObjectForShareModal = [];
$scope.getConnectedSharedUser = function(product) {
$scope.productObjectForShareModal = product;
var data = {
productKeyId : $scope.productObjectForShareModal.keyId
}
//Call the getSharedUserList function for get the detail of the shared connectedUsers
SellerDashboardService.getSharedUserList(function(response) {
if(response != null) {
if (response.data.isProduct) {
$scope.selectedSharedBuyerKeyList = response.data.sellerProductsDto;
// Obtaining user object..
$scope.selectedSharedBuyerObjectList = [];
for(var selectedSharedBuyerKey of $scope.selectedSharedBuyerKeyList) {
var data = selectedSharedBuyerKey;
//call the getBuyerInShared for get the list of the objects
SellerDashboardService.getBuyerInShared(function(response) {
if(response != null) {
if (response.data.isbuyer) {
var buyerObject = response.data.isbuyer;
$scope.selectedSharedBuyerObjectList.push(buyerObject);
}
}
},data);
}
}
}
},data);
}
<a href="#" class="fa fa fa-group btn btn-xs pull-left bg-color-d4"
data-toggle="modal" data-target="#groupModal"
ng-click="getConnectedSharedUser(productDBList)">
</a>
list is repeated after multiple time click on the a tag and user list is repeated again and again.so tell me how to resolve the repeatation problem?
Try this
$scope.selectedSharedBuyerObjectList = [];
$scope.productObjectForShareModal = [];
$scope.cliked=false ///set click to false
$scope.getConnectedSharedUser = function(product) {
$scope.productObjectForShareModal = product;
var data = {
productKeyId : $scope.productObjectForShareModal.keyId
}
//Call the getSharedUserList function for get the detail of the shared connectedUsers
SellerDashboardService.getSharedUserList(function(response) {
$scope.clicked =true; ///set it back to true
if(response != null) {
if (response.data.isProduct) {
$scope.selectedSharedBuyerKeyList = response.data.sellerProductsDto;
// Obtaining user object..
$scope.selectedSharedBuyerObjectList = [];
for(var selectedSharedBuyerKey of $scope.selectedSharedBuyerKeyList) {
var data = selectedSharedBuyerKey;
//call the getBuyerInShared for get the list of the objects
SellerDashboardService.getBuyerInShared(function(response) {
if(response != null) {
if (response.data.isbuyer) {
var buyerObject = response.data.isbuyer;
$scope.selectedSharedBuyerObjectList.push(buyerObject);
}
}
},data);
}
}
}
},data);
}
<a href="#" class="fa fa fa-group btn btn-xs pull-left bg-color-d4"
data-toggle="modal" ng-disabled="cliked" data-target="#groupModal"
ng-click="getConnectedSharedUser(productDBList)">
</a>
What I did in angular 2 is I have Disabled the button on the first click.
E.g.
<button (click)="someFunction()" [disabled]="disableButton"></button>
someFunction() {
disableButton = true;
}
Note: Syntax would be different in your case but logic will be same.
I hope this will help.

In angular js How to do an edit option?

I am trying to do an edit field in angular js but I don't know how to do that one help me
below is my Crud operation code
var app = angular.module('myApp', [])
app.controller('myCtrl', ['$scope', function($scope) {
$scope.products = ["venu", "balaji", "suresh"];
$scope.addItem = function() {
$scope.errortext = "";
if (!$scope.addMe) {
return;
}
if ($scope.products.indexOf($scope.addMe) == -1) {
$scope.products.push($scope.addMe)
} else {
$scope.errortext = "The item is already in your names list.";
}
}
$scope.removeItem = function(x) {
$scope.errortext = "";
$scope.products.splice(x, 1);
}
}])
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp">
<div ng-controller="myCtrl">
<ul>
<li ng-repeat="x in products">{{x}}<span ng-click="removeItem($index)">×</span>
</li>
</ul>
<input ng-model="addMe">
<button ng-click="addItem()">ADD</button>
<p>{{errortext}}</p>
<p>Try to add the same name twice, and you will get an error message.</p>
</div>
</div>
I am doing crud operations in angular js. i have done Delete and Add but I dont know how to do Edit operation in angular js
var app = angular.module('myApp', [])
app.controller('myCtrl', ['$scope', function($scope) {
$scope.products = ["venu", "balaji", "suresh"];
$scope.addItem = function() {
$scope.errortext = "";
if (!$scope.addMe) {
return;
}
if ($scope.products.indexOf($scope.addMe) == -1) {
$scope.products.push($scope.addMe)
} else {
$scope.errortext = "The item is already in your names list.";
}
$scope.addMe = "";
}
$scope.removeItem = function(x) {
$scope.errortext = "";
$scope.products.splice(x, 1);
}
$scope.edit = function(index){
$scope.addMe = $scope.products[index];
$scope.products.splice(index, 1);
}
}])
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp">
<div ng-controller="myCtrl">
<ul>
<li ng-repeat="x in products">{{x}}
<span ng-click="removeItem($index)">×</span>
<span style="color:blue;cursor:pointer;" ng-click="edit($index)">Edit</span>
</li>
</ul>
<input ng-model="addMe">
<button ng-click="addItem()">ADD</button>
<p>{{errortext}}</p>
<p>Try to add the same name twice, and you will get an error message.</p>
</div>
</div>
Try this.
The solution is here:
HTML
<li ng-repeat="x in products" ng-click="preEdit(x, $index)">{{x}}<span ng-click="removeItem($index)">×</span></li>
<input ng-model="addMe">
<button ng-if="isAdd" ng-click="addItem()">ADD</button>
<button ng-if="!isAdd" ng-click="editItem()">EDIT</button>
JS
$scope.isAdd = true;
$scope.preEdit = preEdit;
var index = '';
function preEdit(x, i){
$scope.addMe = x;
index = i;
$scope.isAdd = false;
}
$scope.editItem = editItem ;
function editItem (){
$scope.products[index] = $scope.addMe;
$scope.isAdd = true;
$scope.addMe = '';
index = '';
}
Look my solution in filddle: https://jsfiddle.net/tfx8njw6/
At first you need to add a edit option on the <li> say,
<ul>
<li ng-repeat="x in products">{{x}}
<span ng-click="removeItem($index)">×</span>
<span ng-click="editItem($index)">Edit</span>
</li>
</ul>
Then add a controller function for edit editItem() like
$scope.editItem= function(index) {
$scope.addMe = $scope.products[index];
//this variable will allow you to check whether the operation is an edit or add
$scope.editIndex = index;
}
You can then reuse your addItem() function like this
$scope.addItem = function() {
$scope.errortext = "";
if (!$scope.addMe) {
return;
}
if(angular.isDefined($scope.editIndex)){
$scope.products[$scope.editIndex] = $scope.addMe;
//reset the variable to undefined after using it
$scope.editIndex = undefined;
}else{
if ($scope.products.indexOf($scope.addMe) == -1) {
$scope.products.push($scope.addMe);
} else {
$scope.errortext = "The item is already in your names list.";
}
}
}
If you want to take it to the "next level", check out xeditable. :)
https://vitalets.github.io/angular-xeditable/#text-simple
Good luck!
For Edit what you can do:
0.Pass the id on edit click and get data of that id and assign to the same variable you have used for add and hide add button and show update button.
1.Either use the same text field which you are using for add and show/hide button add/update accordingly.
2.You can use separately div which includes one text box and button to update.Show/hide as per you action.

Angular 1.5 when select all in input checkbox, value won't bind to model

Hi I am using https://vitalets.github.io/checklist-model/ to bind data from a checkbox to the model. When a user selects a checkbox it successfully binds data. However, I need the options to also "select all" I have followed the instructions in the documentation and have tried mapping all the value in the array so when the user "selects all" all the values are binded into the model. Instead of that happening I get an array with value of null. Here is how the flow works
1)init() function is called returning data when the user loads the application
2)user selects an air_date
3)user gets syscode data return after ng-options getSyscodes() is called
4)A user can select multiple syscodes
5)User can "select all" this is where my issue is, when I call selectAll(), instead of returning every value in array, the array returns as "null" and I can't make a call to the API.
I would appreciate any suggestions thanks!
Here is my HTML
Array Structure of Every Object
{syscode:1233,readable_name: "MTV"}
<form>
<div class="form-group">
<pre>Selected Model: {{rc.selections.syscode}} </pre>
<label>Syscode</label>
<!-- <select class="form-control" ng-options="syscode.readable_name for syscode in rc.dropdowns.syscodes" ng-model="rc.selections.syscode" ng-disabled="rc.dropdowns.syscodes.length === 0">
</select> -->
</div>
<button type="button" class="btn btn-default btn-sm dropdown-toggle" data-toggle="dropdown" style="width:214px;height:33px;font-size:15px;margin-left:-16px;"><i class="fa fa-caret-down pull-right" aria-hidden="true" style="width:1em;"></i></button>
<ul class="dropdown-menu">
<button class="btn btn-success btn-md" ng-click="rc.selectAll()"><i class="fa fa-check" aria-hidden="true"></i>Select All</button>
<button class="btn btn-danger btn-md" ng-click="rc.unselectAll()"><i class="fa fa-times" aria-hidden="true"></i>Unselect All</button>
<li ng-repeat="value in rc.dropdowns.syscodes">
<input type="checkbox" checklist-model="rc.selections.syscode" checklist-value="value.syscode" ng-checked="rc.selections.checked" /> {{value.readable_name}}</li>
</ul>
</form>
And Controller
ReportsController.$inject = ['ReportService','$window', '$q'];
function ReportsController(ReportService, $window, $q){
//Sorting Values
var ctrl = this;
//Initial State Values
ctrl.results = [];
ctrl.pageDone = false;
ctrl.loading_results = false;
ctrl.search_enabled = false;
ctrl.searching = false;
//Initial data arrays
ctrl.dropdowns = {
air_dates:[],
syscodes:[],
syscodeArray:[]
};
ctrl.test = null;
//Data binding objects
ctrl.selections = {
air_date:null,
checked: null,
syscode:null,
getAll: false
};
//Get Syscodes
ctrl.selectSyscode = function(){
ctrl.search_enabled = true;
ctrl.dropdowns.syscodes = [];
ctrl.dropdowns.syscodeArray = [];
ReportService.getSyscodes(ctrl.selections).then(function(response){
ctrl.dropdowns.syscodes = response.data;
//This line below enables select all in UI
ctrl.dropdowns.syscodeArray.push(response.data);
console.log("SyscodeArray", ctrl.dropdowns.syscodeArray);
});
};
// Select All Logic
ctrl.selectAll = function(){
var newitems = [];
angular.forEach(ctrl.dropdowns.syscodes, function(syscode) {
ctrl.selections.checked = 1;
newitems.push(syscode.syscode);
});
ctrl.selections.syscode = newitems;
}
// Unselect All
ctrl.unselectAll = function(){
angular.forEach(ctrl.dropdowns.syscodeArray, function(user) {
ctrl.selections.checked = 0;
});
ctrl.selections.syscode = [];
}
//Search Logic by Syscode and Air_Date
ctrl.search = function () {
var defer = $q.defer();
if (ctrl.search_enabled) {
ctrl.searching = true;
ctrl.error = false;
ctrl.sort_by = {
col: 'market',
reverse: true
};
ctrl.filters = undefined;
ReportService.getAssets(ctrl.selections).then(function (response) {
ctrl.results = response.data;
console.log("It worked!!!",response.data);
ctrl.searched_once = true;
ctrl.searching = false;
defer.resolve('searched');
}, function (error) {
defer.reject('search-error');
ctrl.error = true;
ctrl.searching = false;
ctrl.error_data = error;
});
} else {
defer.resolve('no-search');
}
return defer.promise;
};
//Calls initial air dates
var init = function(){
ReportService.getAirDates().then(function(response){
ctrl.dropdowns.air_dates = response.data;
console.log(response.data);
ctrl.pageDone = true;
});
};
init();
}
angular.module('command-center-app').controller('ReportsController', ReportsController);
I tried this, I looped through the array and made a new array containing only "syscode". That array I assigned it ctrl.selections.syscode which is the model. This should be the correct answer
ctrl.selectAll = function(){
var newitems = [];
angular.forEach(ctrl.dropdowns.syscodes, function(syscode) {
ctrl.selections.checked = 1;
newitems.push(syscode.syscode);
});
ctrl.selections.syscode = newitems;
}
There is something wrong with your implementation i think. The library uses an array to handle the checked values in it. But i don't think you are doing that. Plus ng-checked should be there. So:
<li ng-repeat="value in rc.dropdowns.syscodes">
<input type="checkbox" checklist-model="rc.selections.checked" checklist-value="value.syscode" />
{{value.readable_name}}
</li>
In the controller:
// Select All Logic
ctrl.selectAll = function(){
ctrl.selections.checked = [];
angular.forEach(ctrl.dropdowns.syscodeArray, function(user) {
ctrl.selections.checked.push( //iterate over all syscodes and push here
});
}
// Unselect All
ctrl.unselectAll = function(){
ctrl.selections.checked = [];
}
Let me know how it goes.

Angularjs How to Toggle div's in ng-repeat?

I am working in angularjs and I need to toggle div in ng-repeat but its not working fine. jQuery click is also not working on this. On click of pregroupMem() anchor tag I am calling this function. and data id coming from this function and I am using this as membersList in listdiv div. I need to toggle this div on click of "custom-cn" anchor tag.There are multiple lists and in each of these lists there are there multiple listdivs . I need to toggle the particular div on the click of anchor tag of list.
This is my js to get all groups of members.
localStorageService.set('grpOpen', grps.openGroups);
localStorageService.bind($scope, 'grpOpen');
grs.init = init;
function init()
{
getMyData();
}
$scope.data = null;
DataService.getMyData().then(function successCallback(response)
{
$scope.data = response.data.results;
$scope.grpOpen.length = 0;
$scope.grpOpen.push({'data': response.data.results});
},function errorCallback(response) {
});
This is js to get all members list of a group.I have updated this according to your
$scope.open = -1;
$scope.pregroupMem = function(index,id,e){
$rootScope.membersList = '';
// $rootScope.membersList.length = 0;
$scope.loading= true;
DataService.getGrpMem(id).success(function (data) {
$rootScope.membersList = data.results;
$scope.data[index].shown = !$scope.data[index].shown;
if( $scope.open >= 0 && $scope.data[$scope.open] ){
$scope.data[$scope.open].shown = !$scope.data[$scope.open].shown;
}
if( $scope.open !== index ){
$scope.data[index].shown = !$scope.data[index].shown;
}
$scope.open = index;
}).catch(function (err) {
// Log error somehow.
})
.finally(function () {
// Hide loading spinner whether our call succeeded or failed.
$scope.loading = false;
});
}
<ul>
<li ng-repeat="groupsw in grpOpen[0].data track by $index">
<a ng-click="pregroupMem($index,groupsw.grpId,$event)" class="custom-cn" href="javascript:;">{{ groupsw.grpName }}</a>
<div class="listdiv">
<ul class="userlist">
<li ng-repeat="mymembers in membersList">
<a class="add_user" href="javascript:;"><i class="fa fa-user-plus"></i></a>
<div class="userlist">
<span class="usnermalissval" ng-if="mymembers.Name != null">{{mymembers.Name}}</span>
</div>
</li>
</ul>
</div>
</li>
</ul>
You can do it in following way:
angular
.module('app', [])
.controller('MyController', function($scope) {
$scope.data = [
{grpId: 1, grpName: 'One'},
{grpId: 2, grpName: 'Two'},
{grpId: 3, grpName: 'Three'},
{grpId: 4, grpName: 'Four'},
{grpId: 5, grpName: 'Five'}
]
$scope.open = -1;
$scope.pregroupMem = function(index, id, e) {
e.preventDefault();
if( $scope.open >= 0 && $scope.data[$scope.open] ){
$scope.data[$scope.open].shown = !$scope.data[$scope.open].shown;
}
if( $scope.open !== index ){
$scope.data[index].shown = !$scope.data[index].shown;
}
$scope.open = index;
}
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
<ul ng-controller="MyController">
<li ng-repeat="groupsw in data">
<a ng-click="pregroupMem($index, groupsw.grpId, $event)" class="custom-cn" href="javascript:;">{{ groupsw.grpName }}</a>
<div class="listdiv" ng-show="groupsw.shown">
<ul class="userlist">
This is a child div of grpId: {{groupsw.grpId}}
</ul>
</div>
</li>
</ul>
</div>

AngularJS searchbox directive or how to avoid code duplication in controller

I'm working on multiple school student management application. The are multiple roles: school manager and super manager.
The school manager can only search students in his school while super manager can search for student in all schools.
Because the search is done only by removing the school id in second case, I think that the same searchbox can be used, and the same functions for searching.
This is the template:
<div class="input-group">
<div class="input-group-btn">
<button type="button" class="btn btn-default" tabindex="-1">{{ searchBy | translate }}</button>
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" tabindex="-1">
<span class="caret"></span>
<span class="sr-only">Toggle Dropdown</span>
</button>
<ul class="dropdown-menu" role="menu">
<li ng-repeat="value in searchByFields"><a ng-click="searchByAttr(value)">{{ value | translate }}</a></li>
</ul>
</div>
<form ng-submit="search(searchValue)">
<input type="text"
ng-model="searchValue"
class="form-control"
placeholder="Search.." />
</form>
<span class="input-group-btn">
<button class="btn btn-warning" type="button">
<i class="fa fa-search fa-fw"></i>
</button>
</span>
</div>
This is the controller scope functions and variables, that is used in search:
$scope.searchBy = 'cn';
$scope.searchByFields = ['cn', 'ou', 'o'];
$scope.searchByAttr = function (value) {
$scope.searchBy = value;
}
var searchFn = function (params) {
User.search(params).success(function (data) {
$scope.students = data.results;
$scope.collapsedTableRows = [];
_.each($scope.students, function () {
$scope.collapsedTableRows.push(true);
});
}).error(function (reason) {
$scope.students = [];
$scope.collapsedTableRows = [];
var log = Logger.getInstance("AdminController(searchFn)");
var error = reason[0];
log.error('name - \"{0}\", location - \"{1}\", error - \"{2}\"',
[error.name, error.location, error.description]);
});
}
$scope.search = function (value) {
if(value) {
var params = {
search: [
{attr: 'orgId', value: $injector.get('ORG_DN').replace('%id%', $scope.schoolId) },
{attr: $scope.searchBy, value: '*' + value + '*' }
]
};
searchFn(params);
}
}
As you can see, my search results are stored in scope variables, which are used in table directive. I have the same code in two controllers, which is annoying.
How should I construct directive from what I have for search, so that I can pass scope variables to directive and get data from it for my other directive to work correctly?
Create a angular service: Source Tutorial
Your factory can contain data manipulated in a single place, but it also has common operations. It's passable to a controller while creating the controller.
var app = angular.module('app', []);
app.service('MathService', function() {
this.add = function(a, b) { return a + b };
this.subtract = function(a, b) { return a - b };
this.multiply = function(a, b) { return a * b };
this.divide = function(a, b) { return a / b };
});
app.service('CalculatorService', function(MathService){
this.square = function(a) { return MathService.multiply(a,a); };
this.cube = function(a) { return MathService.multiply(a, MathService.multiply(a,a)); };
});
app.controller('CalculatorController', function($scope, CalculatorService) {
$scope.doSquare = function() {
$scope.answer = CalculatorService.square($scope.number);
}
$scope.doCube = function() {
$scope.answer = CalculatorService.cube($scope.number);
}
});

Categories

Resources