Issue With name containing - in angular service - angularjs

I have a service like below
var places = [
{ "city" : "Bangalore","country-name": "India"},
{ "city" : "Mysore","country-name": "India"}
];
this.getCities = function(){
return places;
};
I am calling the getCities in my controller and displaying the data in my html like below.
<li ng-repeat="place in places">
<label>City : {{place.city}}</label>
<label>Country : {{place.country-name}}</label>
</li>
But the country name is coming as 0 and the city is working fine.
Please find the plunker here
Please let me know why it is happening

Rename country-name to countryName. You can't have dashes in your property names and then access them with the dot operator.
If for some reason you're consuming an api that you don't control, you can do this instead:
<label>Country : {{place['country-name']}}</label>

Related

Use angular translate with parameters and HTML

I have a translation label with parameters and html :
{
"myLabel": "There is <b>{{param}}</b> value."
}
I don't arrive to pass my parameter and to get the HTML interpreted. I try many option :
Option 1 : Use ng-bind-html with translate filter
<p ng-bind-html="{{'myLabel' | translate:{param: vm.myParam} }}"></p>
But I get this error :
angular.js:14642 Error: [$parse:syntax] http://errors.angularjs.org/1.6.5/$parse/syntax?p0=%7B&p1=invalid%20key&p2=2&p3=%7B%7B'general.help.notion.text3'%20%7C%20translate%3A%7BnbButton%3A%20vm.nbBtn%7D%20%7D%7D&p4=%7B'general.help.notion.text3'%20%7C%20translate%3A%7BnbButton%3A%20vm.nbBtn%7D%20%7D%7D
at angular.js:88
at r.throwError (angular.js:15200)
at r.object (angular.js:15189)
at r.primary (angular.js:15078)
at r.unary (angular.js:15066)
at r.multiplicative (angular.js:15053)
at r.additive (angular.js:15044)
at relational (angular.js:15035)
at r.equality (angular.js:15026)
at r.logicalAND (angular.js:15018) "<b ng-bind-html="{{'general.help.notion.text3' | translate:{nbButton: vm.nbBtn} }}">"
Is there a way to use ng-bind-html with a parameter ?
Option 2 : Use translate directive
<p translate="myLabel" translate-values="{'param': vm.myParam}"> </p>
But what I get is for example : There is <b>2</b> value.
My current sanitize strategy for angular translate is escaped, I tried with sanitize but in french all my accent are converted into their html code, for example : Déroulement d'un chapitre
I also try the escapeParameters and sanitizeParameters strategies and always I get : There is <b>2</b> value.
Do you know how I can achieve that ?
Thanks in advance
Takeshi
Try something like this:
<p ng-bind-html="'myLabel' | translate"></p>
Remember to include $sce service.
You could use the $translate service in order to get the string translated in the controller (providing the param as parameter), then set the translated value to a var and bind (ng-bind-html) this var in the view.
Something like this (I did not use the controllerAs syntax for brevity):
controller js
$scope.message = "About to be translated..."
$translate('myLabel', {param: 1}).then(function (text) {
$scope.message = $sce.trustAsHtml(text);
}, function (textID) {
$scope.message = $sce.trustAsHtml(text);
});
view
<p ng-bind-html="message"></p>
Working Plunker
Remember to inject the $sce service.

How to select all fields including id and name value in select box using Angular JS

I have the select box.
<select ng-model="sub_class_name" class="form-control">
<option ng-repeat="x in myData" value="{{x}}">{{x.sub_class_name}}</option>
</select>
Am passing value to a controller like this :
$scope.alertdata = function() {
var parameter = {
"first_name": $scope.first_name,
"middle_name": $scope.middle_name,
"subclass": [$scope.sub_class_name]
}
}
After printing the parameter
alert(JSON.stringify(parameter));
Am getting stringified JSON output i.e.,
{"first_name":"Prashanth","middle_name":"H","last_name":"Rotti",
"subclass":["{\"sub_class_id\":3,\"sub_class_name\":\"Dependent \"}"]}
I dont want slashes ["{\"sub_class_id\":3,\"sub_class_name\":\"Dependent \"}"]
I want JSON output like this.
{"first_name":"Prashanth","middle_name":"H","last_name":"Rotti",
"subclass":[{"sub_class_id":"3","sub_class_name":"Dependent"}] }
Adding my comment as answer, as it is not possible to format data properly in comment:
**Update **
Since datatype expected is string in JSON format, so you can initialize like this
$scope.sub_class_name = "{}" // Or $scope.sub_class_name ="[]"; based on data type it may be
$scope.alertdata = function() {
var parameter = {
"first_name": $scope.first_name,
"middle_name": $scope.middle_name,
"subclass": [JSON.parse($scope.sub_class_name)]
}
}
alert(JSON.stringify(parameter));
Let me know if you face any issue with this.
Use JSON.parse()
It will do the trick.

Reading child of an automated unique ID in a nested ng-repeat

How do I get data of a child of an automated unique ID in a nested ng-repeat, if the ID is not in the first level?
My firebase data set is structured as such (note: I do not know the amount or values of users, dates or unique IDs in that data set):
John:[
10-12-2015: {
"-JcFXid1A2G8EM7A_kwc": {
"description" : "hi",
"timestamp": "1449751857810"},
"-JcFZP5FNtL4Yj6nja_7": {
"description" : "this",
"timestamp": "144975185345"},
},
11-12-2015: {
"-JcFtGoZL7J-CCIjTYcL": {
"description" : "is",
"timestamp": "14497518513715"},
"-JcFXid1A2G8EM7A_kwc": {
"description" : "me",
"timestamp": "1449751846956"},
},
]
Thomas: [ ... ]
My HTML code is:
<ion-list>
<ul class="list">
<li ng-repeat="day in list">
<ion-item class="item-divider">{{day.$id}}</ion-item>
// That works as my output is "10-12-2015, etc"
<li ng-repeat="key in day">
// This does not work
<ion-item>{{key.description}}</ion-item>
</li>
</li>
</ul>
</ion-list>
I am new to Firebase and Angular so my apologies if I am missing something obvious. I also understand that Firebase recommends flat hierarchies, but sorting it by user and date is important for data analysis I need to do. But I would be open to suggestions.
FYI - My controller looks like this:
.controller('summaryCtrl', ['$scope','$state','$firebase','$firebaseArray','SessionData', '$ionicPopup', function($scope,$state,$firebase,$firebaseArray,SessionData,$ionicPopup){
var firebaseObj = new Firebase("https://id.firebaseio.com/" + userid);
var fbArray = $firebaseArray(firebaseObj);
fbArray.$loaded()
.then(function(){
$scope.list = fbArray;
})
}])
Thanks.
You don't need to use .$loaded(), the $firebaseArray will take care of triggering $digest when the data is loaded. The .$loaded() promise is useful for resolving in routes.
In your case though you need to go down into the day key to create the array. Try a data structure like below:
{
"userMessages": {
"$uid": {
"$message_id": {
"timestamp": 1450048003760 // use a timestamp
}
}
}
}
This way you can get messages per user by: /userMessages/$uid/. Then using a query you can get them by date.
You can create factory to simplify this.
Don't mind the code structure below, it uses the Angular Styleguide.
angular.module('app', ['firebase'])
.constant('FirebaseUrl', '<my-firebase-app>')
.service('rootRef', ['FirebaseUrl', Firebase])
.factory('messages', Messages)
.controller('SummaryCtrl', SummaryCtrl);
function Messages(rootRef, $firebaseArray) {
return function Messages(userid, date) {
// turn the date into a timestamp
var timestamp = date.getTime();
var messagesRef = rootRef.child('userMessages').child(userid);
// query for messages on that day
var query = messagesRef.orderByChild('timestamp').endAt(timestamp);
return $firebaseArray(query);
};
}
function SummaryCtrl($scope, messages, rootRef) {
var user = rootRef.getUser()
var today = new Date();
$scope.messages = messages(user.uid, today);
}

angularjs angular doesn't read the length of an array

for the passed few days I am struggling with the matter of AngularJS. I am novice at this and that's where my troubles result from.
Anyway here is my problem. I have an app that is made made for asking users some questions, collecting answers and displaying them to the user.
The HTML is:
<div ng-repeat="dialog in dialogWindows">
<div id="{{dialog.idName}}" class="bold abs">
<div class="questionContainer rel">
<button ng-click="compute()>Fake results</button>
<div ng-repeat="input in dialog.inputs">
<input type="radio" id="{{input.radio}}" name="{{dialog.name}}" value="{{input.value}}">
<label for="{{input.radio}}" class="answer abs {{input.a}}">{{input.answer}}</label>
</div>
</div>
</div>
</div><!--/ng-repeat-->
</div><!--/ng-controller-->
And here is the JS managing the ng-repeat above:
function dialogWindows($scope,localStorageService){
$scope.dialogWindows = [
{id:0,
idName:"pigmentation",
number:"1",
name:"Pigmentation",
answer1:"Clear complexion",
answer2:"Semi-swarthy complexion",
answer3:"Swarthy complexion",
answer4:"",
answer5:"",
answer6:"",
href:"#hairColor",
hrefBack:"index.html",
inputs:[{id:0,a:"a1",answer:"Clear compexion", radio:"radio1",value:"1"},
{id:1,a:"a3", answer:"Semi-swarthy complexion", radio: "radio2",value:"1"},
{id:2,a:"a5",answer:"Swarthy complexion",radio:"radio3",value:"1"}
]
Nothing really complicated and so far it works fine. Now you can see that ng-repeat generates three radio buttons. and we have compute function assigned to the button soon you'll see what it does.
Here is the compute() function:
$scope.compute = function() {
if (document.getElementById('radio1').checked) {
$scope.a.push(1);
$scope.b.push(1);
$scope.c.push(1);
$scope.d.push(1);
$scope.e.push(1);
$scope.f.push(1);
$scope.g.push(1);
$scope.h.push(1);
$scope.i.push(1);
$scope.j.push(1);
$scope.k.push(1);
$scope.l.push(1);
$scope.m.push(1);
$scope.n.push(1);
$scope.o.push(1);
$scope.p.push(1);
} else if (document.getElementById('radio2').checked) {
$scope.r.push(1);
$scope.s.push(1);
$scope.t.push(1);
$scope.u.push(1);
$scope.w.push(1);
} else if(document.getElementById("radio3").checked){
$scope.z.push(1);
$scope.x.push(1);
$scope.y.push(1);
$scope.q.push(1);
$scope.ab.push(1);
}
Answered questions are passed to one of 12th arrays responsible for collecting answers.
JS:
$scope.a= [];
$scope.b= [];
$scope.c = [];
$scope.c= [];
$scope.d= [];
$scope.e= [];
$scope.f= [];
$scope.g= [];
$scope.h = [];
$scope.i= [];
$scope.j= [];
$scope.k= [];
$scope.l= [];
$scope.m= [];
$scope.n= [];
$scope.o= [];
$scope.p= [];
$scope.r= [];
$scope.s= [];
$scope.t= [];
$scope.u= [];
$scope.w= [];
$scope.z= [];
$scope.x= [];
$scope.y= [];
$scope.q= [];
$scope.ab= [];
Then I wrote a list of elements each one representic one array, that is...
<div ng-repeat="record in records">
<div class="rel fptsans {{record.className()}}">{{record.item}}</div>
</div>
ng-repeat is generated with this records array as below:
$scope.records = [
{id:0,
className : $scope.a.length > 0 ? 'special' : 'normal',
item: "a",
link: $scope.className == "special" ? "a.html" : ''
},
{id:1,
className: $scope.b.length > 0 ? 'special' : 'normal',
item:"b",
link: $scope.className == "special" ? "b.html" : ''
},
{id:2,
className: $scope.c.length > 0 ? 'special' : 'normal',
item:"c",
link: $scope.className == "special" ? "c.html" : ''
},
//and so on to 12th.
I was sure that every part of the app was consistent but soon I was about to get surprised that Angular doesnt show any results within the ng-repeat="record in records" because it is reffering to an empty objects ($scope.a = []; is in fact empty at initialization), despite that I am able to view the length of an array by simply writing in my html {{a.length}} so apparently the length of an array is increasing.
My question is how may I use $scope.[some array].length inside my angular array. Should I use ng-model with radio buttons ? would it be helpful ? How can I solve this problem which currently made me stuck in one place.Please help I am really out of solutions. Thank You in advance
I think you are populating the $scope.records before the compute is being called. That would result to empty array at the beginning. You need to re-populate the $scope.records by watching your arrays. Look up $watch and see how it works. I personally think you should not put all of those a, b, c, etc. items in the $scope but you should put them in some thing like $scope.Questions.a, $scope.Questions.b, $scope.Questions.c, etc. Then you can create a watch on $scope.Questions or individual items.
[Edit]
I see where is the problem! Before I start to explain the situation I want to recommend you to read more about AngularJS and how to think in AngularJS world (maybe this can help "Thinking in AngularJS" if I have a jQuery background?)
There are a few problems with your code: First you didnt have {{ in your class definition
<div class="record.className}}">
i fixed it:
<div class="{{record.className}}">
the other problem was that you were initializing the ClassName and Link properties of $scope.records in the initialization of the controller and you never updated those values based on the changes in apenic. That means the $scope.Records is being initialized when $scope.alepnic is empty hence both records would have the class "normal". Now if you increase the length of $scope.Records nothing is updating your records to reflect the changes. I moved the initialization code into the compute method so your records are re-evaluated every time your array changes.
the updated code: http://jsfiddle.net/Tb9j5/8/
$scope.compute=function()
{
$scope.alpeic.push(1);
$scope.records = [
{id:0,
link:$scope.alpeic.length > 5 ? "alpeic.html" : "",
className:$scope.alpeic.length > 5 ? "special" : "normal",
item:"This is item A"},
{id:1,
link:$scope.alpeic.length > 5 ? "alpeic.html" : "",
className:$scope.alpeic.length > 5 ? "special" : "normal",
item:"This is item B"}];
}
$scope.compute();
This is not the best Angular method to solve your problem but is the easiest one to communicate to you. The other ways is to setup a $watch on your alpeic array and then re-evaluate the properties in your $scope.Records. Also you could and should use ng-class to set class atrributes without needing a scope:
<div ng-repeat="record in records">
<a href="alpeic.html">
<div ng-class="{special: alpeic.length >= 5, normal: alpeic.length < 5}">{{record.item}}</div>
</a>
</div>

Deep JSON result in AngularJS partial

I have a 'deep' json result which I have to display in an AngularJS partial.
I want to display some attributes of the 'person' node. I have a single result, with only one person.
Actually, this is what I'm doing :
Name : {{country.state.town.city.street.houseNumber.person.name}}
FirstName : {{country.state.town.city.street.houseNumber.person.firstName}}
dob : {{country.state.town.city.street.houseNumber.person.dob}}
Phone : {{country.state.town.city.street.houseNumber.person.Phone}}
What I would like to do is :
var person = country.state.town.city.street.houseNumber.person
Name : {{person.name}}
FirstName : {{person.firstName}}
dob : {{person.dob}}
Phone : {{person.Phone}}
Because a partial is a html file with some ng* elements, and I don't want to hack JS within this file, how could I 'create' a local variable ?
Like NuclearGhost says, probably better to do in the controller if you have that option.
If it's a promise, then, in the controller, you can do this:
$scope.country.then(function(country) {
$scope.person = country.state.town.city.street.houseNumber.person;
});
If you can't do it in the controller, maybe this:
<div ng-repeat="person in [country.state.town.city.street.houseNumber.person]">
Name : {{person.name}}
FirstName : {{person.firstName}}
dob : {{person.dob}}
Phone : {{person.Phone}}
</div>

Resources