How to filter following JSON with ionic filter bar - angularjs

Using Ionic Filter Bar for implementing search in ionic app, I need to to search on "parent_type" and "child_type" from following json,
{
"status": {
"code": 200,
"message": "all data grabbed successfully",
"cause": ""
},
"ParentData": [
{
"id": 67,
"parent_type": "Parent Type",
"child": [
{
"id": 86,
"child_type": "Child Type"
},
{
"id": 93,
"child_type": "Child Type1"
}
]
},
{
"id": 68,
"parent_type": "Parent Type 1",
"child": [
{
"id": 87,
"child_type": "Child Type 1"
},
{
"id": 94,
"child_type": "Child Type 2"
}
]
}
]
}
its working fine for "parent_type" with following code
Here is the filter code
$scope.showFilterBar = function () {
filterBarInstance = $ionicFilterBar.show({
//setting parentData in following way after rest service call
//$scope.parentData = jsondata.ParentData
items: $scope.parentData,
update: function (filteredItems, filterText) {
$scope.parentData = filteredItems;
if (filterText) {
console.log(filterText);
}
},
filterProperties: ['parent_type']
});
};
But not able to search on "child_type"
So is there any way to set filterProperties so it will work for both "parent_type" and "child_type" or any other way to search this Json?
Thanks.

You should remove the "filterProperties" key and then add "expression" key.
Your "filterBarInstance" will be something like this:
$scope.showFilterBar = function () {
filterBarInstance = $ionicFilterBar.show({
items: $scope.parentData,
update: function (filteredItems, filterText) {
$scope.parentData = filteredItems;
if (filterText) {
console.log(filterText);
}
},
expression: function(filterText,value,index,array){
// This function is called for every ParentData object.
// "value" will be the current ParentData object,
// you'll need to iterate over all the "child" array in order to
// check if any of the "child_type" keys contains the "filterText"
// so if "parent_type" contains the "filterText" and any(? or all)
// of the the "child[x].child_type" values also contains the
// "filterText" return true
}
});
};
Check https://github.com/djett41/ionic-filter-bar for the original documentation.
Sorry for my english :)

Related

How filter and delete object with null or empty property in json query

I have this json :
{
"meta": {
"status": 200,
"pagination": {
"page": 1,
"perPage": 15,
"hasNext": true
}
},
"data": [
{
"id": "1",
"title": "Movie title1"
"rating": null,
"playProviders": [
]
},
{
"id": "2",
"title": "Movie title2"
"rating": {
"ratingAssessment": "7.1"
},
"playProviders": [
"HBO", "Netflix"
]
},
....
}
I want to create a page with a list of movies, I need to fetch movies but only those which have a rating and playProviders, what parameters should I use in this request?
https://api.com/movies?orderBy=views
When I filters in the code:
programs.filter((program) => program.rating !== null);
it only gets a few films per page, those that don't have null. For example, 15 are per page and I get 2. How do I filter this? (I am using react typescript)
I don't have access to the API code. I need to filter what is returned by the API or write a query so that you get already filtered data from the API.
programs = [
{rating: 1,
playProviders: ["sf"]
},
{
rating: 4,
playProviders: []
}
]
programs.filter(function(program) {
if (program.rating !== null && program.playProviders.length !== 0) {
return program;
}
})

Angular - Convert objects in a nested array into comma seapared values before binding to grid

below is part of my JSON response coming from an API
{
"totalCount": 2,
"customAttributes": [
{
"objectType": "OWNER",
"atrributeId": 215,
"attributeName": "DATELICENSEFIRSTISSUED",
"attributeDisplayName": "DATE LICENSE FIRST ISSUED",
"dataType": "DATE",
"inputValues": [],
"isGridEligible": "true",
"isInvoiceEligible": "false"
},
{
"objectType": "LOCATION",
"atrributeId": 217,
"attributeName": "DONOTRENEW",
"attributeDisplayName": "DO NOT RENEWS",
"dataType": "Value List",
"inputValues": [
{
"id": 5,
"value": "VEHICLELISTREQUIRED"
},
{
"id": 6,
"value": "STATESWITHRECIPROCITY"
}
],
"isGridEligible": "true",
"isInvoiceEligible": "false"
}
]
}
Here, I am binding customAttributes as grid data.
this.customFieldsService.getCustomFields(this.columnList, this.pageNumber, this.pageSize, null).subscribe(res => {
if(res){
this.cfData = res;
this.gridData = {
data: this.cfData.customAttributes,
total: this.cfData.totalCount
}
}
});
Here, my problem is with inputValues column, which comes as an array of objects. I need to convert it to comma seaparated values and then bind to grid data like
"inputValues": ["VEHICLELISTREQUIRED" "STATESWITHRECIPROCITY"]
I can ignore the "id" property as we are not using it at angular side. I tried using join method but not able to solve it within the nested array. Please suggest. Thanks.
In typescript it can be done with:
const joined: string = customAttribute.inputValues
.map(x => x.value) // [{value: 'VEHICLELISTREQUIRED'}, {value: 'STATESWITHRECIPROCITY'}]
.join(' ') // "VEHICLELISTREQUIRED" "STATESWITHRECIPROCITY"
const putIntoArray = [joined]; // ["VEHICLELISTREQUIRED" "STATESWITHRECIPROCITY"]
Of course you can put the joined string immediately into an array.

I need to get a nested element in a json array

There is some list of elements in json format, it looks like this:
[{
'id': 0,
"name": "Category name1",
"services": [{
"id": 0,
"name": "Product name1"
}, {
"id": 1,
"name": "Product name2"
}]
},
{
'id': 1,
'name': "Category name2",
"services": [{
"id": 0,
"name": "Product name1"
}, {
"id": 1,
"name": "Product name2"
}]
}
]
I'm trying to get only the entire "services" array from the first category. Conditionally, I'm trying to get it as follows:
this.class = this.http.get('/assets/products.json');
this.class.forEach(element => {
if (element.id == ID) //The ID is obtained when calling the function in which this code is executed
{
console.log(element.services);
}
}
However, this gives me absolutely nothing and "undefined" is output to the console, however, with the same array and under the same conditions on the site https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach it (foreach and console.log) outputs everything I need.
//The same foreach only on the mozilla website
array1.forEach(item => {
if(item.id==1){ //1 вместо ID
console.log(item.services);
}});
Output to the console: Array [Object { id: 0, name: "Product name1"}, Object { id: 1, name: "Product name2"}].
P.S. I don't really need this list of products in the console, I'm trying to pass a variable, but since undefined is passed to the variable, as well as to the console, I can't use the variable and call it to display products on the page. All this is used in the typescript angular project.
The HttpClient methods like get return observables, to which you need to subscribe to in order for the request to even get executed. In your situation, the class property is only holding a reference to the observable returned by calling this.http.get. Try subscribing to the observable and use the result to extract the data that you need.
this.http.get<any[]>('/assets/products.json').subscribe((data) => {
this.class = data;
this.class.forEach((element) => {
if (element.id == ID) {
console.log(element.services);
}
});
});

JavaScript (Node.js) - JSON recursion extracting objects to array with order (faltten)

I have a JSON config file as follows:
var conf = [
{
"value": "baz",
"threshold": 20,
"other": 123
},
{
"value": "mo",
"other": 456,
"child": {
"value": "foo",
"other": 789,
"child": {
"value": "larry",
"other": 123
}
}
}
];
I have a requirement to extract each of the objects and persist them together in order if they have child objects. For example, object 1 (baz) is stand alone. Object 2 (mo) will have two child objects. These 3 as a set must be extracted together.
There is no limit to the number of child objects.
Im attempting to persist each object using an array to maintain the order. So the required output would look like:
[[{"value":"baz","threshold":20,"other":123}],
[[{"value":"mo","other":456,"child":{"value":"foo","other":789,"child":{"value":"larry","other":123}}}],
[{"value":"foo","other":789,"child":{"value":"larry","other":123}}],
[{"value":"larry","other":123}]]]
A final requirement is to actually remove the child values from the parents so the output can actually be like:
[
[{"value":"baz","threshold":20,"other":123}],
[
[{"value":"mo","other":456}],
[{"value":"foo","other":789}],
[{"value":"larry","other":123}]
]
]
Ive been hung up on this for hours with little progress. I know I need to create a recursive function, push each node to an array, and then check for child object and repeat.
Heres what I have so far. My thinking is if I can take the array id each task is being pushed to (using a loop id), perhaps I can map that when the function is called again.
Appreciate any guidance.
var execSets = [];
function parser(tasks){
// an ordered array of task execution
for (let eachTask in tasks) {
var taskSet = [];
console.log("====================================");
console.log(tasks[eachTask]);
if(!tasks[eachTask].child && typeof(tasks[eachTask]) === 'object'){
console.log(tasks[eachTask]);
taskSet.push(tasks[eachTask]);
execSets.push(taskSet);
}
if(tasks[eachTask].child){
let childAlias = tasks[eachTask].child;
delete tasks[eachTask].child;
taskSet.push(tasks[eachTask]);
execSets.push(taskSet);
parser(childAlias);
}
}
}
The npm registry is your friend; try 'npm search flat,
There are a few modules that can help flatten a json object. For example https://www.npmjs.com/package/flat
You could do it using recursion. Here is my suggestion:
var conf = [
{
"value": "baz",
"threshold": 20,
"other": 123
},
{
"value": "mo",
"other": 456,
"child": {
"value": "foo",
"other": 789,
"child": {
"value": "larry",
"other": 123
}
}
}
];
function getFlattenedObject(object){
var response = [];
flatten(object, response, 0);
return response;
}
function flatten(object, array, index){
if(!array[index]){
array.push([]);
}
array[index].push(object);
if(object.child){
flatten(object.child, array, index + 1);
object.child = undefined;
}
}
//Logs for comparison
console.dir(conf)
console.dir(getFlattenedObject(conf));
The result structure you are looking for wasn't "intuitive" and hence the solution has gotten a little ugly, but here is how you could use object-scan to answer your question
// const objectScan = require('object-scan');
const data = [{"value":"baz","threshold":20,"other":123},{"value":"mo","other":456,"child":{"value":"foo","other":789,"child":{"value":"larry","other":123}}}]
const fn = (haystack) => objectScan(['[*]', '**.child'], {
filterFn: ({
key: [id, ...p],
value: { child, ...node },
context
}) => {
if (!(id in context)) {
context[id] = [];
}
context[id].push(child || p.length !== 0 ? [node] : node);
}
})(haystack, []);
console.log(fn(data));
// => [ [ { value: 'baz', threshold: 20, other: 123 } ], [ [ { value: 'larry', other: 123 } ], [ { value: 'foo', other: 789 } ], [ { value: 'mo', other: 456 } ] ] ]
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/object-scan#13.7.1"></script>
Disclaimer: I'm the author of object-scan

$filter with custom function in angular

How I can create a $filter with custom function to determining if match ?
This is a json sample with structure:
$scope.routes =[
{
"id": 0,
"name": "Rosa Barnes",
"origin": [
{
"address": [
{
"locality": "Madrid",
"country": "ES"
}
]
}
]
},
{
"id": 1,
"name": "Wright Montoya",
"origin": [
{
"address": [
{
"locality": "London",
"country": "UK"
}
]
}
]
},
{
"id": 2,
"name": "Pearson Johns",
"origin": [
{
"address": [
{
"locality": "London",
"country": "UK"
}
]
}
]
}
];
I want a $filter that passing one country, match in origin.address.country , is possible?
I proved this code but not works:
$scope.routesToShow = $filter('filter')($scope.routes, {origin.address.country: "UK"});
Here there are a demo:
http://jsfiddle.net/86U29/43/
Thanks
What you need is a custom filter. It also looks like you might need to tweak your data structure too.
Take a look at this:
app.filter('CustomFilter', function () {
function parseString(propertyString) {
return propertyString.split(".");
}
function getValue(element, propertyArray) {
var value = element;
propertyArray.forEach(function (property) {
value = value[property];
});
return value;
}
return function (input, propertyString, target) {
var properties = parseString(propertyString);
return input.filter(function (item) {
return getValue(item, properties) == target;
});
}
});
You could use this filter, like this:
$scope.routesToShow = $filter('CustomFilter')($scope.routes, 'origin.address.country', 'UK');
Here is an updated jsfiddle (notice the updated data structure): http://jsfiddle.net/moderndegree/86U29/44/
You can find more information on creating custom filters here:
https://docs.angularjs.org/guide/filter#creating-custom-filters
Simply.
var filter = function(obj){
return obj.origin[0].address[0].country === 'UK';
}
$scope.routesToShow = $filter('filter')($scope.routes, filter);

Resources