ng-class expression not working with parameter coming from httpresponse - angularjs

I have a servlet that returns a JSON object with a parameter named "valoracion" and I want to use it for a span label to be a css class with the name of the value associated to that parameter. This I want to do it to show a .gif in a different way depending on this class. I'm using AngularJS, btw.
This is the js code from the "novedades" page controller:
angular.module('myApp')
.controller('novedadesCtrl', [ '$scope','auth', 'novedadesService', function($scope,auth,novedadesService){
$scope.mostrar = ["Comentarios","Valoraciones"];
$scope.novedades = "Comentarios";
$scope.novedadesComentarios;
$scope.novedadesValoraciones;
$scope.cogerNovedades = function(){
debugger;
novedadesService.novedades( auth.idUser(), function(comentarios,valoraciones) {
$scope.novedadesComentarios = comentarios;
console.log(valoraciones);
$scope.novedadesValoraciones = valoraciones;
});
};
$scope.cogerNovedades();
}]);
novedadesService.novedades is a factory that sends a POST request to the servlet and returns the same JSON returned by the servlet. This is an example of the aforementioned JSON:
idJuego: 0
idUsuario: 500
juego: "Star Wars: The Old Republic"
nombreApellidos: "Gregorio de Miguel"
nombreUsuario: "Goyo"
valoracion: "cuatroEstrella"
This other one is the html code for that page:
<div class="container" id="cuerpo">
<h1 class="theme-color-text font">Novedades</h1>
<div class="row form-inline">
<div class="form-group" style="float: right;">
<label for="mostrar">Mostrar: </label>
<select id="mostrar" class="form-control" ng-model="novedades"
ng-options="x for x in mostrar">
</select>
</div>
</div>
<!-- lista de novedades de comentarios -->
<div ng-if="novedades == 'Comentarios'" class="row">
<ul class="list-group" id="novedades">
<li class="list-group-item" ng-repeat="comentario in novedadesComentarios">
{{comentario.nombreUsuario}}
({{comentario.nombreApellidos}}) ha comentado el juego
{{comentario.juego}}</li>
</ul>
</div>
<!-- lista de novedades de valoraciones -->
<div ng-if="novedades == 'Valoraciones'" class="row">
<ul class="list-group" id="novedades">
<li class="list-group-item" ng-repeat="valoracion in novedadesComentarios">
{{valoracion.nombreUsuario}}
({{valoracion.nombreApellidos}}) ha valorado el juego
{{valoracion.juego}}
con <span ng-class="{{valoracion.valoracion}}"></span></li>
</ul>
</div>
This is the part where I have the problem:
<span ng-class="{{valoracion.valoracion}}"></span>
The following is an example from the css we want the page to show:
.cuatroEstrella{
display: inline-block;
margin-bottom: -10px;
width: 100px;
height: 30px;
background: url("../img/valoracion.gif") 0 -262px;
}
Here you have a screenshot from the page. You can see the problem in the developers console.
I appreciate any help you can provide on this issue.

Don't need to use the {{}}, just like this :
<span ng-class="valoracion.valoracion"></span>

Bad copy/paste ;). You are iterating through 'novedadesComentarios' instead through 'novedadesValoraciones'. You are doing this:
<li class="list-group-item" ng-repeat="valoracion in novedadesComentarios">
{{valoracion.nombreUsuario}}
({{valoracion.nombreApellidos}}) ha valorado el juego
{{valoracion.juego}}
con <span ng-class="{{valoracion.valoracion}}"></span>
</li>
And I think you want to do this:
<li class="list-group-item" ng-repeat="valoracion in novedadesValoraciones">
{{valoracion.nombreUsuario}}
({{valoracion.nombreApellidos}}) ha valorado el juego
{{valoracion.juego}}
con <span ng-class="valoracion.valoracion"></span>
</li>
Update
I had forgotten to say that you still have to do what #Mike Vranckx said and remove the {{}}

Related

Nested ng-repeat performance issue in IE

Am using nested ng-repeat to display below JSON ( given sample format actual format is different and have lot of properties ). When list size is 100 then in IE it takes more than 25 seconds to render.
I tried using "track by" & "oen way binding" but no luck.
Data
{name: "name1", placeVisited: [{city: 'city1', state: "state1"}]}
HTML
<div ng-repeat="item in items track by item.name" class="col-md-4 col-sm-6" style="float: none; display:inline-block; vertical-align: top; cursor: pointer" >
<a class="tile" id="tile{{$index}}" >
<div class="tile-head">
<div class="tile-ont-img"><img src="user.png" class="img-responsive" > </div>
<h4>{{::item.name}}</h4>
</div>
<div class="tile-body" >
<p ng-repeat="place in ::item.placeVisited track by port.state" >
State {{::place.state}}
</p>
</div>
</a>
</div>
Please share your idea to improve nested ng-repeat performance in IE.

In what scope is ng-repeat "as alias" available

I'm using angular 1.4.8. I want to save filtered result from ng-repeat and use it to determine whether to enable a "load more" button at the bottom of the list. I have looked at this question:
AngularJS - how to get an ngRepeat filtered result reference
And many others, they suggest to use "as alias" from ng-repeat, here's what my code looks like:
<ul class="media-list tab-pane fade in active">
<li class="media">
<div ng-repeat-start="item in items | limitTo: totalDisplayed as filteredResult">
{{item}}
</div>
<div class="panel panel-default" ng-repeat-end>
</div>
<div>
{{filteredResult.length}}
</div>
</li>
</ul>
<button ng-click="loadMore()" ng-show="totalDisplayed <= filteredResult.length">
more
</button>
However, I found filteredResult.length is displayed fine right after ng-repeat, but the button is never shown. If I try to display filteredResult.length in where the button is, it will show null.
So is there a rule for "as alias" scope? I've seen plenty of examples work but mine doesn't, what am I missing here?
EDIT:
The accepted answer uses controllerAs which indeed will resolve the problem. However, charlietfl's comment using ng-init to save filteredResult to parent scope is also very neat and that's the solution I use in my code eventually.
Probably some of classes in your <ul class="media-list tab-pane fade in active"> or <li class="media"> is selector for a directive that would have its own scope. So you store filteredResult in e.g. tab-pane's scope and then try to have access out of it's scope in outside of ul tag.
Try to use Controller as instead of scope:
angular
.module('plunker', [])
.controller('MainCtrl', function() {
vm = this;
// make an array from 1 to 10
var arr = [];
while (arr.length < 10) {
arr.push(arr.length + 1)
};
vm.items = arr;
vm.totalDisplayed = 5;
vm.filteredResult = [];
});
<body ng-controller="MainCtrl as main">
{{main.items}}
<ul class="media-list tab-pane fade in active">
<li class="media">
<div ng-repeat-start="item in main.items | limitTo: main.totalDisplayed as filteredResult">
{{item}}
</div>
<div class="panel panel-default" ng-repeat-end>
</div>
<div>
filteredResult = {{main.filteredResult = filteredResult}}
</div>
</li>
</ul>
<button ng-click="loadMore()" ng-show="main.totalDisplayed <= main.filteredResult.length">
more
</button>
</body>
http://plnkr.co/edit/drA1gQ1qj0U9VCN4IIPP?p=preview

Get id of parent element of currently clicked element in AngularJS

How do I get the id of a parent element of currently clicked element in AngularJS?
<div id="d8" class="menutitles ng-scope" ng-repeat="title in list">
<div class="right" ng-click="showsubmenu($event)">+</div>
<div class="left" ng-click="showsubmenu($event)">Unit 9</div>
</div>
How to get the value d8 in showsubmenu($event) function?
Below is what I tried but it doesn't work
$scope.showsubmenu=function(obj)
{
alert(obj.target.parent.attributes.id)
}
It should be parentNode, not just parent:
alert(obj.target.parentNode.id);
Also attributes is redundant as you can access id property directly.
But note, that since you have ngRepeat, it will create invalid markup, since ids are going to be duplicated. You probably want to fix this too, maybe like this or use classes:
<div id="d8{{$index}}" class="menutitles ng-scope" ng-repeat="title in list">
<div class="right" ng-click="showsubmenu()">+</div>
<div class="left" ng-click="showsubmenu()">Unit 9</div>
</div>
<div id="d8" class="menutitles ng-scope" ng-repeat="title in list">
<div class="right" ng-click="showsubmenu()">+</div>
<div class="left" ng-click="showsubmenu()">Unit 9</div>
</div>
It should be enough :D
function showsubmenu($event){
$($event.target).parent();
}
Have a nice day
As an addition to Pedro's answer I'd say that using the jQuery method closest would be preferable.
function showsubmenu($event){
var parent = $($event.target).closest('.yourclass'); // or any selector you prefer
}

Recover value of field in ng-repeat

Sorry for the english, i'm french student :(
I would like create a comment system with AngularJS for a project.
I would like recover a value of an object who is in ng-repeat loop.
JSON : https://drive.google.com/file/d/0Bzj557dnogzOd0ZUMnZ1cWZLSFU/edit?usp=sharing
HTML :
<section ng-controller='AnnouncesCtrl' ng-show='!showActions' ng-swipe-left='showActions=true'>
<header class='header'>
<span class="return"><a href='#newAnnounce'>8</span>
</header>
<div class='loader' ng-show='loader'></div>
<section class='panel'>
<div ng-repeat='a in dept.announce' class='announces'>
<span class='title'>{{a.name}}</span>
<br/>
<span class="date">{{a.date}}</span>
<hr>
<span class="msg">{{a.desc}}</span>
<hr>
<div class="showrep" ng-click="show=true" ng-show='!show'>Montrer les réponses</div>
<div class="allrep" ng-show="show" ng-repeat='answer in a.answers'>{{answer}}<br/></div>
<div class="formrep">
<form ng-submit='addComments()'>
<input type='text' placeholder='Écrire une réponse'><input type='submit' ng-click='a.btn={{a.id}}' value='Répondre'>
</form>
</div>
</div>
</section>
JS :
function AnnouncesCtrl($scope,$http,$rootScope,$location){
$scope.getInfos=function(){
var dept="http://agence-pandor.fr/getAnnounces/index.php";
$scope.loader=true;
$http.get(dept)
.success(deptSuccess)
.error(function(){
$scope.loader=false;
alert('Impossible de récupérer le numéro étudiant. Veuillez vous reconnecter');
$location.url("/connexion"); // On redirige
})
}
deptSuccess=function(response){
$scope.loader=false;
$scope.dept=response;
}
$scope.getInfos();
$scope.addComments=function(){
alert($scope.dept.announce.btn);
}
}
Screenshot :
https://drive.google.com/file/d/0Bzj557dnogzOUDlfNWR3eEthQzA/edit?usp=sharing
I don't quite understand what your project is about (I don't know French). You are iterating over the array "announce" which is supposedly a property of "dept". When you type:
ng-repeat = 'a in dept.announce'
you are creating a temporary variable "a" in the scope that is meant for ng-repeat (like counter variable in a for loop).
If "btn" is supposed to be a unique value, then use:
ng-click = "btn = a.id"
or if "btn" is specific to each value of "a in announce", use:
ng-click = "btn[$index] = a.id";
You can get the value of btn in your JS file by using $scope.btn

Can I use the ng-if on a ng-repeater?

I'm new to angular and was wondering how to tackle the following situation. I'm using angular with jquery mobile and am creating a one page app. When the app loads, I have it create pages or divs inside the body tag. I have two types of pages, "typical pages" and "video pages" but I want to use one object to create both page types. I want to use one object because I also use that object to create my menu and I don't want to have to edit multiple objects.
My issue is, I want to create a "typical page" for each element in the object but I only want to create a "video page" for each object that doesn't have "videoPage: false". I tried using ng-if on the "video page" ng-repeater (see html below) but it doesn't seem to be working. Can I use the ng-if on a ng-repeater?
I have the following data/object:
function App($scope){
$scope.pages = [
{
id: "intro",
title: "Intro",
videoPage: false
},{
id: "activeStretches",
title: "Active Stretches by Area"
},{
id: "passiveStretches",
title: "Passive Stretches by Area"
}
];
}
And the html:
<body ng-app ng-controller="App">
<div data-role="page" id="{{page.id}}" ng-repeat="page in pages">
<div data-role="header" data-theme="h">
<a data-rel="back" data-icon="arrow-l">Back</a>
<h1>{{page.title}}</h1>
</div>
<div data-role="content">
<div class="content-side">
<ul data-role="listview" data-inset="true">
<li ng-repeat="menu in pages" data-theme="{{menu.title == page.title && 'h'}}">
{{menu.title}}
</li>
</ul>
<div class="logo"></div>
</div>
<div class="content-main">
Typical Page
</div>
</div>
</div>
<div data-role="page" id="{{page.id}}Video" ng-repeat="page in pages" ng-if="page.videoPage">
<div data-role="header" data-theme="h">
<a data-rel="back" data-icon="arrow-l">Back</a>
<h1 class="vidTitle"></h1>
</div>
<div data-role="content">
<div class="content-side">
<ul data-role="listview" data-inset="true">
<li ng-repeat="menu in pages" data-theme="{{menu.title == page.title && 'h'}}">
{{menu.title}}
</li>
</ul>
<div class="logo"></div>
</div>
<div class="content-main">
Video Page
</div>
</div>
</div>
</body>
ng-if is new as of 1.1.15 so make sure you're using a new (currently unstable) version of Angular.
And, yes, you can mix ng-if with ng-repeat. Here's a fiddle showing it in action (using 1.2): http://jsfiddle.net/rbQry/1/
Note this line (switch the ng-if to "true" and the repeat comes back):
<li ng-repeat="phone in phones | filter:query" ng-if="false">

Resources