How to get distinct value using lodash in ReactJS? - reactjs

How to get distinct value using lodash in ReactJS? Now I'm getting all the data. But how to avoid printing duplicate data? Actually it is a filter box. So data repetition I've to avoid. Can anyone help me out?
Function:
comboClick () {
var apiBaseUrl = "http://api.eventsacross-stage.railsfactory.com/api/";
var input = this.state.search_event;
let self = this;
axios.get(apiBaseUrl+'v1/events/?on_dashboard=false'+input)
.then(function (response) {
let events = response.data.events;
self.setState({events: events});
console.log(response);
})
.catch(function (error) {
console.log(error);
});
}
Jsx Part:
<div className="dropdown text-center">
<button
className="btn btn-default dropdown-toggle"
type="button"
data-toggle="dropdown"
style={{width: "50%"}}
onClick={this.comboClick.bind(this)}>
Place
<span className="caret"></span>
</button>
<ul className="dropdown-menu">
{this.state.events.map(function (event, i) {
return (
<div key={i}>
{event.locations.map(function (locations, j) {
return (
<li key={j}><p>{locations.city}</p></li>
)
})}
</div>
)
})}
</ul>
</div>

You can use _.uniqBy, as per documentation:
This method is like _.uniq except that it accepts iteratee which is
invoked for each element in array to generate the criterion by which
uniqueness is computed. The order of result values is determined by
the order they occur in the array. The iteratee is invoked with one
argument: (value).
I've added an example:
var locations =
[
{city:"city1"},
{city:"city2"},
{city:"city3"},
{city:"city1"},
];
var locationsUnique = _.uniq(locations, 'city');
console.log(locationsUnique);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/2.4.1/lodash.min.js"></script>
UPDATE:
From the method shared in the comments I'm guessing that what you want to do is something like:
comboClick() {
var apiBaseUrl = "api.eventsacross-stage.railsfactory.com/api/";
var input = this.state.search_event;
let self = this;
axios.get(apiBaseUrl + 'v1/events/?on_dashboard=false' + input).then(function(response) {
let events = response.data.events;
for (var i = 0; i < response.data.events_count; i++) {
var obj = response.data.events[i];
console.log(obj.locations);
//Assuming that obj.locations has the locations that you want to display
var locationsUnique = _.uniq(obj, 'city'); //Added this line
console.log(locationsUnique); //Added this line
}
for (var j = 0; j <= obj; j++) {}
self.setState({events: events});
}).catch(function(error) {
console.log(error);
});
}

Related

InfiniteScroll - AngularJS not working

Edit:
Just for checking purposes, I also did a console.log inside the nextPage function, to check if it's being triggered:
$scope.nextPage = function() {
var captureLength = $scope.captures.length;
console.log('TRIGGER');
if($scope.busy) {
return;
}
...
}
};
And it seems I'm getting a infinite loop, but I can't see why.
=================================
I'm trying to implement infinitescroll into a view but for some reason it's only loading the initial 4 images and not triggering the rest.
Here is my code:
CTRL:
/* ----------------------- Variables ----------------------- */
$scope.auth = auth;
$scope.captures = [];
$scope.following = [];
$scope.allData = [];
$scope.busy = true;
var page = 0;
var step = 4;
$scope.nextPage = function() {
var captureLength = $scope.captures.length;
if($scope.busy) {
return;
}
$scope.busy = true;
$scope.captures = $scope.captures.concat($scope.allData.splice(page * step, step));
page++;
$scope.busy = false;
if($scope.captures.length === 0) {
$scope.noMoreData = true;
}
};
/* ----------------------- Process Data ----------------------- */
$q.all({follows: findFollow(), users: getUsers(), captures: getAllCaptures()}).then(function(collections) {
var follows = collections.follows;
var users = collections.users;
var captures = collections.captures;
follows.filter(function(follow) {
return follow.follower_id === auth.profile.user_id;
}).forEach(function(follow) {
users.filter(function(user) {
return user.user_id === follow.followed_id;
}).forEach(function(user) {
$scope.following.push(user);
});
});
follows.filter(function(follow) {
return follow.follower_id === auth.profile.user_id;
}).forEach(function(follow) {
captures.filter(function(capture){
return follow.followed_id === capture.userId;
}).forEach(function(capture){
console.log(capture);
$scope.allData.push(capture);
});
});
$scope.nextPage();
$scope.busy = false;
});
/* ----------------------- Retrieve Services - Data ----------------------- */
function findFollow() {
return userApi.findFollow().then(function(res) {
return res.data;
});
}
function getUsers() {
return userApi.getUsers().then(function(res) {
return res.data.users;
});
}
function getAllCaptures() {
return captureApi.getAllCaptures().then(function(res) {
return res.data;
});
}
Partial:
<div class="col-md-8">
<div class="well main-well">
<h3 class="page-header-h3">Following Dashboard:</h3>
<hr />
<h4 align="center" ng-show="!captures.length">
<strong>The people that you are following, have not posted anything yet.. Yikes!</strong>
<br /><br />
Quickly, go follow more people!</h4>
<div class="row" infinite-scroll="nextPage()" infinite-scroll-disabled="busy || noMoreData" infinite-scroll-distance="0.1">
<ul class="dynamic-grid" angular-grid="captures" ag-id="gallery">
<li data-ng-repeat="capture in captures | orderBy :'created_at':true" class="grid">
<a ui-sref="detail({id: capture._id})">
<img ng-src="{{capture.picture}}" class="grid-img" />
<span class="follow-capture-info">
<span class="follow-capture-name"><span class="glyphicon glyphicon-user"></span>
{{capture.author}}
<span class="following-capture-time">·
<span class="glyphicon glyphicon-time"></span>
<span am-time-ago="capture.created_at"></span>
</span>
</span>
</span>
</a>
</li>
</ul>
</div>
<div ng-show="busy">Loading more...</div>
</div>
Anyone know where I went wrong?
Thanks.

Get model array values in controller's service

I've been facing an issue since couple of hours. My view template looks like-
<div class="row" ng-repeat="row in CampaignsService.getRows().subItems track by $index">
<div class="col-sm-2">
<select class="form-control dropDownPercent" ng-model="CampaignsService.dropDownPercent[{{CampaignsService.selectCounter}}]" ng-change="CampaignsService.wow(CampaignsService.dropDownPercent, $index)" ng-options="o as o for o in CampaignsService.showPercentDropDown().values">
</select>
</div>
<div class="col-sm-2" style="line-height: 32px">
of visitors send to
</div>
<div class="col-sm-4">
<select class="form-control" ng-model="campaignSelect" ng-options="campaign.Campaign.id as campaign.Campaign.title for campaign in CampaignsService.getRows().items">
<option value=""> Please select </option>
</select>
</div>
<div class="col-sm-4">
<a class="btn btn-default" target="_blank" href="">Show campaign</a>
</div>
Variable CampaignsService.selectCounter is a counter variable and declared in service but when I'm going to use ng-model="CampaignsService.dropDownPercent[{{CampaignsService.selectCounter}}]" it gives me error -
Error: [$parse:syntax] Syntax Error: Token '{' invalid key at column 35 of the expression [CampaignsService.dropDownPercent[{{CampaignsService.selectCounter}}]] starting at [{CampaignsService.selectCounter}}]]
And when I use ng-model="CampaignsService.dropDownPercent['{{CampaignsService.selectCounter}}']" it does not give any error but it takes this variable as string.
My question is how could I create a model array and get model's array values in my service ?? I read many questions in stack community and none of the trick work for me. My service under my script, is
.service('CampaignsService', ['$rootScope', 'AjaxRequests', function ($rootScope, AjaxRequests) {
this.dropDownPercent = [];
this.selectCounter = 0;
var gareeb = [];
this.showPercentDefault = 100;
// this.campaignsData = [];
this.$rowsData = {
items: [], //array of objects
current: [], //array of objects
subItems: [] //array of objects
};
this.getRows = function () {
return this.$rowsData;
}
this.addNewRow = function () {
var wowRow = {}; //add a new object
this.getRows().subItems.push(wowRow);
this.selectCounter++;
gareeb.push(0);
}
this.calculatePercentages = function (index) {
angular.forEach(this.getRows().current, function (data, key) {
if (key == index) {
console.log(data);
}
})
}
this.showPercentDropDown = function ($index) {
var balle = 0;
var start;
angular.forEach(gareeb, function (aha, keywa) {
balle += aha;
})
var last = 100 - balle;
var final = [];
for (start = 0; start <= last; start += 10) {
final.push(start);
}
return this.values = {
values: final,
};
}
this.wow = function (valueWa, keyWa) {
console.log(this.dropDownPercent);
gareeb[keyWa] = valueWa;
this.changePercentDropDown();
}
this.changePercentDropDown = function () {
var angElement = angular.element(document.querySelector('.dropDownPercent'));
angular.forEach(angElement, function (data, key) {
console.log(data);
})
}
}])
Target model structure should be
ng-model="CampaignsService.dropDownPercent[1]"
ng-model="CampaignsService.dropDownPercent[2]"
ng-model="CampaignsService.dropDownPercent[3]"
A big thanks in advance.
Since you are in context of the Angular expression, you don't need interpolation tags {{...}}. So ngModel directive should look like this:
ng-model="CampaignsService.dropDownPercent[CampaignsService.selectCounter]"

ng hide/show based on list values

I need to hide the "Current insurance cover" when coverAmt of all the covers in the list are zero or negative value. If any one coverAmt in the list is positive value then I need show the "Current insurance cover" only once.
I tried with something like this, but now no luck..!
<li ng-repeat="cover in accSummary.response.covers">
<div class="account-detail-row col-xs-12 col-sm-12 col-md-12 padding-left12 padding-right12 padding-top24 padding-bottom12">
<h4 class="font-16 fontwt-400" ng-hide="cover.coverAmt <= 0">Current insurance cover</h4>
</div>
</li>
can anybody please help me on this..! thanks.
You have to calculate this in your controller as below:
app.controller("cover", function($scope){
$scope.covers = [{coverAmt: 10},{coverAmt: 0},{coverAmt: -1}];
$scope.showHeading = function(){
var flag = false;
for(var i=0; i<$scope.covers.length; i++)
{
if($scope.covers[i].coverAmount > 0)
{
flag = true;
break;
}
}
return flag;
};
});
HTML will be
<h4 class="font-16 fontwt-400" ng-show="showHeading();">Current insurance cover</h4>
Try using ```ng-if`` to control the visibility of the Current Insurance Cover. But on the init of the ng-repeat, run a call to loop through the array to test your case.
Below is a sample of what this would look like:
HTML:
<li ng-repeat="cover in accSummary.response.covers" ng-init="checkCover()">
<div class="account-detail-row col-xs-12 col-sm-12 col-md-12 padding-left12 padding-right12 padding-top24 padding-bottom12">
<h4 class="font-16 fontwt-400" ng-if="visible">Current insurance cover</h4>
</div>
</li>
JS:
$scope.visible = false;
$scope.checkCover = function() {
angular.forEach(accSummary.response.covers, function(cover) {
if(cover.coverAmt > 0) { $scope.visible = true; return true; }
}
return false;
}
Firstly if you have the h4 Current insurance cover, within the ng-repeat. If you have multiple positive values, the header will appear multiple times
As for the calculation itself... Rather do that in your controller, then do something like:
<li ng-repeat="cover in accSummary.response.covers">
<div class="account-detail-row">
{{ cover.Something }}
</div>
</li>
<h4 ng-hide="isCurrent">Current insurance cover</h4>
Thus in the success event of the ajax request / promise you could do this:
var total = 0;
$http({ // or whatever request mechanism you're using
url: someURL,
method: "POST",
data: "{}",
headers: { 'Content-Type': 'application/json' }
})
.success(function (data) {
angular.forEach(data.accSummary, function(value, key) {
total += data.accSummary["coverAmt"]
})
})
.finally(function() {
$scope.isCurrent = total <= 0;
})
Or you could create a function and then pass the whole collection through from the view.
Your calculation function could look something like this:
$scope.isCurrent = function(covers) {
var total = 0;
for(var i = 0; i < covers.length; i++){
var cover = covers[i];
total += cover.coverAmt;
}
return total <= 0;
}
Then the usage would be usage:
<h4 ng-hide="isCurrent(accSummary.response.covers)">Current insurance cover</h4>

AngularFire add in reverse order

I need to add objects to Firebase in reverse order. Or reverse data when goes data binding. Or sort objects by time of create.
var ref = new Firebase("https://[url].firebaseio.com/");
$scope.messages = $firebase(ref);
$scope.addMessage = function(e) {
$scope.messages.$add({title: $scope.title, body: $scope.msg, time: $scope.getDate() });
}
<div class="well span3 pull-left note" ng-repeat="(key, msg) in messages">
<button type='button' class='close' ng-click="messages.$remove(key)">×</button>
<b>{{msg.time| date: 'medium'}}</b>
<span>{{msg.title}}</span>
<span>{{msg.body}}</span>
<button ng-click="changeMessage(key)" class="btn btn-mini pull-right"><i class="icon-pencil"></i></button>
</div>
I try to use OrderBy atribute for ng-repeat but this is not easy because in messages are stored objects.
Check out the chat example in angularFire-seed. It uses a custom reverse filter
The reverse filter looks like so:
app.filter('reverse', function() {
function toArray(list) {
var k, out = [];
if( list ) {
if( angular.isArray(list) ) {
out = list;
}
else if( typeof(list) === 'object' ) {
for (k in list) {
if (list.hasOwnProperty(k)) { out.push(list[k]); }
}
}
}
return out;
}
return function(items) {
return toArray(items).slice().reverse();
};
});
And the usage is like so:
<ul id="messages" ng-show="messages">
<li ng-repeat="message in messages | reverse">{{message.text}}</li>
</ul>

Displaying the array elements one by one in a form in Angular js

I am building an application using Angular js and Taffy Db.
I have got a resultset from Taffy DB which is an an array.
I want to display the elements one by one in my HTML page.
javascript:
$scope.viewList = function () {
$scope.sharelists = [];
$scope.resultSet = teamlist().get();
var teamdata = $scope.resultSet;
var length = teamdata.length;
angular.forEach(teamdata, function (teamdata, i) {
if (i < length) {
console.log(i);
$scope.teamlistresult = teamdata.text;
$scope.sharelists.push({
text: $scope.teamlistresult
});
}
});
};
});
HTML:
<label for="sharedby">Shared by</label>
<input class="btn-primary" type="submit" value="View" ng-click="viewList()" />
<ul class="unstyled">
<li ng-repeat="share in sharelist">
<input type="checkbox" ng-model="share.done">
<span>{{share.text}}</span>
</li>
</ul>
But I couldnt display the array elements one by one.
Please advice
I am not sure but if this method
$scope.resultSet = teamlist().get(); is async and returns promise then you should use
teamlist().get().then(function(data) {
var teamdata = data;
var length = teamdata.length;
angular.forEach(teamdata, function (teamdata, i) {
if (i < length) {
console.log(i);
$scope.teamlistresult = teamdata.text;
$scope.sharelists.push({
text: $scope.teamlistresult
});
}
});
}

Resources