Compare objects in angularjs - angularjs

What I'm trying to achieve is that if a Post contains comments, it should display the comments. I tried the angular.equals, which either doesn't work or I am not familiar on how to use it right?
Here's the Controller for both Post and Comment.
var PostController = function ($scope, $location, Post, Comment) {
$scope.search = function () {
Post.query({
offset: $scope.offset,
limit: $scope.limit
},
function (data) {
$scope.more = data.length === 20;
$scope.posts = $scope.posts.concat(data);
});
};
$scope.searchComments = function () {
Comment.query({
},
function (data) {
$scope.comments = data;
});
};
$scope.showComment = function () {
angular.equals(Post, Comment);
}
}
And here's from the view:
<ul class="posts">
<li ng-repeat="post in posts">
<div class="post-info">
<h1>{{post.title}}</h1>
<div class="right-section">
<div class="edit-post-button right">Edit</div>
<span class="reputation right">{{post.reputation}}</span>
</div>
</div>
<br />
<div class="post-box">
<p>
{{post.content}}
</p>
</div>
<br />
<ul>
<li ng-repeat="comment in comments" ng-show="showComment()">
{{comment.content}}
</li>
</ul>
</li>
</ul>
Maybe this could be done in the back-end? I am not sure?

It seems like you want to filter the comments to a particaular post. As you have said in comments, the Comment resource has a pid that ties it to a particular post.
The best way to accomplish the filtering is with an angular filter.
In this way, you don't need to compare anything with equals, you can just filter the comments in the markup:
<ul>
<li ng-repeat="comment in comments | filter:{ pid: post.id }">
{{comment.content}}
</li>
</ul>

Related

How to limit results with ng-repeat?

Sorry for the basic question, extremely new to software development and angular in particular. I'm currently making a small app that uses an api to find cinemas near a certain postcode.
I have made a results page that show what films are playing in a certain cinema, but I want to limit the amount of results returned and include a 'Show more films' button.
I have included my html and controller below:
HTML
<div class="main-container">
<fountain-header></fountain-header>
<div class="cinemas-container">
<h2 align="center" class="cinemas-h2">Movies playing here:</h2>
<div class="cinema2" ng-repeat="listing in $ctrl.listings">
<h3 class="cinema-h5">{{listing.title}}</h3>
<ul class="cinema-h4">
<li ng-repeat="time in listing.times">{{time}}</li>
</ul>
</div>
<div class="main-container">
</main>
</div>
<fountain-footer></fountain-footer>
</div>
</div>
ListingsController
function ListingsController($http, $stateParams) {
console.log($stateParams);
console.log($stateParams.cinemaID);
var vm = this;
$http
.get('https://api.cinelist.co.uk/get/times/cinema/' + $stateParams.CinemaID +'?day=1')
.then(function (response) {
console.log(response);
vm.listings = response.data.listings;
});
}
Could I just use limitTo to achieve this?
P.S sorry for the poor information, it's my first question on here.
Please try the following example in the fiddle link -
Using the limitTo filter.
ng-repeat="d in data | limitTo: limitvar"
https://jsfiddle.net/m0q9ju8a/
let me know if this helps.
You can do like this:
HTML
<div class="main-container">
<fountain-header></fountain-header>
<div class="cinemas-container">
<h2 align="center" class="cinemas-h2">Movies playing here:</h2>
<div class="cinema2" ng-repeat="listing in vm.listings | limitTo: vm.limit as results">
<h3 class="cinema-h5">{{listing.title}}</h3>
<ul class="cinema-h4">
<li ng-repeat="time in vm.listing.times">{{time}}</li>
</ul>
</div>
<button ng-hide="results.length === vm.listings.length" ng-click="vm.limit = vm.limit +8">show more...</button>
<div class="main-container">
</main>
</div>
<fountain-footer></fountain-footer>
</div>
</div>
and in youn controller
function ListingsController($http, $stateParams) {
console.log($stateParams);
console.log($stateParams.cinemaID);
var vm = this;
vm.limit = 8;
$http
.get('https://api.cinelist.co.uk/get/times/cinema/' + $stateParams.CinemaID +'?day=1')
.then(function (response) {
console.log(response);
vm.listings = response.data.listings;
});
}

all arrays are not showing with angular

This is my controller that will fetch all notes for my main page. When I console.log($scope.allNotes) all my arrays are logged but when I render with my HTML only 1 array shows up
exports.allNotesController = function ($scope, $http, $notes) {
$notes.fetchNotes().then(function (result) {
var data = result.data
data.filter(function (notes) {
$scope.allnotes = notes.notes
console.log($scope.allnotes)
})
})
}
my HTML:
<section class="row all-notes">
<h1>All Notes</h1>
<div class="allNotes">
<ul ng-repeat="notes in allnotes">
<li>{{ notes }}</li>
</ul>
</div>
</section>
<a class="btn btn-default" href="#/login">Login</a>
I solved it in a very hacky way.
Heres my new controller
exports.allNotesController = function ($scope, $http, $notes) {
$notes.fetchNotes().then(function (result) {
$scope.allnotes = result.data
})
}
my HTML, this is where the magic happens. lol
<ul ng-repeat="notes in allnotes track by $index">
<li>{{ notes.notes.toString() }}</li> // i had no idea I can use toString() here
</ul>

Angular.js - ng-repeat not working

Angular.js is pretty new to me. I have learned before the $scope method for the controller and now trying the "this" method. For some reason I can not get my ng-repeat to work. here's my code:
HTML:
<ul class="nav nav-pills">
<li><a ng-click="myCtrl.tab=1" href>one</a></li>
<li><a ng-click="myCtrl.tab=2" href>two</a></li>
<li><a ng-click="myCtrl.tab=3" href>three</a></li>
</ul>
<div ng-controller="imageContr as imageCtrl">
<div ng-show="myCtrl.tab === 1" class="tab">
<h3>ONE title</h3>
<p>hello</p>
<li ng-repeat="item in gallery">
<img alt="imagealt" ng-src="{{item.photo}}">
</li>
</div>
<div ng-show="myCtrl.tab === 2" class="tab">
<h3>TWO title</h3>
<p>how are</p>
</div>
<div ng-show="myCtrl.tab === 3" class="tab">
<h3>THREE title</h3>
<p>you?</p>
</div>
</div>
</section>
</body>
</html>
APP.JS:
(function() {
var app = angular.module('myApp', []);
app.controller('myController', function() {
this.tab = 1;
});
app.controller('imageContr', function() {
this.gallery = images;
var images = {
photo: 'image1.jpg'
};
});
})();
Declare images before you assign it, and make it an array
var images = [{ photo: 'image1.jpg' }];
this.gallery = images;
Then in your view:
<li ng-repeat="item in imageCtrl.gallery">
<img alt="imagealt" ng-src="{{item.photo}}">
</li>
You are storing the gallery on this of the controller (which is basically the $scope), hence you need to access it in the template via imageContr as well:
<li ng-repeat="item in imageCtrl.gallery">
<img alt="imagealt" ng-src="{{item.photo}}">
</li>
You could also consider making gallery an array, so can easily iterate over it. Or you need to use the "iterate over object properties"-syntax:
<div ng-repeat="(key, value) in myObj"> ... </div>

How do I target just one instance of a nested repeat?

This is probably pretty basic, but I'm going round in circles.
I have a nested controller in a ng-repeat - I would like to trigger an event in an instance of the repeat that will affect only the nested controller in that instance, not the nested controller in all instances.
Here is a basic example to try and make things clearer:
<div ng-controller="PostsCtrl">
<div ng-repeat="post in posts">
<p>{{post.body}}</p>
<div ng-controller="CommentsCtrl">
<div ng-repeat="comment in comments">
<p>{{comments.body}}</p>
<a href ng-click="showComments(post.id)">Show comments</a>
</div
</div>
</div>
</div>
angular.module('myApp')
.controller('PostsCtrl', function ($scope, Restangular) {
var posts = Restangular.all('posts');
posts.getList().then(function(posts) {
$scope.posts = posts;
});
$scope.showComments = function(id) {
$scope.$broadcast('SHOW_COMMENTS', id);
};
});
angular.module('myApp')
.controller('CommentsCtrl', function ($scope, Restangular) {
$scope.$on('SHOW_COMMENTS', function(event, id) {
var post = Restangular.one('posts', id);
post.get().then(function(post) {
$scope.comments = post.comments;
});
});
});
What would happen in this example is that all instances of the comments controller would be populated with the same comments - I just need to be able to target the relevant one. I'm sure I'm missing something pretty fundamental, and probably going about this the wrong way.
Many thanks.
You're broadcasting "SHOW_COMMENTS" to all repeated posts. You need to isolate the scope per Post.
Isolate the scope using ng-controller="PostCtrl".
<div ng-controller="PostsCtrl">
<div ng-repeat="post in posts" ng-controller="PostCtrl">
<p>{{post.body}}</p>
<div ng-controller="CommentsCtrl">
<div ng-repeat="comment in comments">
<p>{{comments.body}}</p>
<a href ng-click="showComments()">Show comments</a>
</div
</div>
</div>
</div>
Move show comments from PostsCtrl to PostCtrl.
angular.module('myApp')
.controller('PostCtrl', function ($scope) {
$scope.showComments = function() {
$scope.$broadcast('SHOW_COMMENTS', $scope.post.id);
};
});
Do you really need to use events? You could use ng-if instead.
Your comments are embedded in each Post anyway so why request them again. In this case you could do like something this...
<div ng-controller="PostsCtrl">
<div ng-repeat="post in posts" ng-controller="PostCtrl">
<p>{{post.body}}</p>
<a href ng-click="toggleComments()">Show comments</a>
<div ng-controller="CommentsCtrl" ng-if="showComments">
<div ng-repeat="comment in post.comments">
<p>{{comments.body}}</p>
</div
</div>
</div>
</div>
Toggle comments...
angular.module('myApp')
.controller('PostCtrl', function ($scope) {
$scope.showComments = false;
$scope.toggleComments = function() {
$scope.showComments = !$scope.showComments;
};
});

order item in ngrepeat follow property of item

How can I order the post to top-down structure (the post which has highest likes number will be first and the last is the post which lowest likes number). To do that I set oderBy:likes.length but it is not work. Please help, thanks!
function MyController($scope) {
$scope.posts = [{"title": "AAtitle",
"content":"AAcontent",
"likes":["person1", "person2", "person3"]
},
{"title": "BBtitle",
"content":"BBcontent",
"likes":["person10"]
},
{"title": "CCtitle",
"content":"CCcontent",
"likes":["person10","person11", "person100", "person1", "person2"]
}
]
}
<div ng-controller = "MyController">
<ul>
<li ng-repeat = "post in posts | oderBy: likes.length">
<div> {{post.title}} </div>
<div> {{post.content}} </div>
<div> {{post.likes.length}} </div>
</li>
</ul>
</div>
You could write a function to do the sorting in the controller before displaying in view. Or preferable, you could write a custom filter
Filter:
angular.module('YourAppName', [])
.filter('orderByLikes', function() {
function compare(a, b) {
return b.likes.length - a.likes.length;
}
return function (input) {
return input.sort(compare);
}
});
View:
<div ng-controller = "MyController">
<ul>
<li ng-repeat = "post in posts | orderByLikes:posts">
<div> {{post.title}} </div>
<div> {{post.content}} </div>
<div> {{post.likes.length}} </div>
</li>
</ul>
</div>
Here is a working Fiddle

Resources