angular js to keep track of like and dislike click - javascript

I am trying to develope app in angularjs where i am reading json to read comments with like and dislike button . i am stuck at point where i am not sure how to track if user has already clicked on Like for particular comment ??
data.json::
[ {
"name": "Anam",
"age": 20,
"id": 100,
"commentline": "Yes Good !!!",
"like":5,
"dislike":1
},
{
"name": "Moroni",
"age": 50,
"id": 101,
"commentline": "Yes Good !!!",
"like":5,
"dislike":1
},
{
"name": "Tiancum",
"age": 43,
"id": 102,
"commentline": "Yes Good !!!",
"like":5,
"dislike":1
},
{
"name": "Jacob",
"age": 27,
"id": 103,
"commentline": "Yes Good !!!",
"like":5,
"dislike":1
},
{
"name": "Nephi",
"age": 29,
"id": 104,
"commentline": "Yes Good !!!",
"like":5,
"dislike":1
},
{
"name": "Anam",
"age": 20,
"id": 100,
"commentline": "Yes Good !!!",
"like":5,
"dislike":1
}
]
HTML ::
<!DOCTYPE html>
<html ng-app="FundooDirectiveTutorial">
<head>
<title>Rating Directive Demo</title>
<link rel="stylesheet" href="rating.css"/>
<link rel="stylesheet" type="text/css" href="css/bootstrap.css">
<style>
.sideheading
{
display: inline-block
}
</style>
</head>
<body ng-controller="FundooCtrl">
<h2>Listing All Comments </h2>
<br/><!--
<div class="commentbox" ng-repeat="comment in comments" >
<h4 class="sideheading">comment By:</h4>{{comment.name}}<br/>
<h4 class="sideheading">Comment ::</h4>{{comment.commentline}} <br/>
<h4 class="sideheading">Likes ::</h4> {{comment.like}} <br/>
<h4 class="sideheading">Dislike::</h4> {{comment.dislike}} <br/>
</div>
-->
<div class="panel panel-default" ng-repeat="comment in comments">
<div class="panel-heading">
<h3 class="panel-title">{{comment.name}}</h3>
</div>
<div class="panel-body">
Comment ::{{comment.commentline}} <br/>
Likes :: {{comment.like}}
<button type="button" class="btn btn-default btn-xs" ng-click="incrlikes(comment)">
<span class="glyphicon glyphicon-star"></span> Like
</button>
<button type="button" class="btn btn-default btn-xs" ng-click="decrlikes(comment)">
<span class="glyphicon glyphicon-star"></span> DisLike
</button><br/>
Dislike:: {{comment.dislike}}
<br/>
likeflag::
<br/>
</div>
</div>
<!-- <div fundoo-rating rating-value="rating" max="10" on-rating-selected="saveRatingToServer(rating)"></div>
<br/>
Readonly rating <br/>
<div fundoo-rating rating-value="rating" max="10" readonly="true"></div>
-->
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.6/angular.min.js"></script>
<script type="text/javascript" src="comment.js"></script>
</body>
</html>
JS ::
var app=angular.module('FundooDirectiveTutorial', []);
app.controller('FundooCtrl', function ($scope, $http) {
$http.get('comment.json').success(function(data) {
$scope.comments = data;
$scope.incrlikes=function(a)
{
var selectedIndex=$scope.comments.indexOf( a );
console.log('Likes increment'+a.name);
console.log($scope.comments.indexOf( a ) +'with index of name is '+$scope.comments[selectedIndex].name );
$scope.comments[selectedIndex].like=$scope.comments[selectedIndex].like+1;
$scope.likeflag=1;
if($scope.likeflag==1)
{
}else
{
console.log('Already like');
}
}
});
});
Fiddle::
http://jsfiddle.net/simmi_simmi987/DeKP4/

I solved my this problem using ng-show and ng-hide,
when likeClicked is false then i show like button , and when user click it on it i change variable to false . so automaticaly , dislike button is shown
var app=angular.module('FundooDirectiveTutorial', []);
app.controller('FundooCtrl', function ($scope, $http) {
$http.get('comment.json').success(function(data) {
$scope.comments = data;
$scope.likeClicked=[];
$scope.incrlikes=function(a)
{
var selectedIndex=$scope.comments.indexOf( a );
if(! $scope.likeClicked[selectedIndex])
{
console.log('Likes increment'+a.name);
console.log($scope.comments.indexOf( a ) +'with index of name is '+$scope.comments[selectedIndex].name );
$scope.comments[selectedIndex].like=$scope.comments[selectedIndex].like+1;
$scope.likeClicked[selectedIndex]=true;
}
else
{
console.log('Already like');
}
}
$scope.decrlikes=function(a)
{
var selectedIndex=$scope.comments.indexOf( a );
if($scope.likeClicked[selectedIndex])
{
console.log('Likes increment'+a.name);
console.log($scope.comments.indexOf( a ) +'with index of name is '+$scope.comments[selectedIndex].name );
$scope.comments[selectedIndex].like=$scope.comments[selectedIndex].like-1;
$scope.likeClicked[selectedIndex]=false;
}
else
{
console.log('Already Dislike');
}
}
});
});

Related

SOS, $scope not working on algular js

i am making a http.get that is giving me this answer below, that i am getting from a localhost json:
[
{
"_id": 52562,
"title": "Event name",
"startDate":"20-03-20",
"endDate": "20-03-20",
"description": "Lorem ipsun doloren he jlhdkh skjrlkuslinf sidhkjh this is a test",
"imageUrl": [
"https://images-na.ssl-images-amazon.com/images/G/01/img15/pet-products/small-tiles/23695_pets_vertical_store_dogs_small_tile_8._CB312176604_.jpg",
],
"donateTypes": [{
"_id": 1,
"name": "Fraldas",
"min": 2,
"total": 12
}, {
"_id": 1,
"name": "Fraldas",
"min": 2,
"total": 12
}, {
"_id": 1,
"name": "Fraldas",
"min": 2,
"total": 12
}]
}
];
The thing is, in my html the scope is not rendering, i really don't know why and i have already tried everything! i dont know what to do! anybody can help?
index.html:
<!DOCTYPE html>
<html ng-app="saoVicentinoApp">
<head>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.3/angular.min.js"></script>
<script data-require="angular-route#*" data-semver="1.2.14" src="https://code.angularjs.org/1.2.14/angular-route.js"></script>
<script src="app.js"></script>
<script src="EventController.js"></script>
<script src="github.js"></script>
</head>
<body>
<h1>Sao Vicente</h1>
<div ng-view></div>
</body>
</html>
github.js
(function(){
var github = function($http){
var getUser = function(){
return $http.get("http://localhost/course1/finalAndCorrect/json")
.then(function(response){
return response.data;
});
};
return{ //what i return will represent the public api
getUser: getUser
};
};
var module = angular.module("saoVicentinoApp");
module.factory("github", github);
}());
app.js:
(function(){
var app = angular.module("saoVicentinoApp", ["ngRoute"]);
app.config(function($routeProvider){ //do this configuration when bringing this module to life
$routeProvider
.when("/", {
templateUrl:"user.html",
controller:"EventController"
})
.otherwise({redirectTo:"/"});
});
}());
EventController.js:
(function(){
angular.module('saoVicentinoApp')
.controller('EventController', ['$scope', 'github', function($scope, github){
$scope.test = 4;
var onUserComplete = function(data){
$scope.event = data;
console.log($scope.event);
};
var onError = function(reason){
$scope.error = "Could not fetch the data.";
};
github.getUser()
.then(onUserComplete, onError);
}]);
}());
user.html
<!-- event Container -->
<div class="list-group">
<!-- event Container -->
<div class="list-group-item">
<h3>{{event.title}}
<em class="pull-right">{{event.startDate}} - {{event.endDate}}</em>
</h3>
<!-- Image Gallery -->
<div ng-show="event.imageUrl.length">
<!-- Fail 1 Message -->
<div ng-show="event.imageUrl">
<img class="img img-circle img-thumbnail center-block" ng-src="{{event.imageUrl[0]}}" />
<!-- <ul class="clearfix">
<li class="small-image pull-left thumbnail" ng-repeat="image in event.imageUrl"> <img ng-src="{{image}}" /> </li>
</ul>-->
</div>
</div>
<section>
<ul class="nav nav-pills">
<li><a href ng-click="tab = 1">Description</a></li>
<li><a href ng-click="tab = 2">Como posso contribuir?</a></li>
<li><a href ng-click="tab = 3">Calendario</a></li>
</ul>
<div class="panel" ng-show="tab === 1">
<h4>Description</h4>
<blockquote>{{event.description}}</blockquote>
</div>
<div class="panel" ng-show="tab === 2">
<h4>Como posso contribuir?</h4>
<div ng-repeat="donations in event.donateTypes">
<div>{{donations.name}}</div>
<div>{{donations.min}}</div>
<div>{{donations.total}}</div>
</div>
</div>
<div class="panel" ng-show="tab === 3">
<h4>Calendario</h4>
<blockquote>None yet</blockquote>
</div>
</section>
</div>
</div>
remove the promise from the factory. Since you are using promise(.then) from then controller no need to use it from the factory. Just return the http request
github.js
(function(){
var github = function($http){
var getUser = function(){
return $http.get("http://localhost/course1/finalAndCorrect/json")
};
return{ //what i return will represent the public api
getUser: getUser
};
};
var module = angular.module("saoVicentinoApp");
module.factory("github", github);
}());
You json is also invalid
[
{
"_id":52562,
"title":"Event name",
"startDate":"20-03-20",
"endDate":"20-03-20",
"description":"Lorem ipsun doloren he jlhdkh skjrlkuslinf sidhkjh this is a test",
"imageUrl":[
"https://images-na.ssl-images-amazon.com/images/G/01/img15/pet-products/small-tiles/23695_pets_vertical_store_dogs_small_tile_8._CB312176604_.jpg"
],
"donateTypes":[
{
"_id":1,
"name":"Fraldas",
"min":2,
"total":12
},
{
"_id":1,
"name":"Fraldas",
"min":2,
"total":12
},
{
"_id":1,
"name":"Fraldas",
"min":2,
"total":12
}
]
}
]
And data in http response comes under data property. So change this
var onUserComplete = function(data){
$scope.event = data.data[0];
console.log($scope.event);
};

What's the point of creating a directive in this angular.js example?

So I was following a tutorial on code academy on Angular.js. I understood every step and these are the final files which displays a simple game board. My question is: why did we need to go through the trouble of creating a directive called game and linking that to game.html for displaying the content? We already have the $scope given in the ScopeController file. Why couldn't we just go to the index.html file and just display using expressions with ng-repeat like this:
{{scope.visitor_score}}. So couldn't we have just done that all in the index.html file instead of making a directive?
index.html:
<!doctype html>
<html>
<head>
<link href='https://fonts.googleapis.com/css?family=Roboto:400,100,300' rel='stylesheet' type='text/css'>
<link href='https://fonts.googleapis.com/css?family=Oswald' rel='stylesheet' type='text/css'>
<link href="https://s3.amazonaws.com/codecademy-content/projects/bootstrap.min.css" rel="stylesheet">
<link href="css/main.css" rel="stylesheet">
<script src="js/vendor/angular.min.js"></script>
</head>
<body ng-app="GameboardApp">
<div class="header">
<h1 class="logo">GameBoard</h1>
</div>
<div class="main" ng-controller="ScoreController">
<div class="container">
<div class="row">
<game info="score" ng-repeat="score in scores"></game>
</div>
</div>
</div>
<!-- Modules -->
<script src="js/app.js"></script>
<!-- Controllers -->
<script src="js/controllers/ScoreController.js"></script>
<!-- Directives -->
<script src="js/directives/game.js"></script>
</body>
</html>
app.js:
var app = angular.module('GameboardApp',[]);
ScopeController.js
app.controller('ScoreController', ['$scope', function($scope) {
$scope.scores = [
{
datetime: 1420848000000,
visitor_team: {
city: "Charlotte",
name: "Hornets"
},
home_team: {
city: "New York",
name: "Knicks"
},
period: "Final",
visitor_score: 110,
home_score: 82
},
{
datetime: 1420848000000,
visitor_team: {
city: "Dallas",
name: "Mavericks"
},
home_team: {
city: "Los Angeles",
name: "Clippers"
},
period: "Final",
visitor_score: 100,
home_score: 120
},
{
datetime: 1420848000000,
visitor_team: {
city: "Brooklyn",
name: "Nets"
},
home_team: {
city: "Detroit",
name: "Pistons"
},
period: "Third Quarter",
visitor_score: 69,
home_score: 74
},
{
datetime: 1420848000000,
visitor_team: {
city: "Indiana",
name: "Pacers"
},
home_team: {
city: "Philadelphia",
name: "76ers"
},
period: "Third Quarter",
visitor_score: 70,
home_score: 72
},
{
datetime: 1420848000000,
visitor_team: {
city: "San Antonio",
name: "Spurs"
},
home_team: {
city: "Minnesota",
name: "Timberwolves"
},
period: "Halftime",
visitor_score: 58,
home_score: 43
},
{
datetime: 1420848000000,
visitor_team: {
city: "Orlando",
name: "Magic"
},
home_team: {
city: "Portland",
name: "Trail Blazers"
},
period: "First Quarter",
visitor_score: 13,
home_score: 26
}
]
}]);
game.html:
<div class="col-sm-4">
<div class="row scorecard">
<p class="period">{{ info.period }} </p>
<div class="visitor col-xs-4">
<h2 class="visitor-score">{{ info.visitor_score }} </h2>
<h3>
<span class="visitor-city">{{ info.visitor_team.city }} </span><br/>
<span class="visitor-name">{{ info.visitor_team.name }} </span>
</h3>
</div>
<div class="dash col-xs-3">
<h2>-</h2>
</div>
<div class="home col-xs-4">
<h2 class="home-score">{{ info.home_score }} </h2>
<h3>
<span class="home-city">{{ info.home_team.city }} </span><br/>
<span class="home-name">{{ info.home_team.name }} </span>
</h3>
</div>
</div>
</div>
game.js:
app.directive('game',function(){
return{
restrict: 'E',
scope: {
info: '='
},
templateUrl: 'js/directives/game.html'
}
}
);
Yes, you could. But you'd better not.
Clean code is simple and direct. Clean code reads like well-written
prose.
---- Grady Booch, author of Object-Oriented Analysis and Design with Applications
It's the matter of getting your code clean, beautiful and reusable.
Indeed, suppose you will need to show that repeated list on 10 differnt pages. Copypasting these 22 lines would be a very, very, very bad idea.
If you have it only in one place, well, you might want to leave it with ng-repeat, but it's likely you're going to reuse that, so you will have to refactor later anyway.
I think it might be useful for you to read some of Bob Martin's books or check out his videos, thay are awesome.
Cheers!

Get selected option from select with angular JS and ionic

I have some issues with select on angular Js, I searched a lot and found some solutions but not working.
I have a Json Structured like that generated from my service.php
[
{
"Name": "Name1",
"Variante": [
{
"Prix": "79.00",
"Name": "20 Piéces"
}
],
"Description": "",
"main_image": "images/products/DSC_0192.jpg"
},
{
"Name": "NAME2",
"Variante": [
{
"Prix": "39.00",
"Name": "250g"
},
{
"Prix": "60.00",
"Name": "500g"
}
],
"Description": "",
"main_image": "images/products/DSC_0125.jpg"
}
]
Here is my controller.js
.controller('productsCtrl', function($scope, $http, $stateParams) {
$http.get('service.php')
.success(function (response) {
$scope.products = response;
});
});
Here is my products.html
<ion-view view-title="Products">
<ion-content>
<ion-list>
<ion-item style="background-image: url({{product.main_image}})"
ng-repeat="product in products" class="productListItem">
<h2 class="h2Name">{{product.Name}}</h2>
<button class="button button-balanced button-right">
<i class="icon ion-ios-cart"></i>
</button>
<select class="Variantes"
ng-if="product.Variante.length > 1"
ng-model="selectedItem"
ng-options="variant.Name for variant in product.Variante">
</select>
<h2 class="Variantes" ng-if="product.Variante.length == 1">
{{product.Variante[0].Name}}
</h2>
<h2 class="h2Price" ng-if="product.Variante.length > 1">
{{selectedItem.Prix}}
</h2>
<h2 class="h2Price" ng-if="product.Variante.length == 1">
{{product.Variante[0].Prix}}
</h2>
</ion-item>
</ion-list>
</ion-content>
</ion-view>
If I have more than one VarianteI want to be able to change the price (Prix) value when I change the select box. But it doesn't work.
Any help needed !!
Thanks
The issue you have is due to the ng-if. It creates a separate scope, use ng-show instead cause it uses the same scope and your code should work perfectly.
Using ng-show would work but you could also use ng-if if you're taking care of the dot rule for ng-model.
If you would add your selectedItem to the product object your markup with ng-if will work as expected. Your ng-model for the select would be like ng-model="product.selectedItem".
Please have a look at the demo below or in this jsfiddle.
var jsonData = [
{
"Name": "Name1",
"Variante": [
{
"Prix": "79.00",
"Name": "20 Piéces"
}
],
"Description": "",
"main_image": "images/products/DSC_0192.jpg"
},
{
"Name": "NAME2",
"Variante": [
{
"Prix": "39.00",
"Name": "250g"
},
{
"Prix": "60.00",
"Name": "500g"
}
],
"Description": "",
"main_image": "images/products/DSC_0125.jpg"
}
];
angular.module('demoApp', ['ionic'])
.controller('productsCtrl', function($scope, $http, $stateParams) {
$scope.product = {
selectedItem: {}
};
//$http.get('service.php')
//.success(function (response) {
//http just removed for the demo
$scope.products = jsonData;//response;
//});
});
<script src="http://code.ionicframework.com/1.1.0/js/ionic.bundle.js"></script>
<link href="http://code.ionicframework.com/1.1.0/css/ionic.css" rel="stylesheet"/>
<ion-view ng-app="demoApp" ng-controller="productsCtrl" view-title="Products">
<ion-content>
<ion-list>
<ion-item style="background-image: url({{product.main_image}})"
ng-repeat="product in products" class="productListItem" ng-init="product.selectedItem = product.Variante[0]">
<h2 class="h2Name">{{product.Name}}</h2>
<button class="button button-balanced button-right">
<i class="icon ion-ios-cart"></i>
</button>
<select class="Variantes"
ng-if="product.Variante.length > 1"
ng-model="product.selectedItem"
ng-options="variant.Name for variant in product.Variante">
</select>
<h2 class="Variantes" ng-if="product.Variante.length == 1">
{{product.Variante[0].Name}}
</h2>
<h2 class="h2Price" ng-if="product.Variante.length > 1">
{{product.selectedItem.Prix | currency}}
</h2>
<h2 class="h2Price" ng-if="product.Variante.length == 1">
{{product.Variante[0].Prix | currency}}
</h2>
</ion-item>
</ion-list>
</ion-content>
</ion-view>

AngularJS & JSON - Obtain Value from Previous & Next Object

Background:
I have created an AngularJS test app which, obtains data from a JSON file, which is separated into categories and within each category is an employee card which is displayed through ng-repeat. These categories can then be viewed utilising a slider (using bxSlider).
Aim:
With bxSlider you can use custom Next/Previous buttons, what I wanted to achieve was to dynamically display the relevant category names in the Next/Previous buttons (please see annotation link below - my level does not allow me to post images).
Website Category Slider Wireframe
For example: the current category on view is the 'Technology' department, the previous button may then show 'Motors' department and the next button may show 'Law' department.
I understand that the code below would allow me to access the Category name 'Technology'. However this needs to be done in a dynamic nature.
{{employees[0].category}}
Below this I will include all what I believe to be relevant code.
JSON file:
[
{
"category": "Technology",
"shortname": "tech",
"icon": "fa-desktop",
"cards": [
{
"id": "card-1",
"name": "George Sofroniou",
"shortname": "G_Sof",
"age": "23",
"company": "Pirean Ltd.",
"role": "Graduate UI Developer"
},
{
"id": "card-2",
"name": "Steve Jobs",
"shortname": "S_Jobs",
"age": "56 (Died)",
"company": "Apple Inc.",
"role": "Former CEO"
},
{
"id": "card-3",
"name": "Mark Zuckerberg",
"shortname": "M_Zuck",
"age": "30",
"company": "Facebook",
"role": "CEO"
},
{
"id": "card-4",
"name": "Tim Cook",
"shortname": "T_Cook",
"age": "54",
"company": "Apple Inc.",
"role": "CEO"
},
{
"id": "card-5",
"name": "Jony Ive",
"shortname": "J_Ive",
"age": "48",
"company": "Apple Inc.",
"role": "Senior Vice President of Design"
},
{
"id": "card-6",
"name": "Marissa Mayer",
"shortname": "M_May",
"age": "39",
"company": "Yahoo!",
"role": "CEO"
},
{
"id": "card-7",
"name": "Yves Behar",
"shortname": "Y_Beh",
"age": "47",
"company": "Fuseproject",
"role": "Founder"
}
]
},
{
"category": "Motors",
"shortname": "mot",
"icon": "fa-car",
"cards": [
{
"name": "Elon Musk",
"shortname": "E_Musk",
"age": "43",
"company": "Tesla Motors",
"role": "CEO"
}
]
},
{
"category": "Football",
"shortname": "foot",
"icon": "fa-futbol-o",
"cards": [
{
"id": "card-1",
"name": "Sir Alex Ferguson",
"shortname": "A_Fer",
"age": "73",
"company": "N/A",
"role": "Retired"
}
]
},
{
"category": "Law",
"shortname": "law",
"icon": "fa-gavel",
"cards": [
{
"id": "card-1",
"name": "Harvey Specter",
"shortname": "H_Spec",
"age": "43",
"company": "Pearson Specter Litt",
"role": "Name Partner"
}
]
}
]
HTML Code:
<!-- Slider Container -->
<div class="slider-container">
<!-- Search Content -->
<!-- controls: true -->
<div class="content-results bxslider"
bx-slider="mode: 'horizontal', pager: true, nextSelector: '#next', prevSelector: '#prev', nextText: '<i class=\'fa fa-chevron-right\'></i>', prevText: '<i class=\'fa fa-chevron-left\'></i>', minSlides: 1, maxSlides:1, infiniteLoop: true, adaptiveHeight: true, hideControlOnEnd: false">
<!-- Employee -->
<div class="cards-container"
ng-repeat="item in filtered = ( employees | filter: query | orderBy:empOrder:direction )"
notify-repeat-finished>
<div class="category" ng-animate="'animate'" >
<div class="category-title">
<h1 class="title-cat"><i class="fa {{item.icon}}"></i> {{ item.category }}</h1>
</div>
<div class="category-cards-container">
<div class="employee-card card" ng-repeat="employee in filtered = (item.cards | filter: query | orderBy:empOrder:direction )" dom-manipulation>
<!-- Front Card -->
<div class="front">
<div class="pic-container">
<img ng-src="../static/images/placeholders/{{ employee.shortname }}.jpg" class="emp-pic" alt="Photo of {{ employee.name }}">
<h3 class="emp-name">{{ employee.name }}</h3>
<div class="darken"></div>
</div>
<ul class="emp-details">
<li class="detail emp-age">
<h5>Age: <small>{{ employee.age }}</small></h5>
</li>
<li class="detail emp-role">
<h5>Role: <br><small>{{ employee.role }}</small></h5>
</li>
<li class="detail emp-company">
<h5>Company: <br><small>{{ employee.company }}</small></h5>
</li>
</ul>
</div>
<!-- END Front Card -->
<!-- Back Card -->
<div class="back">
<div id="map-load">
<i class="fa fa-map-marker"></i>
</div>
<div id="maps-container">
<div id="googleMap"></div>
</div>
<i class="fa fa-times"></i>
</div>
<!-- END Back Card -->
</div>
</div>
</div>
<!-- No Matches -->
<div class="no-match" ng-show="filtered.length == 0">
<h3 class="no-matchText">Your search provides no matches!</h3>
</div>
<!-- END No Matches -->
</div>
<!-- END Employee -->
</div>
<!-- END Search Content -->
<!-- Next & Previous Buttons -->
<div class="btn-nextprev">
<div class="next-container">
<a href="" class="btn btn-next" id="next">
</a>
</div>
<div class="prev-container">
<a href="" class="btn btn-prev" id="prev">
</a>
</div>
</div>
<!-- END Next & Previous Buttons -->
</div>
<!-- END Slider Container -->
AngularJS:
Controller
var personControllers = angular.module('personControllers', ['ngAnimate']);
//PersonSearch Controller
personControllers.controller('PersonList', ['$scope', '$http',
function($scope, $http) {
$http.get('../static/scripts/data2.json').
success(function(data) {
console.log("JSON file loaded");
console.log(data);
$scope.employees = data;
//$scope.empOrder = 'name';
}).
error(function(){
console.log("JSON file NOT loaded");
});
}]);
EDIT
Updated Controller
var personControllers = angular.module('personControllers', ['ngAnimate']);
//PersonSearch Controller
personControllers.controller('PersonList', ['$scope', '$http',
function($scope, $http) {
$http.get('../static/scripts/data2.json').
success(function(data) {
console.log("JSON file loaded");
console.log(data);
$scope.employees = data;
//$scope.empOrder = 'name';
//Next & Previous Button Category Label
$scope.getNextCategoryIndex = function(currentIndex){
var nextIndex = currentIndex+1;
if( nextIndex >= $scope.employees.length ){
//move to start if at list end
nextIndex = 0;
}
return nextIndex;
}
$scope.getPrevCategoryIndex = function(currentIndex){
var prevIndex = currentIndex+1;
if( prevIndex < 0 ){
//move to the last index, if already at the start
prevIndex = $scope.employees.length - 1;
}
return prevIndex;
}
}).
error(function(){
console.log("JSON file NOT loaded");
});
}]);
Updated Next/Previous Buttons
<!-- Next & Previous Buttons -->
<div class="btn-nextprev">
<div class="next-container">
<a href="" class="btn btn-next" id="next">
{{ employees[getNextCategoryIndex($index)].category }}
</a>
</div>
<div class="prev-container">
<a href="" class="btn btn-prev" id="prev">
{{ employees[getPrevCategoryIndex($index)].category }}
</a>
</div>
</div>
<!-- END Next & Previous Buttons -->
I would probably do something like this: create functions to your controller to get the previous and next indexes (to handle the index overflows):
$scope.getNextCategoryIndex = function(currentIndex) {
var nextIndex = currentIndex+1;
if (nextIndex >= $scope.employees.length) {
// move over to start if we already were at the end of the list
nextIndex = 0;
}
return nextIndex;
}
$scope.getPrevCategoryIndex = function(currentIndex) {
var prevIndex = currentIndex+1;
if (prevIndex < 0) {
// move over to the last index, if we already are at the start
prevIndex = $scope.employees.length - 1;
}
return prevIndex;
}
And then in the HTML call those functions using $index (the current index of ng-repeat, see AngularJS documentation for ngRepeat for more details) as parameter:
<!-- Next & Previous Buttons -->
<div class="btn-nextprev">
<div class="next-container">
<a href="" class="btn btn-next" id="next">
{{employees[getNextCategoryIndex($index)].category}}
</a>
</div>
<div class="prev-container">
<a href="" class="btn btn-prev" id="prev">
{{employees[getPrevCategoryIndex($index)].category}}
</a>
</div>
</div>
<!-- END Next & Previous Buttons -->
The code you need should be:
{{employees[$index - 1].category}} //For the prev
{{employees[$index + 1].category}} //For the next
Recent Update (09-Apr-2015):
I have now been able to achieve what I wanted, on click of the button the relevant function runs and loops through the category names. One more thing to add now is that the buttons run in sync.
Controller
//Next & Previous Button Category Label
$scope.i = 0;
$scope.j = $scope.employees.length;
$scope.nextCat = $scope.i + 1;
$scope.prevCat = $scope.j - 1;
$scope.getNext = function(){
//console.log($scope.nextCat);
$scope.nextCat++;
if( $scope.nextCat >= $scope.employees.length ){
$scope.nextCat = 0;
}
$scope.prevCat++;
if( $scope.prevCat >= $scope.employees.length ){
$scope.prevCat = 0;
}
};
$scope.getPrev = function(){
//console.log($scope.nextCat);
$scope.prevCat--;
if( $scope.prevCat < 0 ){
$scope.prevCat = $scope.employees.length - 1;
}
$scope.nextCat--;
if( $scope.nextCat < 0 ){
$scope.nextCat = $scope.employees.length - 1;
}
};
HTML
<!-- Next & Previous Buttons -->
<div class="btn-nextprev">
<div class="next-container">
<a href="" class="btn btn-next" id="next"
ng-click="getNext()">
</a>
{{ employees[nextCat].category }}
</div>
<div class="prev-container">
<a href="" class="btn btn-prev" id="prev"
ng-click="getPrev()">
</a>
{{ employees[prevCat].category }}
<!-- {{ employees[prevCat].category }} -->
</div>
</div>
<!-- END Next & Previous Buttons -->
Update:
This is still not going to be a viable solution. I am technically able to achieve what is required however I am still required to use position: fixed. This means that the Category label then disappears.
I am now going to try and achieve this without it being within the ng-repeat and using ng-click it will iterate to the next Category name. Hopefully this will be the solution, and I will update upon any success/failure.
Update:
I am yet to find my optimal solution however, my current workaround for this utilises #jmustonen's solution.
Outside of the bxSlider I have the custom arrow's (if I placed these inside there were issues with the arrows not duplicating across pages - I believe there's an issue with it when it has position:fixed).
Then within my ng-repeat I include...
{{ employees[getNextCategoryIndex($index)].category }}
I will then be required to do some CSS in order for this to appear as if it is displayed as part of the Next/Previous buttons. Again these become invisible if position: fixed is used.

bootstrap collapse event hidden.bs.collapse not being detected

I have an angular application that uses bootstrap collapse element.
I've created a directive called accordion-list that host the collapsible elements.
Then, to listen to the events, i've used jquery event delegation.
For some reason, my application can't detect when the bootstrap fires the hidden.bs.collapse event.
Here is my code:
//app.js
'use strict';
(function () {
var provasNaoIdentificadas = angular.module("provasNaoIdentificadas", [
'restClient'
]);
provasNaoIdentificadas.controller("accordionCtrl", ["$scope", "ListaInscricao", function($scope, ListaInscricao){
$scope.inscricao = {
"Secretaria": ""
};
$("accordion-list").on("hidden.bs.collapse shown.bs.collapse", ".collapse", function (event) {
if ($(this).hasClass("in")) {
$(this).prev().find(".glyphicon").removeClass("glyphicon-plus glyphicon-minus").addClass("glyphicon-minus");
$(this).prev().find("span.pull-right.text-muted").removeClass("expandir fechar").addClass("fechar");
} else {
$(this).prev().find(".glyphicon").removeClass("glyphicon-plus glyphicon-minus").addClass("glyphicon-plus");
$(this).prev().find("span.pull-right.text-muted").removeClass("expandir fechar").addClass("expandir");
}
console.log(1, this, event); // i have detected the problem by interpreting
});
ListaInscricao.get({"id": 1}, function(data){
if (data.Sucesso) {
$scope.inscricao = data.Dados;
} else {
// toastr
}
});
}]);
provasNaoIdentificadas.directive('accordionList', function() {
return {
"restrict": "E",
"templateUrl": "partials/accordion.html"
};
});
})();
Help you guys can help me. Thanks in advance. :)
EDIT
Here's my files:
index.html:
<!-- index.html -->
<!DOCTYPE html>
<html ng-app="provasNaoIdentificadas">
<head>
<title>Hábile: Inscrição De Escolas Públicas Para Provas Não Identificadas</title>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" />
<link rel="stylesheet" href="css/vendor/bootstrap.min.css" />
<script src="js/vendor/jquery-1.11.1.min.js"></script>
<script src="js/vendor/bootstrap.min.js"></script>
<script src="js/vendor/angular.min.js"></script>
<script src="js/vendor/angular-resource.min.js"></script>
<script src="js/app.js"></script>
<script src="js/rest-client.js"></script>
<style>
.panel-heading {
cursor: pointer;
}
.panel-heading .panel-title span.pull-right.text-muted {
font-size: 10px;
}
.panel-heading .panel-title span.pull-right.text-muted.expandir:before {
content: "clique para expandir";
}
.panel-heading .panel-title span.pull-right.text-muted.fechar:before {
content: "clique para fechar";
}
</style>
</head>
<body>
<div class="container">
<div class="well text-justify">
<h3>Formulário de Inscrição Hábile 2014</h3>
</div>
<div ng-controller="accordionCtrl">
<h2 id="nomeSecretaria">{{ inscricao.Secretaria }}</h2>
<accordion-list></accordion-list>
</div>
<div class="text-center">
<button type="button" class="btn btn-lg btn-primary">Salvar Inscrição</button>
<button type="button" class="btn btn-lg btn-warning">Finalizar Inscrição</button>
</div>
</div>
</body>
</html>
partials/accordion.html
<!-- partials/accordion.html -->
<div class="panel-group" id="accordion_escolas">
<div class="panel panel-default" ng-repeat="escola in inscricao.Escolas">
<div class="panel-heading" data-toggle="collapse" data-target="#escola{{ $index }}" data-parent="#accordion_escolas">
<div class="panel-title">
<span class="glyphicon glyphicon-plus"></span>
{{ escola.Nome }} <span class="text-muted">x alunos inscritos</span>
<span class="pull-right text-muted expandir"></span>
</div>
</div>
<div id="escola{{ $index }}" class="panel-collapse collapse">
<div class="panel-body">
<p>
<label for="qtdProfessoresEscola{{ $index }}">Qtd. Professores</label><br />
<input class="form-control" type="text" id="qtdProfessoresEscola{{ $index }}}}" value="{{ escola.QtdProfessores }}" />
</p>
<div class="panel-group" id="accordion_escola{{ $index }}">
<div class="panel panel-default" ng-repeat="serie in escola.Series">
<div class="panel-heading" data-toggle="collapse" data-target="#turma_{{ $index }}_escola{{ $parent.$index }}" data-parent="#accordion_escola{{ $parent.$index }}">
<div class="panel-title">
<span class="glyphicon glyphicon-plus"></span>
{{ serie.Nome }} <span class="text-muted">y alunos inscritos</span>
<span class="pull-right text-muted expandir"></span>
</div>
</div>
<div id="turma_{{ $index }}_escola{{ $parent.$index }}" class="panel-collapse collapse">
<div class="panel-body">
<table class="table table-hover table-condensed table-bordered">
<thead>
<tr>
<th>Turma</th>
<th>Qtd Alunos</th>
<th>Qtd Testes A3</th>
<th>Alunos PCD</th>
<th></th>
</tr>
</thead>
<tbody>
<tr ng-repeat="turma in serie.Turmas">
<td>{{ turma.Nome }}</td>
<td><input class="form-control" type="text" value="{{ turma.QtdAlunos }}" /></td>
<td><input class="form-control" type="text" value="{{ turma.QtdTestesA3 }}" /></td>
<td><input class="form-control" type="text" value="{{ turma.AlunosPCD }}" /></td>
<td><button class="btn btn-primary btn-sm" type="button">Excluir Turma</button></td>
</tr>
</tbody>
</table>
<p>
<button class="btn btn-primary" type="button">Adicionar Turma</button>
</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
js/app.js:
/* js/app.js */
'use strict';
(function () {
var provasNaoIdentificadas = angular.module("provasNaoIdentificadas", [
'restClient'
]);
provasNaoIdentificadas.controller("accordionCtrl", ["$scope", "ListaInscricao", function($scope, ListaInscricao){
$scope.inscricao = {
"Secretaria": ""
};
$("accordion-list").on("hidden.bs.collapse shown.bs.collapse", ".collapse", function (event) {
if ($(this).hasClass("in")) {
$(this).prev().find(".glyphicon").removeClass("glyphicon-plus glyphicon-minus").addClass("glyphicon-minus");
$(this).prev().find("span.pull-right.text-muted").removeClass("expandir fechar").addClass("fechar");
} else {
$(this).prev().find(".glyphicon").removeClass("glyphicon-plus glyphicon-minus").addClass("glyphicon-plus");
$(this).prev().find("span.pull-right.text-muted").removeClass("expandir fechar").addClass("expandir");
}
console.log(1, this, event);
});
ListaInscricao.get({"id": 1}, function(data){
if (data.Sucesso) {
$scope.inscricao = data.Dados;
} else {
// toastr
}
});
}]);
provasNaoIdentificadas.directive('accordionList', function() {
return {
"restrict": "E",
"templateUrl": "partials/accordion.html"
};
});
})();
js/rest-client.js:
/* js/rest-client.js */
'use strict';
(function(){
var restClient = angular.module('restClient', ['ngResource']);
restClient.factory('ListaInscricao', ['$resource', function ($resource) {
return $resource('mock/lista_inscricao.json');
}]);
})();
mock/lista_inscricao.json:
{
"Sucesso": true
,
"Mensagem": ""
,
"Dados": {
"Secretaria": "Secretaria de Educação ABC"
,
"Escolas": [
{
"Nome": "Escola 1"
,
"QtdProfessores": 12
,
"Series": [
{
"Nome": "1º Ano Ensino Médio"
,
"Turmas": [
{
"Nome": "A"
,
"QtdAlunos": 30
,
"QtdTestesA3": 0
,
"AlunosPCD": "27,29"
}
, {
"Nome": "B"
,
"QtdAlunos": 28
,
"QtdTestesA3": 2
,
"AlunosPCD": ""
}
]
}
,
{
"Nome": "2º Ano Ensino Médio"
,
"Turmas": [
{
"Nome": "A"
,
"QtdAlunos": 25
,
"QtdTestesA3": 1
,
"AlunosPCD": "7"
}
]
}
]
}
,
{
"Nome": "Escola 2"
,
"QtdProfessores": 10
,
"Series": [
{
"Nome": "3º Ano Ensino Médio"
,
"Turmas": [
{
"Nome": "A"
,
"QtdAlunos": 30
,
"QtdTestesA3": 0
,
"AlunosPCD": "15,27"
}
, {
"Nome": "B"
,
"QtdAlunos": 26
,
"QtdTestesA3": 0
,
"AlunosPCD": ""
}
, {
"Nome": "C"
,
"QtdAlunos": 25
,
"QtdTestesA3": 0
,
"AlunosPCD": ""
}
]
}
]
}
]
}
}
for now, I've just changed my event listener. For some reason, jquery can't hear the hidden.bs.collapse. I've noticed that the click event is not suitable for this case, because if you click fast enough, you can end with a closed accordion and a minus icon on it. So, I've changed the event listener to:
$(document).on("hide.bs.collapse show.bs.collapse", ".collapse", function (event) {
$(this).prev().find(".glyphicon").toggleClass("glyphicon-plus glyphicon-minus");
$(this).prev().find("span.pull-right.text-muted").toggleClass("expandir fechar");
event.stopPropagation();
});
This is working pretty well. But, as bhantol said, it not quite the angularjs way of doing things. The one with a better solution win the prize xD
We don't use jquery code in Controllers.
Controllers are not the right place for DOM manipulation.
Directives are what you need for DOM manipulation.
Also in AngularJS we generally don't use jQuery eventing programming style.
Here is approximate plunker of your orignial code. If I understand correctly you re trying to toggle the state of glyphicon state + and - using the code below:-
$("accordion-list").on("hidden.bs.collapse shown.bs.collapse", ".collapse", function (event) {
if ($(this).hasClass("in")) {
(this).prev().find(".glyphicon").removeClass("glyphicon-plus glyphicon-minus").addClass("glyphicon-minus");
$(this).prev().find("span.pull-right.text-muted").removeClass("expandir fechar").addClass("fechar");
} else {
$(this).prev().find(".glyphicon").removeClass("glyphicon-plus glyphicon-minus").addClass("glyphicon-plus");
$(this).prev().find("span.pull-right.text-muted").removeClass("expandir fechar").addClass("expandir");
}
console.log(1, this, event); // i have detected the problem by interpreting
});
Click here for the solution plunker.
The solution is all in accordion.html notice ng-model however I hace commented out your jquery code in the controller.
ng-model="collapseState"
this is to hold the state.
then further notice
<span class="glyphicon"
ng-class="collapseState[$index] ? 'glyphicon-minus' : 'glyphicon-plus'">
</span>
here we choose the class based on the value of collapseState[$index].
Also notice ng-click which basically toggles the value of collapseState[$index]
ng-click="collapseState[$index]= !collapseState[$index]"
So far what we have done is used a model and altered the view by manipulating the model.
This is the gist of AngularJS way.

Categories

Resources