Filtering with multiple checkboxes in angularJS - angularjs

I'm new to AngularJS. I wrote a program to filter the Item list when i check related check boxes. But here my CheckBoxes are behaving like "Radio" buttons. Anyway, program is working but it is not working with multiple check boxes. Please help me.
My Program # http://plnkr.co/edit/iV7wyYoCNJdY1Ze7J6Pg?p=preview

Easy way
I would Set different models for both check boxes and add filter like:
<body data-ng-controller="TestController">
<table id="hotels">
<tr>
<th>Hotel Name</th>
<th>Star Rating</th>
<th>Hotel type</th>
<th>Hotel Price</th>
</tr>
<tr data-ng-repeat="hotel in hotels | filter:search.type1 | filter:search.type2">
<td>{{hotel.name}}</td>
<td>{{hotel.star}}</td>
<td>{{hotel.type}}</td>
<td>{{hotel.price}}</td>
</tr>
</table>
<br/>
<h4>Filters</h4>
<input type="checkbox" data-ng-model='search.type1' data-ng-true-value='luxury' data-ng-false-value='' /> Luxury
<input type="checkbox" data-ng-model='search.type2' data-ng-true-value='double suite' data-ng-false-value='' /> Double suite
</body>
Demo Plunker
Custom filter##
(I like it more)
We can bind the checkboxes to one object like:
$scope.types = {luxury: false, double_suite:false};
and after create custom filter like:
iApp.filter('myfilter', function() {
return function( items, types) {
var filtered = [];
angular.forEach(items, function(item) {
if(types.luxury == false && types.double_suite == false) {
filtered.push(item);
}
else if(types.luxury == true && types.double_suite == false && item.type == 'luxury'){
filtered.push(item);
}
else if(types.double_suite == true && types.luxury == false && item.type == 'double suite'){
filtered.push(item);
}
});
return filtered;
};
});
So our HTML now seems simple:
<body data-ng-controller="TestController">
<table id="hotels">
<tr>
<th>Hotel Name</th>
<th>Star Rating</th>
<th>Hotel type</th>
<th>Hotel Price</th>
</tr>
<tr data-ng-repeat="hotel in hotels | myfilter:types">
<td>{{hotel.name}}</td>
<td>{{hotel.star}}</td>
<td>{{hotel.type}}</td>
<td>{{hotel.price}}</td>
</tr>
</table>
<br/>
<h4>Filters</h4>
<input type="checkbox" data-ng-model='types.luxury' /> Luxury
<input type="checkbox" data-ng-model='types.double_suite' /> Double suite
<pre>{{types|json}}</pre>
</body>
Demo 2 Plunker
[EDIT for #Mike]
If you interesting to invert the check-box filter, just add directive (grabbed from HERE):
iApp.directive('inverted', function() {
return {
require: 'ngModel',
link: function(scope, element, attrs, ngModel) {
ngModel.$parsers.push(function(val) { return !val; });
ngModel.$formatters.push(function(val) { return !val; });
}
};
});
sow new HTML form:
<input type="checkbox" inverted data-ng-model='types.luxury' /> Luxury
<input type="checkbox" inverted data-ng-model='types.double_suite' /> Double suite
Demo 3 Plunker

If, like me you are not really familiar with custom filter and prefer a simpler solution, here is a simple example to bind data with ng-model of checkboxes in ng-repeat: tutorial here
It is a good example with ng-value-true and ng-value-false :
<div ng-repeat="fruit in fruits">
<input type="checkbox" ng-model="fruit.name" ng-true-value="{{fruit.name}}" ng-false-value="{{fruit-name}} - unchecked" ng-change="filterMultipleSystem()"/><br/>
</div>
The Javscript function:
$scope.filterMultipleSystem = function(){
setTimeout(function () {
var x = document.getElementsByClassName("firstLoop");
var i; for (i = 0; i < x.length; i++) {
if(x[i].title.indexOf("unchecked")!==-1){
x[i].style.display = "none";
}
else
x[i].style.display = "inherit"; }},10); }`;

Here is bit refined filter(edited for my needs from #Maxim Shoustin) where you can select by multiple arguments. If u had 3 types and needed select 2 of 3, you can use this, cause other doesnt work on that(tried myself):
app.filter('myfilter', function () {
return function (items, types) {
var filtered = [];
for (var i in items)
{
if (types.found == true && items[i].type == 'Found') {
filtered.push(items[i]);
}
else if (types.notfound == true && items[i].type == 'Not found') {
filtered.push(items[i]);
}
else if (types.moved == true && items[i].type == 'Moved') {
filtered.push(items[i]);
}
}
return filtered;
};
});

Related

Problem for using a textbox and radio buttons in order to filter a table in ng-reapeat Angularjs

I have a problem for filtering a table in AngularJS into ng-repeat.
I would like to add radio button (based on table column) under a search text field for adding more filters.
For the moment when I enter "char" in the text field, the system filters correctly the table and displays all results.
My goal: if I select the radio button "Person", only the results with the person containing "char" should appear. If I click on "company", the radio button "Person" should be unselected and only result with the company containing "char" should appear.
Here my view:
<div class="spacer input-group">
<div class="input-group-addon">
<span class="glyphicon glyphicon-search"></span>
</div>
<input type="text" ng-model="searchText" class="form-control" placeholder="Search name..." ng-change="search(searchText)"/>
<div class="input-group-btn">
<button class="btn btn-default" ng-click="razRecherche()">
<span class="glyphicon glyphicon-remove"></span>
</button>
</div>
</div>
<div>
<!-----------------HERE THE RADIO BUTTONS ----------- START --->
<input type="radio" name="filter" value="PERSON" ng-model="search.PERSON">
<label for="PERSON">Person</label>
<input type="radio" name="filter" value="COMPANY" ng-model="search.COMPANY">
<label for="COMPANY">Company</label>
<!-----------------HERE THE RADIO BUTTONS ------------- END --->
</div>
<div class="table-responsive" id="allContacts">
<table ng-show="contacts.length" class="table table-striped table-hover spacer">
<thead>
<tr>
<th class="colPerson">
Person
<span class="hSpacer" ng-class="cssChevronsTri('PERSON')"></span>
</th>
<th class="colCompany">
Company
<span class="hSpacer" ng-class="cssChevronsTri('COMPANY')"></span>
</th>
<th class="colDescription">
Description
<span class="hSpacer" ng-class="cssChevronsTri('REQUESTDESCRIPTION')"></span>
</th>
</tr>
</thead>
<tbody ng-repeat="contact in contacts | filter:searchText | orderBy:champTri:triDescendant">
<tr class="clickable">
<td class="colPerson" ng-click="selContact(contact,contact.ID)" ng-class="{sel:selIdx==$index}">{{contact.PERSON}}</td>
<td class="colCompany" ng-click="selContact(contact,contact.ID)">{{contact.COMPANY}}</td>
<td class="colDescription" ng-click="selContact(contact,contact.ID)">{{contact.REQUESTDESCRIPTION}}</td>
</tr>
</tbody>
</table>
</div>
My controller
app.controller('ctrlContacts', function ($scope, $timeout, ContactService){
$scope.search = function(searchText) {
$scope.reloadPreviousSearch = false;
if (!searchText.length) {
//alert("searchText empty");
}
if (searchText.length>2) {
$timeout(function () {
// RETRIEVE DATA FROM JSON OBJECT OF THE SERVER SEVICE AND A DB QUERY - OK
ContactService.fastSearch(searchText).success(function(contacts){
console.log("query fastSearch OK");
var length = contacts.length;
$scope.loading = false;
if (length == 0) {
$scope.searchButtonText = "No result";
}else {
$scope.searchButtonText = length + " results found";
}
// For the orderby date
for (var i=0; i<length; i++) {
if(contacts[i].REQUESTTRUEDATE!=""){
contacts[i].REQUESTTRUEDATE = new Date(contacts[i].REQUESTTRUEDATE.replace(/-/g,"/"));
}else{
contacts[i].REQUESTTRUEDATE=null;
}
}
$scope.contacts = contacts;
$scope.champTri='PERSON';
$scope.selIdx= -1;
$scope.selContact=function(contact,idx){
$scope.selectedContact=contact;
$scope.selIdx=idx;
window.location="#/view-contacts/" + idx;
}
$scope.isSelContact=function(contact){
return $scope.selectedContact===contact;
}
});
}, 1000);
}else{
$scope.contacts=null;
}
}
// SEARCH
$scope.searchText = null;
$scope.razRecherche = function() {
$scope.searchText = null;
$scope.contacts=null;
}
// SORT
$scope.champTri = null;
$scope.triDescendant = false;
$scope.personsSort = function(champ) {
if ($scope.champTri == champ) {
$scope.triDescendant = !$scope.triDescendant;
} else {
$scope.champTri = champ;
$scope.triDescendant = false;
}
}
$scope.cssChevronsTri = function(champ) {
return {
glyphicon: $scope.champTri == champ,
'glyphicon-chevron-up' : $scope.champTri == champ && !$scope.triDescendant,
'glyphicon-chevron-down' : $scope.champTri == champ && $scope.triDescendant
};
}
});
I'm trying to add the radio buttons for filtering the table from the text entered in the text field. But I don't know how to use them for filtering the table into the ng-repeat.
Could you please help me to add the filters on the text field (searchText) with the radio buttons?
Thank you in advance for your help.
you have to make the following edits:
Edit your radio buttons as follow :
<!-----------------HERE THE RADIO BUTTONS ----------- START --->
<input type="radio" name="filter" value="PERSON" ng-change ="chosefilter()"
ng-model=" filterType">
<label for="PERSON">Person</label>
<input type="radio" name="filter" value="COMPANY" ng-change ="chosefilter()"ng-model="filterType">
<label for="COMPANY">Company</label>
<!-----------------HERE THE RADIO BUTTONS ------------- END --->
your table as follow :
<tbody ng-repeat="contact in contacts | filter:searcher| orderBy:champTri:triDescendant">
inside your controller add this:
$scope.searchText="";
$scope.searcher={
PERSON:"",
COMPANY:"",
};
$scope.filterType="PERSON";
$scope.chosefilter=function()
{
console.log( $scope.filterType);
if( $scope.filterType=='PERSON')
{
$scope.searcher.PERSON=$scope.searchText;$scope.searcher.COMPANY="";
}
else if( $scope.filterType=='COMPANY')
{
$scope.searcher.COMPANY=$scope.searchText;$scope.searcher.PERSON="";
}
console.log($scope.searcher);
}
what i did that $scope.searcher variable must has properties the same as data content properties like PERSON and COMPANY . then in filter just write the name of the object like this : filter:[OBJECT NAME] ;
i did a small app to make your filter , so if there is errors please tell me to fix it .

How can I pass a Camunda process variable containing JSON from one form to the next?

I want to get json array Data from service and then display this data inside table (with checkboxes)
after that i want to get data ( which was checked by user , i mean checkbox was clicked) and put it another json Array and then wrap this variable as camVariable in order to export it for second user form,
i have tried this in several ways but can’t accomplish my goal, what should i change to make it possible?
here is my code:
camForm.on('form-loaded', function() {
camForm.variableManager.fetchVariable('jsonData');
});
camForm.on('variables-fetched', function() {
$scope.jsonData = camForm.variableManager.variableValue('jsonData');
});
var selectedDocuments=$scope.selectedDocuments=[];
$scope.content = '';
$scope.isChecked = function(id){
var match = false;
for(var i=0 ; i < $scope.selectedDocuments.length; i++) {
if($scope.selectedDocuments[i].id == id){
match = true;
}
}
return match;
};
$scope.sync = function(bool, item){
if(bool){
// add item
$scope.selectedDocuments.push(item);
} else {
// remove item
for(var i=0 ; i < $scope.selectedDocuments.length; i++) {
if($scope.selectedDocuments[i].id == item.id){
$scope.selectedDocuments.splice(i,1);
}
}
}
};
camForm.on('submit', function() {
camForm.variableManager.createVariable({
name: 'selectedDocuments',
type: 'json',
value:$scope.selectedDocuments
});
});
function toJsonValue(arr) {
var myJSON = "";
var FinalResult = JSON.stringify(arr);
myJSON = JSON.stringify({FinalResult});
var json=$scope.json={};
json=JSON.parse(myJSON);
return json;
}
$scope.toggle = function (index){
if($scope.jsonData[index].hidethis == undefined){
$scope.jsonData[index].hidethis = true;
}else{
$scope.jsonData[index].hidethis = !$scope.jsonData[index].hidethis;
}
}
</script>
<h2>My job List</h2>
<div class="container">
<table name ="table" class="table table-hover" style="width:100%;" cellspacing="0">
<thead>
<tr>
<th style="width:80px; height:25px;"><input style="width:25px; height:25px;" type="checkbox" onclick="checkAll(this)"></th>
<th style="width:140px;">id</th>
<th style="width:305px;">organizationNameEN</th>
<th style="width:305px;">organizationNameGE</th>
<th> </th>
</tr>
</thead>
<tbody ng-repeat="item in jsonData" >
<tr>
<td><input type="checkbox" ng-change="sync(bool, item)" ng-model="bool" ng-checked="isChecked(item.id)" ></td>
<td><input style="width:305px;" type="number" id="id" ng-model="item.id" readonly /></td>
<td><input style="width:305px;" type="text" id="organizationNameEN" ng-model="item.organizationNameEN" required /></td>
<td><input style="width:305px;" type="text" id="organizationNameGE" ng-model="item.organizationNameGE" required/></td>
<td><button class="btn btn-default btn-xs" ng-click="toggle($index)"><span class="glyphicon glyphicon-eye-open"></span></button></td>
</tr>
<tr id="{{hideid + $index}}" ng-show="item.hidethis">
<td>
<label for="startDate" class="control-label">startDate</label>
<div class="controls">
<input style="width:105px;" id="strtDate" class="form-control" type="text" ng-model="item.startDate" required readonly/>
</div>
<br>
<label for="endDate" class="control-label">endDate</label>
<div class="controls">
<input style="width:105px;" id="endDate" class="form-control" type="text" ng-model="item.endDate" required readonly/>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<script>
function checkAll(bx) {
var cbs = document.getElementsByTagName('input');
for(var i=0; i < cbs.length; i++) {
if(cbs[i].type == 'checkbox') {
cbs[i].checked = bx.checked;
}
}
}
</script>
</form>
I do something similar. In my first form, the user captures some transactions. Form 2 they double-capture (new transactions which must match the first capture) and form 3 they view they successful transactions and authorise them.
I have handled this by creating a JSON array of transactions in the first form. I save this to a process variable in the on-submit event using code like this:
camForm.on('submit', function() {
// this callback is executed when the form is submitted, *before* the submit request to
// the server is executed
// creating a new variable will add it to the form submit
variableManager.createVariable({
name: 'customVariable',
type: 'String',
value: 'Some Value...',
isDirty: true
});
I retrieve it in the subsequent forms like you do in the form-loaded/variables-fetched events.
If the JSON array data is updated in subsequent forms, I save it back to the same variable using code like this:
camForm.on('submit', function(evt) {
var fieldValue = customField.val();
var backendValue = variableManager.variable('customVariable').value;
if(fieldValue === backendValue) {
// prevent submit if value of form field was not changed
evt.submitPrevented = true;
} else {
// set value in variable manager so that it can be sent to backend
variableManager.variableValue('customVariable', fieldValue);
}
});
These code snippets are from the Camunda documentation.

Stuck on angularjs ng-checked

I'm trying to implement that when a user clicks a check box it displays all products in the ng-repeat with a quantity of 0. Else when the check box is not check all items display. Currently I was able to get half the functionality.
Check box :
<input type="checkbox" name="onoffswitch" class="onoffswitch-checkbox" id="myonoffswitch" ng-checked="vm.OnHandQty()">
Table
<tr ng-repeat="item in vm.items | filter :search">
<td ng-bind="item.itemNo"> </td>
<td ng-bind="item.description"></td>
<td ng-bind="(item.listPrice | currency)"></td>
<td ng-bind="item.onHandQty" ng-model="quantity"></td>
</tr>
Controller
vm.OnHandQty = function () {
$scope.search = {};
vm.items.forEach(i => {
if (i.onHandQty == 2) {
console.log(i);
$scope.search = i;
return true;
}
else {
$scope.search =i;
return false;
}
});
}
I would propose changing the implementation of your checkbox and controller:
Checkbox
<input type="checkbox" ng-model="vm.checked" name="onoffswitch" class="onoffswitch-checkbox" id="myonoffswitch">
- Here, we use "ng-model" instead of "ng-checked" and "vm.checked" is a variable that you define as the ng-model for your checkbox.
Controller
$scope.search = function(item) {
return ($scope.vm.checked) ? item.onHandQuantity === 0: true;
};
- Here, we define the "ng-repeat" filter that you are using in your table.
Try this instead:
<tr ng-repeat="item in vm.items" ng-show="onoffswitch==true && item.onHandQty != 0? false : true">
<td ng-bind="item.itemNo"> </td>
<td ng-bind="item.description"></td>
<td ng-bind="(item.listPrice | currency)"></td>
<td ng-bind="item.onHandQty" ng-model="quantity"></td>
</tr>
This will only show the row if onoffswitch is true and if the onHandQty is zero, otherwise it will show the row. So the row will be hidden if onoffswitch is true and onHandQty is not zero.
You can make use of ng-change and ng-model.
<input type="checkbox" name="onoffswitch" class="onoffswitch-checkbox" id="myonoffswitch" ng-model="vm.checked" ng-change="checkBoxChange(vm.checked)">
Then, from you checkBoxChange function, apply your business logic:
vm.checkBoxChange = function(checked){
if(checked){
//Do something
}else{
//Something else
}
};

Angular filter using OR instead of AND logic

I'm having some checkboxes and on check, table filter values. But if I select active and draft it doesn't show anything because it's implementing AND logic, I need filters that is using OR logic.
<div class="clearfix">
<input data-ng-model="active" data-ng-true-value="active" class="pull-left" type="checkbox" id="active"/>
<label class="pull-left" for="active">Active</label>
</div>
<div class="clearfix">
<input data-ng-model="draft" data-ng-true-value="draft" class="pull-left" type="checkbox" id="draft"/>
label class="pull-left" for="draft">Draft</label>
</div>
<table class="table">
<tr ng-repeat="campaign in dashboard.campaigns | filter:all | filter:active | filter:draft">
<td>{{campaign.name}}</td>
<td>{{campaign.startDate}}</td>
<td>{{campaign.endDate}}</td>
<td>{{campaign.status}}</td>
<td>{{campaign.tasks}}</td>
</tr>
Edit:
here is the solution
app.filter('byStatus', [function () {
return function (campaigns, active, draft) {
var tempCampaigns = [];
angular.forEach(campaigns, function (campaign) {
if(campaign.status == active || campaign.status == draft ){
tempCampaigns.push(campaign);
}
});
return tempCampaigns;
};
}]);
<tr ng-repeat="campaign in dashboard.campaigns | byStatus:active:draft">
thx all ;)
You just need to implement custom filter like this:
angular.module('App.filters', []).filter('activeOrDraft', [function () {
return function (campaigns) {
if (!angular.isUndefined(campaigns)) {
var tempCampaigns = [];
angular.forEach(campaigns, function (campaign) {
if (campaign.active || campaign.draft) {
tempCampaigns.push(campaign);
}
});
return tempCampaigns;
} else {
return campaigns;
}
};
}]);
and use it instead of filter:active | filter:draft like this:
| activeOrDraft
Not sure about meaning of all in your code, so add it if needed.

AngularJS How To Manage checkbox only in the controller.js?

Is it possible to manage and save the checkbox value (object) only in the controllers.js?
Thanks in advance.
I have this HTML-code (entity is an object):
<table>
<tr data-ng-repeat="entity in entities">
<td> <input type='checkbox' ng-click="toggleChecked(entity)"> {{entity.name}}</td>
</tr>
</table>
<pre>{{selectedBoxes|json}}</pre>
in my controllers.js I did this:
$scope.selectedBoxes = [];
$scope.toggleChecked = function(entity) {
if ($scope.selectedBoxes.length > 0) {
for (var box in $scope.selectedBoxes) {
if (box.name == entity.name) {
$scope.selectedBoxes.splice(box, 1);
return;
}
}
} else {
$scope.selectedBoxes.push(entity);
}
}
I am not able to print this <pre>{{selectedBoxes|json}}</pre>.
The angular method of manipulating your model actually discourages using on click to manipulate the model.
I would suggest the following:
<table>
<tr data-ng-repeat="entity in entities">
<td> <input ng-model="entity.checked" type='checkbox'> {{entity.name}}</td>
</tr>
</table>
<pre>{{selectedBoxes()| json}}</pre>
Controller:
$scope.selectedBoxes = function() {
var selected = [];
for (var entity in $scope.entities) {
if ($scope.entities[entity].checked) {
selected.push($scope.entities[entity]);
}
}
return selected;
};
Whenever a property on entity changes, selectedBoxes() will re-evaluate which will automatically update the html.

Resources