Angularjs ng-repeat with some conditions: - javascript

This is my json response i am storing this in
$scope.times = response.data;
My $scope.times json object:
[
{
"id": 1,
"status": true,
"time": "2018-03-05T10:24:15.000Z",
"complaintId": 1
},
{
"id": 2,
"status": true,
"time": null,
"complaintId": 1
},
{
"id": 3,
"status": true,
"time": "2018-03-05T10:53:14.000Z",
"complaintId": 2
},
{
"id": 6,
"status": false,
"time": "2018-03-05T11:58:45.000Z",
"complaintId": 1
},
{
"id": 7,
"status": true,
"time": "2018-03-05T12:11:53.000Z",
"complaintId": 1
},
{
"id": 8,
"status": false,
"time": "2018-03-05T13:23:13.000Z",
"complaintId": 2
},
{
"id": 9,
"status": true,
"time": "2018-03-05T08:17:18.000Z",
"complaintId": 3
},
{
"id": 10,
"status": true,
"time": "2018-03-05T12:32:08.000Z",
"complaintId": 2
}
]
I am displaying this in html using ng-repeat= 'time in times' , but i need to get json object of times with complaintId which located in last, for example there are many complaintId:1 in object.
i need to get only which have complaintId in last.
My expected output in time:
[
{
"id": 7,
"status": true,
"time": "2018-03-05T12:11:53.000Z",
"complaintId": 1
},
{
"id": 9,
"status": true,
"time": "2018-03-05T08:17:18.000Z",
"complaintId": 3
},
{
"id": 10,
"status": true,
"time": "2018-03-05T12:32:08.000Z",
"complaintId": 2
}
]
My ng-repeat looping code:
table
tr
th S.no
th Time
tr(ng-repeat='time in times')
td {{$index + 1 }}
td {{time.status}}

(Don't judge, it's Monday)
Here is the best solution I could find. You can obviously improve it (make it shorter) by using some ES6 magic with .reduce / .filter / .forEach, etc.
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<body>
<div ng-app="myApp" ng-controller="myCtrl">
<div ng-repeat="time in times">
<pre>{{time | json}}</pre>
</div>
</div>
<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.times = [{"id":1,"status":true,"time":"2018-03-05T10:24:15.000Z","complaintId":1},{"id":2,"status":true,"time":null,"complaintId":1},{"id":3,"status":true,"time":"2018-03-05T10:53:14.000Z","complaintId":2},{"id":6,"status":false,"time":"2018-03-05T11:58:45.000Z","complaintId":1},{"id":7,"status":true,"time":"2018-03-05T12:11:53.000Z","complaintId":1},{"id":8,"status":false,"time":"2018-03-05T13:23:13.000Z","complaintId":2},{"id":9,"status":true,"time":"2018-03-05T08:17:18.000Z","complaintId":3},{"id":10,"status":true,"time":"2018-03-05T12:32:08.000Z","complaintId":2}];
var a = $scope.times;
var b = []; // collect complaintId
for(var i=0;i<a.length;i++){
if(!b.includes(a[i].complaintId)){
b.push(a[i].complaintId);
}
}
var c = []; // collect duplicates per complaintId
for(var i=0;i<b.length;i++){
var temp = []
for(var j=0;j<a.length;j++){
if(b[i] == a[j].complaintId){
temp.push(a[j])
}
}
c.push(temp)
}
// now it's safe to `reduce` the inner arrays (per complaintId)
var d = []; // .forEach .reduce
for(var i=0; i<c.length;i++){
var temp = c[i][0].time;
var temp2 = c[i][0];
for(var j=1; j<c[i].length;j++){
if(c[i][j].time){
if(new Date(c[i][j].time).valueOf() > new Date(temp).valueOf()){
temp = c[i][j].time;
temp2 = c[i][j];
}
}
}
d.push(temp2)
}
$scope.times = d;
});
</script>
</body>
</html>

You can use the Angular Filter module
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-filter/0.5.8/angular-filter.min.js"></script>
And then filter out the duplicates using:
ng-repeat="time in times | unique: 'complaintId'"
angular.module('app', ['angular.filter'])
.controller('test', function($scope) {
$scope.items = [
{
"id": 1,
"status": true,
"time": "2018-03-05T10:24:15.000Z",
"complaintId": 1
},
{
"id": 2,
"status": true,
"time": null,
"complaintId": 1
},
{
"id": 3,
"status": true,
"time": "2018-03-05T10:53:14.000Z",
"complaintId": 2
},
{
"id": 6,
"status": false,
"time": "2018-03-05T11:58:45.000Z",
"complaintId": 1
},
{
"id": 7,
"status": true,
"time": "2018-03-05T12:11:53.000Z",
"complaintId": 1
},
{
"id": 8,
"status": false,
"time": "2018-03-05T13:23:13.000Z",
"complaintId": 2
},
{
"id": 9,
"status": true,
"time": "2018-03-05T08:17:18.000Z",
"complaintId": 3
},
{
"id": 10,
"status": true,
"time": "2018-03-05T12:32:08.000Z",
"complaintId": 2
}
]
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.5/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-filter/0.5.8/angular-filter.min.js"></script>
<div ng-app="app">
<div ng-controller="test">
<table>
<tr ng-repeat="item in items | unique: 'complaintId'">
<td>{{$index + 1}}</td>
<td>{{item.status}}</td>
</tr>
</table>
</div>
</div>

Try using loadash lib.
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.js"></script>
<body>
<div ng-app="myApp" ng-controller="myCtrl">
<div ng-repeat="c in times">
{{c.complaintId}} - {{c.time}}
</div>
</div>
<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.times= [{
"id": 1,
"status": true,
"time": "2018-03-05T10:24:15.000Z",
"complaintId": 1
},
{
"id": 3,
"status": true,
"time": "2018-03-05T10:53:14.000Z",
"complaintId": 2
},
{
"id": 6,
"status": false,
"time": "2018-03-05T11:58:45.000Z",
"complaintId": 1
},
{
"id": 7,
"status": true,
"time": "2018-03-05T12:11:53.000Z",
"complaintId": 1
},
{
"id": 8,
"status": false,
"time": "2018-03-05T13:23:13.000Z",
"complaintId": 2
},
{
"id": 9,
"status": true,
"time": "2018-03-05T08:17:18.000Z",
"complaintId": 3
},
{
"id": 10,
"status": true,
"time": "2018-03-05T12:32:08.000Z",
"complaintId": 2
}
];
$scope.times = _.sortBy($scope.times,'time').reverse();
$scope.times= _.uniqBy($scope.times, 'complaintId');
// console.log($scope.times);
});
</script>
</body>
</html>

Related

How to add object to specific place in JavaScript?

I am using a library React simple chatbot and add data from database, but the problem is i have array like below
Array from Database
[{
"id": 1,
"message": "What is your name?",
"type": "text",
"trigger": "2"
}, {
"id": 2,
"message": "What is your age?",
"type": "text",
"trigger": "3"
}, {
"id": 3,
"message": "What is your date of birth?",
"type": "text",
"trigger": "1"
}]
But i need something like below
[{
"id": 1,
"message": "What is your name?",
"type": "text",
"trigger": "2"
}, {
"id": 2,
"user": true,
"trigger": 3
}, {
"id": 3,
"message": "What is your age?",
"type": "text",
"trigger": "4"
}, {
"id": 4,
"user": true,
"trigger": 5
}, {
"id": 5,
"message": "What is your date of birth?",
"type": "text",
"trigger": "6"
}, {
"id": 6,
"user": true,
"trigger": 1
}]
Please help me to create array like this. I write some code, but doesn't work for me. My code print duplicate ids. Basically i want to pass object after every object with increment id.
Code
fetch("api_url_here")
.then((res) => {
return res.json();
})
.then((data) => {
const steps = data.map((res, index) => {
return {
id: index,
message: res.question,
type: res.type,
trigger: res.trigger,
};
});
var array = [];
var trigger = 1;
steps.forEach((step, index) => {
index = index;
array.push(step);
if (step.type == "text") {
array.push({
id: trigger + 1,
user: true,
trigger: trigger,
});
}
trigger++;
});
document.getElementById("json").append(JSON.stringify(array));
})
Current Output
[{
"id": 0,
"message": "What is your name?",
"type": "text",
"trigger": "2"
}, {
"id": 2,
"user": true,
"trigger": 1
}, {
"id": 1,
"message": "What is your age?",
"type": "text",
"trigger": "3"
}, {
"id": 3,
"user": true,
"trigger": 2
}, {
"id": 2,
"message": "What is your date of birth?",
"type": "text",
"trigger": "1"
}, {
"id": 4,
"user": true,
"trigger": 3
}]
Any solution appreciated!
You only need to add this as a final step to correct the id and trigger
const almost = [{
"id": 0,
"message": "What is your name?",
"type": "text",
"trigger": "2"
}, {
"id": 2,
"user": true,
"trigger": 1
}, {
"id": 1,
"message": "What is your age?",
"type": "text",
"trigger": "3"
}, {
"id": 3,
"user": true,
"trigger": 2
}, {
"id": 2,
"message": "What is your date of birth?",
"type": "text",
"trigger": "1"
}, {
"id": 4,
"user": true,
"trigger": 3
}]
const final = almost.map( (obj,index) => {
const newObj = {};
Object.assign(newObj,
obj,
{
"id":index+1,
"trigger": index+2
}
);
return newObj;
});
final[final.length-1].trigger = 1;
console.log(final)
EDIT: to make it clear, your code would look like:
fetch("api_url_here")
.then((res) => {
return res.json();
})
.then((data) => {
const steps = data.map((res, index) => {
return {
id: index,
message: res.question,
type: res.type,
trigger: res.trigger,
};
});
var array = [];
var trigger = 1;
steps.forEach((step, index) => {
index = index;
array.push(step);
if (step.type == "text") {
array.push({
id: trigger + 1,
user: true,
trigger: trigger,
});
}
trigger++;
});
array = array.map( (obj,index) => {
const newObj = {};
Object.assign(newObj,
obj,
{
"id":index+1,
"trigger": index+2
}
);
return newObj;
});
array[array.length-1].trigger = 1;
document.getElementById("json").append(JSON.stringify(array));
})

Ionic 2 (Angular) GroupBy Pipe

I'm having a trouble grouping my objects, I'm trying to use the ngx-group-by pipe but it doesn't seem to solve my problem.
Assuming the data structure is :
Every company has it products (which contains sub products), and it prices;
For example our company is XXX and it sales cars and motorcycles:
Products : TwoWheels , FourWheels
SubProducts : Bike,Motorcycle (TwoWheels) , Cars (FourWheels)
I'm trying to display the price for every SubProduct and group it by the ProductId
Here's my Json:
{
"id": 1,
"firstName": "test",
"lastName": "tast",
"displayName": "myname",
"profilePic": "none",
"location": "mylocation",
"pricingList": [
{
"id": 1,
"userId": 1,
"ProductId": 1,
"subProductId": 1,
"price": 50,
"subProduct": {
"id": 1,
"ProductId": 1,
"name": "MotorCycle",
"treatment": {
"id": 1,
"name": "TwoWheels"
}
},
"Product": {
"id": 1,
"name": "TwoWheels"
}
},
{
"id": 2,
"userId": 1,
"ProductId": 1,
"subTreatmentId": 7,
"price": 50,
"subProduct": {
"id": 7,
"ProductId": 1,
"name": "bike",
"Product": {
"id": 1,
"name": "TwoWheels"
}
},
"Product": {
"id": 1,
"name": "TwoWheels"
}
},
{
"id": 3,
"userId": 1,
"ProductId": 2,
"subTreatmentId": 8,
"price": 30,
"subProduct": {
"id": 8,
"treatmentId": 2,
"name": "Car",
"Product": {
"id": 2,
"name": "FourWheels"
}
},
"Product": {
"id": 2,
"name": "FourWheels"
}
}
]
}
And here's my Ionic 2/Angular html:
<div *ngFor="let p of User.pricingList | groupBy:p.ProductId">
<div class="ProductTitle">{{p.Product.name}}</div>
<div>
<div class="myClass">Name</div>
<div class="myClass">Price</div>
</div>
<div style="myClass2">
<div class="myClass">{{p.subProduct.name}}</div>
<div class="myClass">{{p.price}}</div>
</div>
</div>
GroupByPipe implementation

Fuzzy search deep array only on certain properties

I have a JSON dataset which could be very large when it returns, with the following structure for each object:
{
"ctr": 57,
"averageECPC": 23,
"cost": 2732.54,
"margin": 66,
"profit": 2495.9,
"property": {
"value": "Izzby",
"uri": "/Terrago/2"
},
"status": {
"content": "<p>Some Content</p>",
"stage": 1
},
"alerts": {
"status": 2
},
"revenue": {
"value": 2573.13,
"compare": 0
},
"children": [{
"ctr": 79,
"averageECPC": 54,
"cost": 3554.78,
"margin": 88,
"profit": 3145.81,
"property": {
"value": "Comvex",
"uri": "/Octocore/4"
},
"status": {
"content": "<p>Some Content</p>",
"stage": 1
},
"alerts": {
"status": 2
},
"revenue": {
"value": 1247.92,
"compare": 0
}
}]
}
Now I want to search all objects in the array and return only objects which include a string of some sort, but I only want to search certain properties.
I basically have another array which contains the keys I want to search, e.g.
const iteratees = ['ctr', 'property.value', 'status.stage']
I have lodash available within the project, but I have no idea where to start.
Any ideas?
You could use filter(), some() and reduce() to do this.
const iteratees = ['ctr', 'property.value', 'status.stage'];
var searchFor = 'lo';
var result = arr.filter(function(o) {
return iteratees.some(function(e) {
var res = e.split('.').reduce(function(a, b) {
if(a) return a[b];
}, o);
if(res) {
if((res).toString().indexOf(searchFor) != -1) return true;
}
})
})
var arr = [{
"ctr": 'lorem',
"averageECPC": 23,
"cost": 2732.54,
"margin": 66,
"profit": 2495.9,
"property": {
"value": "Izzby",
"uri": "/Terrago/2"
},
"status": {
"content": "<p>Some Content</p>",
"stage": 1
},
"alerts": {
"status": 2
},
"revenue": {
"value": 2573.13,
"compare": 0
},
"children": [{
"ctr": 79,
"averageECPC": 54,
"cost": 3554.78,
"margin": 88,
"profit": 3145.81,
"property": {
"value": "Comvex",
"uri": "/Octocore/4"
},
"status": {
"content": "<p>Some Content</p>",
"stage": 1
},
"alerts": {
"status": 2
},
"revenue": {
"value": 1247.92,
"compare": 0
}
}]
}, {
name: 'lorem',
ctr: 12,
property: {
value: 1
},
status: {
stage: 1
}
}, {
name: 'ipsum'
}]
const iteratees = ['ctr', 'property.value', 'status.stage'];
var searchFor = 'lo';
var result = arr.filter(function(o) {
return iteratees.some(function(e) {
var res = e.split('.').reduce(function(a, b) {
if (a) return a[b];
}, o);
if (res) {
if ((res).toString().indexOf(searchFor) != -1) return true;
}
})
})
console.log(result)

Applying filter on parent if it has been applied on children AngularJS

I have a list with items and have applied filter on those items by value from text box. I want to get new filtered list with parent and its children if parent has at least one filtered item.If doesn't, that parent should not be displayed.
For an example: If I enter "3D" in the text box I don't want to get "Day parts" and "Week parts" listed below as they don't have children anymore after filtering.
<div ng-controller="Ctrl">
<input type="text" data-ng-model="inputValue.name"/>
<ul data-ng-repeat="condition in conditions">
<div data-ng-click="setHeadingStatus(condition)">
<div>
{{condition.name}}
</div>
<li ng-repeat="item in condition.items | filter:inputValue">
<div class="custom-typeahead-list-title">{{item.name}}</div>
<div class="custom-typeahead-list-desc">{{item.description}}</div>
</li>
</div>
</ul>
function Ctrl($scope , $filter){
$scope.countryCode = 1;
$scope.conditions = [
{
"id": 1,
"name": "Experiences",
"expanded": false,
"items": [
{
"id": 1,
"name": "3D"
},
{
"id": 2,
"name": "Imax"
},
{
"id": 3,
"name": "D-Box"
},
{
"id": 4,
"name": "THX"
}
]
},
{
"id": 2,
"name": "Day parts",
"expanded": false,
"items": [
{
"id": 1,
"name": "Early Bird"
},
{
"id": 2,
"name": "Matinee"
},
{
"id": 3,
"name": "Last Night"
}
]
},
{
"id": 3,
"name": "Week parts",
"expanded": false,
"items": [
{
"id": 1,
"name": "Monday"
},
{
"id": 2,
"name": "Wednesday"
},
{
"id": 3,
"name": "Weekend"
}
]
}
]
}
Here is the example of it
http://jsfiddle.net/KJ3Nx/48/
You can put an ng-show on the div that displays each block, and set the expression to the filtered length;
<div data-ng-show="(condition.items | filter:inputValue).length > 0" data-ng-click="setHeadingStatus(condition)">
Updated fiddle

How to exclude a specific id from an array?

I have an array with sports names, with the option to check and uncheck them.
The items with checked = false are being saved in a DB. By default all the items are in checked = true, BUT, I want to exclude one of the items in the array and put it to checked = false instead.
at first, the array looks like this
[
{
"id": 26,
"name": "LIVE Betting",
"priority": 0
},
{
"id": 8,
"name": "NBA",
"priority": 1
},
{
"id": 24,
"name": "College Basketball",
"priority": 2
},
{
"id": 42,
"name": "Women College Basketball",
"priority": 3
},
{
"id": 9,
"name": "NHL",
"priority": 4
},
{
"id": 6,
"name": "MLB",
"priority": 5
}
]
and this is the function working over here
_this.getSportChecked(customer).then(function(sportChecked) {
var sportIds = _.pluck(sports, 'id'),
intersectedSports = _.intersection(sportIds, sportChecked.sport);
if (sports.length) {
//HERE I NEED TO EXCLUDE THE ID 9
sports = _.map(sports, function(sport) {
sport.checked = !_.includes(intersectedSports, sport.id);
return sport;
});
}
});
which returns this objects
{
"id": 26,
"name": "LIVE Betting",
"priority": 0,
"checked": true
}
{
"id": 8,
"name": "NBA",
"priority": 1,
"checked": true
}
{
"id": 24,
"name": "College Basketball",
"priority": 2,
"checked": true
}
{
"id": 42,
"name": "Women College Basketball",
"priority": 3,
"checked": true
}
{
"id": 9,
"name": "NHL",
"priority": 4,
"checked": true
}
{
"id": 6,
"name": "MLB",
"priority": 5,
"checked": true
}
so as you can see all those items are checked = true by default, but I want to set up the id = 9 to checked = false by default until the user switches it to true in case that he wants.
What are your suggestions here? read the note in my code please, there is the part where I need to exclude it.
Well, you can simply find the sport by id and uncheck it manually.
if (sports.length) {
//HERE I NEED TO EXCLUDE THE ID 9
sports = _.map(sports, function(sport) {
sport.checked = !_.includes(intersectedSports, sport.id);
// Special case for id 9
if (sport.id === 9) {
sport.checked = false;
}
return sport;
}

Categories

Resources