Link data: Angular - angularjs

My angular app needs to link together two different data objects, or something like that. I'm having trouble putting this into words.
Data ::::
$scope.users = [{userid: "5", name: "Bobby"},{userid: "3", name: "Fett"}];
$scope.comments = [{id: "1", content: "a comment", userid: "3"},{id: "2", content: "another comment", userid: "3"}];
Directive ::::
<article ng-repeat="comment in comments">
Posted by: {{user.name}} Comment: {{comment.content}}
</article>
Obviously, {{user.name}} isn't going to work. But the idea is to get the user name from the matching comment userid.
Not really sure where to start with this

One possible solution could be a user index to get the corresponding user:
var userIndex = {};
for (var i = 0, len = users.length; i < len; i++) {
userIndex[users[i].userid] = users[i];
}
$scope.userIndex = userIndex;
$scope.comments = comments;
Using this index you can get the username:
<article ng-repeat="comment in comments">
Posted by: {{ userIndex[comment.userid].name}} Comment: {{comment.content}}
</article>
See this plunker.

Related

get value in array in ngfor

I want to know how to get value in array in *ngFor. First I use *ngFof to get item list. Second I use commonService.indexKey$.getValue() to check id in commonService.quantityList$.getValue() available or not
This is my code
HTML
<div *ngFor="let item of commonService.quantityList$.getValue(); let i = index" class="Box">
<label>Qty : {{commonService.indexKey$.getValue()== item.id?item.quantity - commonService.indexKey$.getValue().count:item.quantity}}</label>
</div>
Example data
commonService.quantityList$.getValue()
quantity = [
{ id:1, quantity:100 },
{ id:2, quantity:200 },
{ id:3, quantity:30 }
];
commonService.indexKey$.getValue()
indexCount = [
{id: 1,count: 2},
{id: 2,count: 3},
{id: 3,count: 4},
]
Not sure what are you trying to do in your label really because seems you are making a comparison “==“ so the label will output “true” or “false”. Is that what you really want?
<div *ngFor="let item of commonService.quantityList$.getValue(); let i = index" class="Box">
<label>Qty : {{commonService.indexKey$.getValue()[i]== item.id?item.quantity - commonService.indexKey$.getValue()[i].count :item.quantity}}</label>
</div>

AngularJS ng-repeat and indexOf() to check objects

I have two json objects (data1 and data2) that have related information. Namely, both objects have properties (arrays) which in turn can have identical data. So, I am trying to figure out how to display those data with highlighting them properly, i.e. identical data with green color and non-identical with red color. Somehow it wrongly highlights all data with red color.
Here is the html:
<ul>
<li ng-repeat="item in vm.data2.features"
ng-class="vm.data1.features.indexOf(item) !== -1 ? 'check' : 'uncheck'">
<span ng-bind="item.id"></span>
</li>
</ul>
and objects:
vm.data1 = {
id: '4569',
name: 'Given data',
features: [
{id: "TEST_TEXT2", desc: 'smth12'},
{id: "TEST_PPP", desc: 'smthsmthsmth'},
{id: "TEST_ECASH", desc: "somelongtexthere"}
]
};
vm.data2 = {
id: '1305',
name: 'Base data',
features: [
{id: "TEST_BP", desc: 'smth'},
{id: "TEST_TEXT2", desc: 'smth12'},
{id: "TEST_PPP", desc: 'smthsmthsmth'},
{id: "TEST_TEXT1", desc: 'blahblah'},
{id: "TEST_ECASH", desc: "somelongtexthere"}
]
};
The full demo is here.
Any help would be appreciated.
Indexof() method will look for similarity in object references not the id itself. findIndex() method can help you here instead.
vm.hasFeature = function(item){
var hasElements= vm.data1.features.findIndex(function(e){
return e.id == item.id;
});
console.log(item, hasElements);
return hasElements;
}
And in html
<li ng-repeat="item in vm.data2.features"
ng-class="vm.hasFeature(item) > -1 ? 'check' : 'uncheck'">
vm.hasFeature = function(item){
var hasElements= vm.data1.features.findIndex(function(e){
return e.id == item.id;
});
console.log(item, hasElements);
return hasElements;
}
CodePen Link: https://codepen.io/anon/pen/ewgLBN?editors=1010
None of the objects will be the same because indexOf(item) will compare object references of item. You'll need to do a deep equals comparison of the items.
i.e.
{id: "TEST_TEXT2", desc: 'smth12'} === {id: "TEST_TEXT2", desc: 'smth12'} // false
vm.data1.features[0] === vm.data1.features[1] // false
Example using lodash would be something like:
_.some(vm.data1.features, otherItem => _.isEqual(item, otherItem))
Because
_.isEqual(vm.data1.features[0], vm.data2.features[1]) // true
Docs for Lodash:
_.some
_.isEqual

Angular how to have multiple selected

I have this array of objects. that holds somethings like this.
[
{
id: 1,
name: "Extra Cheese"
},
{
id: 2,
name: "No Cheese"
}
]
im iterating thru the array here
<select ng-model="item.modifiers" multiple chosen class="chosen-select" tabindex="4" ng-options="modifier._id as modifier.name for modifier in modifiers"></select>
The thing item.modifiers model that has an array of this 2 id
[
1,2
]
I want the multi select to auto selected the two ids that are in the item.model
I want the final result to look something like this
Your code is pretty much working already, maybe some of the variables are not assigned correctly (eg. id instead of _id)
angular.module('test', []).controller('Test', Test);
function Test($scope) {
$scope.modifiers = [
{
id: 1,
name: "Extra Cheese"
},
{
id: 2,
name: "No Cheese"
}
]
$scope.item = {};
// add this for pre-selecting both options
$scope.item.modifiers = [1,2];
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>
<div ng-app='test' ng-controller='Test'>
<select ng-model="item.modifiers" multiple chosen class="chosen-select" tabindex="4" ng-options="modifier.id as modifier.name for modifier in modifiers"></select>
</div>
If I understand the question correctly, you're wanting to pre-select the two options.
To do this you will need to set your ng-model to point to the actual objects you are iterating over.
You will also need to change your ng-options to ng-options="modifier as modifier.name for modifier in modifiers" rather than just iterating over the ids.
Here's the relevant documentation under Complex Models (objects or collections)
https://docs.angularjs.org/api/ng/directive/ngOptions
Something like this should work:
HTML:
<select ng-model="$ctrl.item.modifiers"
ng-options="modifier as modifier.name for modifier in $ctrl.modifiers"
multiple chosen class="chosen-select" tabindex="4" >
</select>
JS:
app.controller("my-controller", function() {
var $ctrl = this;
$ctrl.modifiers = [{
id: 1,
name: "Extra Cheese"
}, {
id: 2,
name: "No Cheese"
}];
$ctrl.item = {
modifiers: []
}
$ctrl.$onInit = function() {
const id1 = 1;
const id2 = 2;
for (const modifier of $ctrl.modifiers) {
if (modifier.id === id1 || modifier.id === id2) {
$ctrl.item.modifiers.push(modifier);
}
}
}
}
Here's a pen showing the result:
http://codepen.io/Lahikainen/pen/WooaEx
I hope this helps...

How to bind variables to INPUT dynamically

I have an object in the controller which value I am getting from http GET request:
$scope.myObj = {
id1: "1",
id2: "5",
id3: "",
id4: ""
};
It can have any number of fields (id...) with any values. But if id-k is not empty all id-n where n < k is not empty too.
I need to bind to INPUT last not empty field of the object. What is best way to do it?
Here is a plnkr
Update: This object is a position in the classificator.
In my example ID of position is 1.5. I need to allow edit only last position in the classification. The user can change 5 to 6, 7 or anything else, but it can not change 1 segment
If the object will be
$scope.myObj = {
id1: "2",
id2: "5",
id3: "4",
id4: "8"
};
The classification is 2.5.4.8 and user must be able edit only last segment - 8.
Controller
...
$scope.myObj = {
id1: "1",
id2: "5",
id3: "6",
id4: ""
};
$scope.segments = Object.keys($scope.myObj)
.filter(function(key) {
return $scope.myObj[key];
})
.sort(function(a, b){
return Number(a.replace('id', '')) - Number(b.replace('id', ''));
});
...
HTML
<span ng-repeat="segment in segments">
<span ng-if="!$last">{{ myObj[segment] }}</span>
<input ng-if="$last" ng-model="myObj[segment]">
</span>
<p>{{ myObj }}</p>
Plnkr - https://plnkr.co/edit/8C9lLLdCvvzFinaOXqtd?p=preview
Original Answer
You can calculate the last non blank id in the controller and set it to a scope variable. Something like
$scope.myLast = $scope.myObj['id' + Object.keys($scope.myObj).reduce(function(a, key){
if ($scope.myObj[key]) {
var idNum = Number(key.replace('id', ''));
a = Math.max(a, idNum)
}
return a;
}, -Infinity)];
Note - you can't rely on the order of keys, so you can't actually assume that the last key is the biggest one.
Plnkr - https://plnkr.co/edit/apy8qZNJNK4Q23J5Ja4N?p=preview
I need to bind to INPUT..
So it seems ,what you have is , a list of objects where the no. of elements in the list can vary.. and you want to bind all of them to <input>
If so then this would do the job:
<div ng-init="tempName = key" ng-repeat="(key, value) in myObj">
<label for="{{key}}" >{{key.toUpperCase()}}</label>
<input name="{{key}}" id="{{key}}" type="text" ng-model="myObj[tempName]" />
</div>
here's an awesome plunkr doing just that
EDIT:
To ignore the empty fields : use this

Loop through an array of objects with ng-repeat angular

I can't find a way to loop through my array of json objects with angular .
My array looks like that in firebug(Each series of objects have an index value.):
[[0], Object { idliste=0, id=1, photo="pot.jpg", plus...}, Object { idliste=0, id=3, photo="pot.jpg", plus...}]
[[1], Object { idliste=1, id=1, photo="pot.jpg", plus...}, Object { idliste=1, id=3, photo="pot.jpg", plus...}]
[[2], Object { idliste=2, id=1, photo="pot.jpg", plus...}, Object { idliste=2, id=3, photo="pot.jpg", plus...}]
It has been produced by this code :
var idListe = $scope.getIdListe();
$scope.listeCommandes[idListe]= new Array([idListe]);
for (i=0;i<$scope.panier.length;i++){
$scope.listeCommandes[idListe].push({
idliste:idListe,
id: $scope.panier[i].id,
photo: $scope.panier[i].photo,
nom: $scope.panier[i].nom,
quantite:$scope.panier[i].quantite,
prix: $scope.panier[i].prix,
heureajout:$scope.getHeure()
});
};
$scope.getIdListe = function(){
var idListe = $scope.listeCommandes.length;
return idListe;
};
And the html is :
<div ng-repeat="idliste in listeCommandes" >
<div ng-repeat="(nom, id) in idliste">
{{nom}} : {{id}}
</div>
</div>
It doesn't work. I really can't figure how to make it work, it means, simply print each objects, following the index number.
THank you if u got any idea. I've searched the forums but can't find any solution. Maybe it's the way i 've created an index that is wrong ?
finally answered my problem by adding an angular module called angular-filter "mentionned within this example:
http://jsbin.com/weyov/45/edit?html,js,output
Thank a lot for you help .
Now my code look like that :
var idListe = $scope.getIdListe();
for (i=0;i<$scope.panier.length;i++){
$scope.listeCommandes.push({
idliste:idListe,
id: $scope.panier[i].id,
photo: $scope.panier[i].photo,
nom: $scope.panier[i].nom,
quantite:$scope.panier[i].quantite,
prix: $scope.panier[i].prix,
heureajout:$scope.getHeure()
});
};
and the html :
<ul ng-repeat="(key, value) in listeCommandes | groupBy: 'idliste'">
Group name: {{ key }}
<li ng-repeat="article in value">
article: {{ article.nom}}
</li>
</ul>
then my orders are now all automtically grouped by ID in the html view :
Group name: 0
article: Pots Gris
article: Pot Vert
Group name: 2
article: Pot Bleu
article: Pot Vert
article: Pinceaux
Group name: 5
article: Pots Gris
article: Pot Vert
article: Pot Rouge
article: Pot Bleu

Resources