ngGrid Multi Column Filtering - javascript

I am using the ngGrid module for AngularJS to show some paged data. I want to be able to search across multiple columns, however using an OR search.
Lets say I have a column with the following headings: Id, Name, Description. When I search I want to return all rows where either Id OR name OR description contain the search term.
$scope.pagingOptions = {
pageSizes: [20, 50, 100],
pageSize: 20,
totalServerItems: 0,
currentPage: 1
};
$scope.gridOptions =
{
data: 'myData',
columnDefs: [
{ field: 'id', displayName: 'Id' },
{ field: 'name', displayName: 'Name' },
{ field: 'description', displayName: 'Description' },
{ displayName: 'Actions', cellTemplate: '<input type="button" data-ng-click="doSomething(row.entity)" value="Do Something" />'}],
enablePaging: true,
showFooter: true,
showFilter: true,
pagingOptions: $scope.pagingOptions,
filterOptions: {
filterText: "",
useExternalFilter: false
}
};
I have tried using the default search box, and also using an external input box bound to $scope.filterText to define a custom filter such as:
$scope.filterUpdated = function () {
$scope.gridOptions.filterOptions.filterText = 'id:' + $scope.filterText + ';name:' + $scope.filterText + ';description:' + $scope.filterText;
};
However this seems to do an AND on all of the columns. Is it possible to achieve what I want using the ngGrid module?
Thanks in advance,
Chris

Yes it's possible to do an OR filter, but after searching in the ng-grid source code I can't see how it can be done using their filterOptions.filterText. That can do AND filtering only.
The solution would be then to use filterOptions.useExternalFilter:true
I also found no examples of it, but after playing around with that for a bit, I got the notion that the filter is actually done by re-creating the gridOptions.data object|array. That is the only downside to this filter.
Plunker code is here
So basically your code would look like this index.html:
<body ng-controller="MyCtrl">
<strong>Filter Name:</strong> </string><input type="text" ng-model="filterName"/>
</br>
OR
</br>
<strong>Filter Age:</strong> </string><input type="text" ng-model="filterAge"/>
</br>
<button ng-click="activateFilter()">Run Filter</button>
<br/>
<br/>
<div class="gridStyle" ng-grid="gridOptions"></div>
</body>
And in your controller.js:
app.controller('MyCtrl', function($scope) {
$scope.filterOptions = {
filterText: '',
useExternalFilter: true
};
$scope.activateFilter = function() {
var name = $scope.filterName || null;
var age = ($scope.filterAge) ? $scope.filterAge.toString() : null;
if (!name && !age) name='';
$scope.myData = angular.copy($scope.originalDataSet, []);
$scope.myData = $scope.myData.filter( function(item) {
return (item.name.indexOf(name)>-1 || item.age.toString().indexOf(age) > -1);
});
};
$scope.originalDataSet = [{name: "Moroni", age: 50},
{name: "Tiancum", age: 43},
{name: "Jacob", age: 27},
{name: "Nephi", age: 29},
{name: "Enos", age: 34}];
$scope.myData = angular.copy($scope.originalDataSet, []);
$scope.gridOptions = {
data: 'myData',
filterOptions: $scope.filterOptions
};
});
That's just basic filtering (use regex and/or convert to lowercase for better matching). Also note that if both name and age are empty I set name to be '' and then every element would return true inside the filter (resulting in the whole dataset return).
This option is much better suited to dynamic dataset (read - server fed), but it works just as well but replicating the original dataset and applying the filters on it.

Related

Show breakline in uigrid

I'm using uigrid like below:
columnDefs: [
{ name: 'CA', field: 'CA', displayName: 'CA', enableCellEdit: false }
]
the CA column has data like below :
<div> name : Jon ><br /> Job : Barber </div>
even that i have <br /> i got a result as it is , without a break line.
Any solution ? to show the result like :
name : Jon
Job : Barber
I believe this might be close to what you want, user2848242.
JavaScript/AngularJS Controller:
var app = angular.module('app', ['ui.grid', 'ngSanitize']);
app.controller('MainCtrl', ['$scope', '$http', function($scope, $http) {
$scope.gridOptions = {
rowHeight: 40,
enableRowHeaderSelection: false,
columnDefs: [{
name: 'CA1',
field: 'CA',
displayName: 'Original CA',
enableCellEdit: false,
cellTemplate: '<span ng-bind-html="row.entity[col.field]"></span>'
}, {
name: 'CA2',
field: 'Name',
displayName: 'Alternative CA',
enableCellEdit: false,
cellTemplate: '<div>Name: {{row.entity[col.field]}}<br />Job: {{row.entity["Job"]}}</div>'
}]
}
$http.get('data.json')
.then(function(response) {
$scope.gridOptions.data = response.data;
});
}]);
The basic idea is, add a cellTemplate to your columnDefs. The tricky part is, since HTML is in your data you need to use ngSanitize to "trust" the HTML so it'll appear as HTML. Since it's best to separate HTML from data, for many reasons, I provided an alternative - hence Original CA and Alternative CA columns.
Here's a working Plunker, http://plnkr.co/edit/pkoARFr11Q7TmbBIegIT?p=preview.
Hope that helps, let me know if you have any other questions.

Angular-Formly dynamically change select options

I would like to know if I could change select options using Angular-Formly depending on another select's selected value.
Lets say I have beverageTypeSelect and drinkSelect.
beverageTypeSelect has options Alcoholic and Non-Alcoholic.
drinkSelect would have Heineken, Budweiser, Alcohol 96%, if beverageTypeSelect value is Alcoholic.
drinkSelect would have Coca-Cola, Pepsi, Water, if beverageTypeSelect value is Non-Alcoholic.
How can I do that?
Editing:
Ok, let's try to make it a little more clear:
This is not my real application, but I want to keep it simple and get the general solution for this, so I'll keep with the beverage.
We are using https://github.com/formly-js/angular-formly-templates-bootstrap.
We have a formly forms generator. The part of code that is interesting in here is this:
if (obj.ngOptions){
o.templateOptions.options=[];
o.templateOptions.ngOptions = obj.ngOptions;
}
We have figured out that options must by an empty array so ngOptions can take place.
So we have a formly form like this:
[{
key: 'beverageTypeSelect',
type: 'select',
templateOptions: {
options: [{
name: 'Alcoholic',
value: 'A'
},
{
name: 'Non-Alcoholic',
value: 'N'
}]
}
}, {
key: 'drinkSelect',
type: 'select',
templateOptions: {
options: [],
ngOptions: 'item as item.label for item in model.drinkSelect track by item.id'
}]
Then we'll have a html to show our form:
<formly-form fields="formFields" model="DrinkingCtrl.data" form="DrinkingCtrl.form">
</formly-form>
And, finally, our controller:
'use strict'
angular.module('drunkApp')
.controller('DrinkingCtrl', drinking);
function drinking($scope, $stateParams, $state, $reactive, AutoSaveReactiveFormScope) {
var self = this;
var vm = AutoSaveReactiveFormScope($scope, this, 'NAME_TO_SEARCH_FOR_DRINK_FORMLY_FORM', 'drinkPublishName', drinkMongoCollection, $stateParams.id); // This is a factory that gives us everything (or almost it) that we need in a controller with form autosave functionallity :).
var drinkOptions = [{
id: 'H',
label: 'Heineken',
types: ['A']
}, {
id: 'B',
label: 'Budweiser',
types: ['A']
}, {
id: 'A',
label: 'Alcohol 96%',
types: ['A']
}, {
id: 'C',
label: 'Coca-Cola',
types: ['N']
}, {
id: 'P',
label: 'Pepsi',
types: ['N']
}, {
id: 'W',
label: 'Water',
types: ['N']
}];
vm.autorun(function() {
if (self.data) {
self.data.drinkSelect = _.filter(drinkOptions, function(drk) {
return _.contains(drk.types, self.data.beverageTypeSelect);
});
}
});
}
This really works, but I was expecting something cleaner, something that I could do directly inside of the form declaration. Maybe do something like we can do with required or hideExpression (that we can write something like 'model.option1 != "BLA"' or a function).
p.s.: Hope this time I made myself clearer.

Dgrid - Display label for number (i.e. 02 = Cat) I want to display Cat - not the number

In my Dgrid I have a column that displays the code (in number format) for an event.
enter image description here
I want to display the label not the number in the dgrid. So if 1 = Cat. In the database it shows as a 1 - but I want to display 'Cat' in dgrid. Can't find anything on how to do this.
Help or a lead in a direction would be helpful. Thanks!!
UPDATED: 6.16.15
Here is the code. I'm limited in what I can show.
These are some of the codes. 02 = XXXXX, 03 = XXXXX1, and so on and so on. Right now, the dgrid displays the numbers. It's kind of like a key. I need it to display what the number represents in the dgrid, not the number. So 02 should display 'Traffic Stop'. Not sure how to do a jsfiddle yet, and don't have a whole lot of extra time at the moment. I'm limited in what info I can give out, so I'd have to recreate a dummy version.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>XXXXXXXX Events</title>
<link rel="stylesheet" href="/static/web_ui/dgrid/css/skins/slate.css">
<h1>XXXXXXXX Events</h1>
<form id="queryForm">
<label for="XXXXXField">XXXXX Type contains:</label>
<input id="XXXXXField" name="event_type">
<button type="submit">Filter</button>
<button type="reset">Reset</button>
</form>
<script src="/static/web_ui/dojo/dojo.js"
data-dojo-config="async: true"></script>
<script>
require([
'dojo/_base/declare',
'dojo/dom',
'dojo/on',
'dstore/Rest',
'dstore/Request',
'dgrid/extensions/ColumnResizer',
'dgrid/extensions/ColumnReorder',
'dgrid/CellSelection',
'dgrid/extensions/DijitRegistry',
// 'dstore/Memory',
// 'dstore/Trackable',
// 'dstore/Cache',
'dgrid/OnDemandGrid'
// 'dojo/domReady!'
], function (declare, dom, on, Rest, Request, ColumnResizer, ColumnReorder, CellSelection, DijitRegistry, OnDemandGrid) {
var store = new Rest({target:'/api/XXXXXXEvents/?format=json',
sortParam: 'ordering', ascendingPrefix:'', descendingPrefix:'-'
});
// var cacheStore = Cache.create(store, {
// cachedStore: new (Memory.createSubclass(Trackable)) ()
// });
var grid = window.grid = new (declare([OnDemandGrid, ColumnResizer, ColumnReorder, CellSelection, DijitRegistry])) ({
collection: store,
selectionMode: 'single',
sort: 'id',
// idProperty: 'id',
columns: [
{field: 'id', label:'ID', resizeable: false},
{field: 'XXXXX_type', label:'XXXXX Type', resizeable: false},
{field: 'XXXXX_at', label:'XXXXX Time', resizeable: false},
{field:'XXXXX', label:'XXXXX Count', resizeable: false},
{field:'XXXXX', label:'XXXXX', resizeable: false},
{field:'XXXXX_info', label:'XXXXX Info', resizeable: false},
{field:'hidden', label:'Hidden', resizeable: false},
{field:'XXXXX', label:'XXXXX', resizeable: false},
{field:'XXXXX', label:'XXXXX', resizeable: false}
]
}, 'grid');
grid.startup();
on(dom.byId('queryForm'), 'submit', function(event) {
event.preventDefault();
grid.set('collection', store.filter({
// Pass a RegExp to Memory's filter method
// Note: this code does not go out of its way to escape
// characters that have special meaning in RegExps
last: new RegExp("^\d+$")
}));
});
on(dom.byId('queryForm'), 'reset', function() {
// Reset the query when the form is reset
grid.set('collection', store);
});
});
</script>
</head>
<body class="slate">
<div id="grid"></div>
</body>
</html>
You need to use the column formatter function for rendering data.
check the jsfiddle over here.
Check the examples over here
I have taken this example and modified as per your needs.
require([
'dgrid/Grid',
'dojo/domReady!'
], function(Grid) {
var data = [
{ id: 1, number: 7 },
{ id: 2, number: 8 },
{ id: 3, number: 9 }
];
function testFormatter(item){
//console.log(item,typeof(item));
var newItem;
if ( item == 7 )
newItem = 'Dog'
else if ( item == 8 )
newItem = 'Cat'
else if ( item == 9 )
newItem = 'Bird'
return newItem;
}
var columnsFormatter = [
{
label: "Number",
field: "number",
formatter: testFormatter
}
];
var grid = new Grid({
columns: columnsFormatter
}, "gridcontainer");;
grid.renderArray(data);
});

EmberJS - Checkboxes and Getting Values in Controller

Below is a simple example how I intend to use check boxes. What I have is an array of terms with id and name field and each post can be assigned to a single or multiple terms/categories.
var config = {};
config.terms = [
{id: 1, termName: 'Red'},
{id: 2, termName: 'Green'},
{id: 3, termName: 'Blue'}
];
Problem
With EmberJS handlebar expression I am showing those checkboxes but I am confused what to use as form element variable name field doesn't seem to defined in the controller. The checked field works as controller property but when I add termName as checked all of the checkboxes are checked by default and label after checking changes after clicking checkboxes.
What I need to get on the controller is the term names that are selected
Below is the example code. You can also find it on JsFiddle. Check uncheck the red/green/blue checkboxes to see the problem. Also have a look in console.
HTML
<div id="main"></div>
<script type="text/x-handlebars" data-template-name="index">
{{#each term in terms}}
{{input type="checkbox" name=term.name}} {{term.name}}
{{/each}}
<button {{action "submit"}}>Submit</button>
</script>
JS
var config = {};
config.terms = [
{id: 1, name: 'Red'},
{id: 2, name: 'Green'},
{id: 3, name: 'Blue'}
];
App = Ember.Application.create({
rootElement: '#main'
});
App.IndexRoute = Ember.Route.extend({
setupController: function(controller){
controller.set('terms', config.terms);
}
});
App.IndexController = Ember.Controller.extend({
actions: {
submit: function(){
console.log(this.Red);
console.log(this.Blue);
console.log(this.Green);
}
}
});
In you jsfiddle example you'r binding the name to the checked value of the checkbox. I think that's not what you want to do.
The checked value should be bound to a boolean value.
So,
1st approach: either add a property to your term object (selected: false)
config.terms = [
{id: 1, name: 'Red', selected: false },
{id: 2, name: 'Green', selected: false },
{id: 3, name: 'Blue', selected: false }
];
(as Ember objects:)
config.terms = [
Em.Object.create({id: 1, name: 'Red', selected: false }),
Em.Object.create({id: 2, name: 'Green', selected: false }),
Em.Object.create({id: 3, name: 'Blue', selected: false })
];
and then bind the property in your template this way:
{{input type="checkbox" checked=term.selected}}
2nd approach: bind it to controller properties:
// inside your controller:
redSelected: false,
greenSelected: false,
blueSelected: false,
{{input type="checkbox" checked=controlller.redSelected}}

Dojo datagrid: sort by first value in cell layout

I have used a formatter to add some html (a link, a break and a span) on or around different values. The issue now is that the column does not sort. I think it is because every cell in the column starts with the same value (a link with the same url. Eventually the urls will be different).
Here is the data:
{id: 1, 'main': 'puma', 'description': 'A puma is a cat', 'url': 'http://www.google.com', 'filesize': '12.34', date: '2010-01-01'},
{id: 2, 'main': 'tiger', 'description': 'Tiger, another cat', 'url': 'http://www.google.com', 'filesize': '43.27', date: '2013-03-04'},
{id: 3, 'main': 'Wombat', 'description': 'wombat, not a cat', 'url': 'http://www.google.com', 'filesize': '59.01', date: '2011-03-08'}
This is for the layout (left out the other columns from this sample):
{name: 'Title', fields: ['main','description','url','filesize'], 'width': '200px',formatter: formatLink}
And this is the formatter:
function formatLink(value){
return ''+value[0]+'<br />'+value[1]+'<span class="smalltxt"> File Size: ' + value[3] + 'MB</span>';
}
For clarity, to see it all in action: http://jsfiddle.net/QXYDK/6/
Ideally I would not have all this stuff in the same cell, but it required for this project.
The center column does not sort at all at the moment. Is there a way I can choose to sort by value[0] (the first field, 'main')?
I don't know if it's a bug in Dojo or not, but Dojo only defines sorting on the field attribute. But because you're using a custom field with a formatter, you only use fields and not field.
The solution is to define the field you want to sort on (in this case "main").
The code for your layout would become:
var layout = [
{name: 'Index', field: 'id'},
{name: 'Title', fields: ['main','description','url','filesize'],field: 'main', 'width': '200px',formatter: formatLink},
{name: 'Date', field: 'date', width: 10, formatter: formatDate}
];
By default, Dojo sorts your data case sensitive, which means that Wombat (which starts with a capital) will be sorted differently than puma and tiger (which start with a lower case letter). To enable case insensitive sorting, you need to define a comparatorMap on your store, for example:
store.comparatorMap = new Object();
store.comparatorMap["main"] = function(a, b) {
if (a.toLowerCase() < b.toLowerCase()) {
return -1;
} else if (a.toLowerCase() == b.toLowerCase()) {
return 0;
} else {
return 1;
}
};
I also updated your JSFiddle with this new information. The result can be found here.

Categories

Resources