Select different child JSON element with select input in AngularJS - javascript

I am printing a list of food types by making an API call per category. The food in the categories have this JSON structure:
{"uid":"56",
"title":"Nussbrot",
"code":"X 39 2000000",
"final_factor":"0",
"sorting":"0",
"unit":[
{"title":"Scheiben",
"gram":"45",
"max":"100"
},
{"title":"Messerspitzen",
"gram":"250",
"max":"12"}
]
}
I am looping through & printing the values out into a template. No problem. I am printing the "unit" values into a select box:
<option ng-repeat="title in food.unit">{{ title.title }}</option>
And I am currently printing out the grams & title of the first unit in each food like this:
<div class="max">Max is: {{ food.unit[0].max }}</div>
<div class="grams">Grams is: {{ food.unit[0].gram }} </div>
How can I make this dynamic, so that I am printing out the max & grams of the currently selected unit?
Here's my Plunkr.

Angular makes dealing with options and selected options very easy. You should stop thinking in terms of indexes or value. With angular you can bind the entire object, so there's no need to look it up. For example you could do the following for your select:
<select ng-model='selectedUnit' ng-options="unit as unit.title for unit in food.unit"></select>
Let me briefly explain the expression for ng-options
unit in food.unit means we will iterate over the food.unit array storing each value in unit as we go along.
unit as unit.title means what we are putting in the ng-model whenever the user selects an item is the entire unit object itself. The as unit.title tells angular to use the title of the unit as a display for the option.
What this ends up doing is that whenever the user selects one of the options, the entire unit object will be stored in the ng-model variable (in this case selectedUnit). This makes it really easy to bind it elsewhere. For example you can just do:
<div class="unit">Unit is: {{ selectedUnit.title }}</div>
<div class="max">Max is: {{ selectedUnit.max }}</div>
<div class="grams">Grams is: {{ selectedUnit.gram }} </div>
In angular, if you find yourself dealing with indexes or ids and then looking things up by id or index then you are typically doing it wrong. One of the biggest advantages of using angular is how easy it is to deal with objects, and you should really take advantage of it.
For example, I often see newbies doing something like
<li ng-repeat="person in persons">{{person.name} <a ng-click="savePerson(person.id)">Save</a></li>
And then in their code they use the id to look up the person from an array:
$scope.savePerson = function(id){
var person = persons[id];
$http.post('/persons/'+id, person);
};
This kind of lookup is almost always unecessary with angular. You can almost alway just pass the person right away:
<li ng-repeat="person in persons">{{person.name} <a ng-click="savePerson(person)">Save</a></li>
And then have the click handler take the person:
$scope.savePerson = function(person){
$http.post('/persons/'+person.id, person);
};
I know I strayed a bit from your original question. But hopefully this makes sense and helps you write things more simply using the "angular way"
Her is the plunkr for your example:
http://plnkr.co/edit/lEaLPBZNn0ombUe3GPa9?p=preview

you can fist of all handle the selected item with the ng-selected:
http://docs.angularjs.org/api/ng.directive:ngSelected
<select>
<option ng-repeat="title in food.unit" ng-selected="selectedIndex=$index">{{ title.title }}</option>
</select>
<div class="max">Max is: {{ food.unit[selectedIndex].max }}</div>
<div class="grams">Grams is: {{ food.unit[selectedIndex].gram }} </div>
This should propably work ;) Havn't tryed it yet!

Related

How to show object values in HTML persistently

Let's suppose I am having an object like y={1,2,3}. I want to display its value using Angular in HTML.
So what I did is:
for(var i=0;i<y.length;i++){
$scope.data=y[i]; //transferring
}
and in my HTML it is written:
<html>
{{data}}
</html>
Now I know that it is showing the last value(3) because the data value is updated at the end, and since the last value of the loop is 3 it sets the 3 in HTML. So my question is how can we fix this problem?
First problem is that y should be an array:
var y = [1, 2, 3]
Second, you should use ng-repeat in your html, not for loop:
<span ng-repeat="num in y">
{{ num }}
</span>
Most importantly, you should look through the documentation and some tutorials first. Because it is the most basic part of angularjs which is taught first in every book or tutorial.
UPDATE
If you want to show object properties in your html, you can do this:
<span ng-repeat="(key, value) in y">
{{key}} - {{ value }}
</span>
Yea I got the answer!
Store every response in an array and then render that array using ng-repeat.
It was so easy that it dint scratched my mind.

Angular Drop-down inside of ng-repeat with additional logic needed for selected option

This is basically a 2 part question which is why some of the other answers I've found on StackOverflow don't sufficiently cover what I'm asking.
Also need to note: using Bootstrap.
My simplified html can be explained like this:
<div class="container-fluid">
<div class="row"> Headers </div>
<div class="ParentObjectDiv" ng-repeat="pobj in pobjlist">//pobj list is returned from call in controller
<div class="row"> ParentObject values </row>
<div class="ChildObjectContainer">
<div class="row"> Headers </div>
<div class="ChildObjectDiv" ng-repeat="cobj in pobj.cobjs">
<div class="row">
<div class="col-md-1">
<select ng-model="cobj.someproperty"
ng-options="option for option in optionlist">
//Here is the issue : the optionlist is returned from a separate call in the constructor
//The cobj.someproperty can be null, and when that's the case, I want a custom selection
//that says please select a property
</select>
</div>
</div>
</div>
</div>
</div>
</div>
Ok, so on to what I have tried.
Can't do a selectedOption = "whatever" in the controller for obvious reasons.
I have tried adding an angular expression that sets the property of cobj.someproperty to a value like "Value not know" if it detects that the property is empty/null.
This is probably coming down to a fundamental misunderstanding of angular on my part. I have tried putting the expression that assigns this "not known" value to the property in various expression directives and just in the html itself. It is not an option to have this "not known" value on the actual object in the database and the list of Pobj's and their Cobj's is very large so I don't think I can spare iterating the entire list structure to set it before rendering and then iterating it again in the ng-repeats. I'm hoping that I can have a quick expression that evaluates null and sets it. Something like:
{{cobj.someproperty = cobj.someproperty ? cobj.someproperty : "value not known"}}
But not sure if that's a valid expression and if it is where I would put it because so far I've tried putting it in the ng-model itself, an ng-if, and just a blank line of html all within the scope of the cobj in the ng-repeat and none are working.
I haven't "tried" this, but my preferred solution and the one I've been researching is to see if there is a way to instead of evaluating and changing the cobj.someproperty, to change the ng-model of the select to point at a dummy property and at the same time set the cobj.dummyproperty to cobj.someproperty if some property is set, otherwise to set it to "value not known".
Additional considerations :
The parentobject list can be very large (>1k) and has on average 3 childobjects (but can have anywhere from 1 to 20) so performance is an issue.
There will be many cases where the user will not want to set this property so "value not known" when null will not be a temporary thing.
A user also needs to be able to select "value not known" if they have later realize they were mistake about the cobj.someproperty.
I am going to work on the logic to push the changes back to the database later so I am not worried about how the value is stored in the model in angular because I will most likely not use the ng-model to update the field. Right now I'm just worried with the selected option of the drop down.
Here is the answer with simplified html.
JavaScript code
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.items = [{
"someProperty": "abc"
}, {
"someProperty": "xyz"
}, {
"someProperty": null
}]
$scope.optionlist = ["abc","xyz","pqr"];
});
HTML code:
<table ng-controller="MainCtrl" >
<tbody>
<tr ng-repeat="item in items track by $index">
<td width="75%">
{{ item.someProperty }}
</td>
<td width="25%">
<select ng-model="item.someProperty" >
<option value="">Value not know</option>
<option value="{{option}}" ng-repeat="option in optionlist">{{option}}</option>
</select>
</td>
</tr>
</tbody>
So whenever angular finds a null value for someProperty it binds the value to "Value Not Know". I am using ngRepeat instead of ngOption. Let me know if this is what you are looking for.
here is my plunk

How to show the name of the variable in an AngularJS website?

I'm trying to show the name of the variable in my website written with AngularJS.
for example:
Backend code:
$scope.Bundles = {
Bundle1:["Sensor1","Sensor2"],
Bundle2:["Sensor1","Sensor2","Sensor3"],
Bundle3:["Sensor1","Sensor2","Sensor3","Sensor4"]
}
Frontend code:
<label ng-repeat="name in Bundles">
<div> *Want to show "Bundle#" (name), instead of it's value (the sensors)* </div>
</label>
Some notes:
From google searches, I always find people asking how to show the value of the variable, {{name}}, I know that, haven't found anything like the question im asking here
I need it because later in the code I will need to do a ng-repeat with "sensor in name" to show the sensors separately, so I really need a concrete solution and not a dirty one with another array holding the names.
Thank you.
You can access both the key and value using:
<label ng-repeat="(key, value) in Bundles">
<div> *Want to show {{ key }}, instead of it's value {{ value }} (the sensors)* </div>
</label>
You can use the tuple returned by the ng-repeat as stated in the docs https://docs.angularjs.org/api/ng/directive/ngRepeat
<label ng-repeat="(key,value) in Bundles">
You can use javascipt Object.keys(arr) to get all the keys and then iterate to the keys using ng-repeat.
$scope.BundleNumbers = Object.keys($scope.Bundles)
$scope.BundleNumbers will have ["Bundle1", "Bundle2", "Bundle3"]
<label ng-repeat="name in BundleNumbers">
{{name}}
</label>
The other and efficient/angular way to do is :
<label ng-repeat="(key,value) in Bundles">{{key}} </label>
Reference links:
Angular JS ng Repeat
JavaScript Object keys

Maintaining an array of ints representing option indices in Angularjs

I have an array of ints in my model which is meant to represent the indices of a list of options the user will pick from using a select list. The idea is there's a list you can expand and you keep picking things from the select list. I have code along these lines:
<ul>
<li ng-repeat="item in model.arrayOfInts">
<select ng-model="item"
ng-options="choice.id as choice.name for choice in common.options">
<option value="">---</option>
</select>
<button ng-click="model.arrayOfInts.splice($index, 1)" type="button">
Delete
</button>
</li>
</ul>
<button ng-click="model.arrayOfInts.push(null)" type="button">
Add
</button>
I have two problems which seem to be related:
the ng-model does not seem to actually bind properly; if I inspect the scope I can see that newly-pushed members of arrayOfInt are still set to null even after I select something from the select menu representing them.
When I attempt to push another item into the array, Angular complains that duplicate options are not allowed.
What is the proper way to do what I'm trying to do?
JSFiddle sample
The first issue ("ng-model does not bind properly") is because you're not targeting the array with ng-model. item in your ng-repeat is a new property on the scope (created by the ng-repeat). It doesn't contain any information on where it came from (arrayOfInts).
The following code tells ng-model to point to the right index of the array, rather than a new scope property.
<select ng-model="model.arrayOfInts[$index]"
ng-options="choice.id as choice.name for choice in common.options">
The second issue is because model.arrayOfInts can have multiple duplicates in it (click "add" twice and you've just added two nulls). Angular needs some way to tell the difference between them, so you need to add a tracking property, in this case $index.
<li ng-repeat="item in model.arrayOfInts track by $index">

AngularJs - Holding value of for loop string to use elsewhere

I've come a bit stuck in my angularjs project.
I run a for loop to query some nested JSON data and output it in 3 different variables inside an ng-repeat. So it makes up a title where i have the control over the elements that make up the title {{ number }} {{ shots }} {{ goals }}.
However, my knowledge of angularjs is stretched here because when I click on one of the events (from the ng-repeat list) it gives me a new tab, but I want to bring the title of that event to the new tab.
I can't call it as a scope variable as the last variable is still being held in there. I thought about assigning it as a new variable.. but was unsure how to actually do that in angularjs.
Here is the code i'm working with:
<li ng-repeat="event in events.events">
<div ng-if="actionType(event)" >
{{number}}
{{shots}}
{{goals}}
</div>
<a class="showPlayer" ng-click="showPlayer(event)">
View more stats
</a>
</li>
my angularjs is just a standard for loop which looks for values inside the js and assigns them as variables.
Any advice is very much appreciated.
EDIT: 24 hours later and I still can't crack this (very frustrating).
I'm not sure if there is a way to grab the string from the ng-click and clone that?
I don't want to have to run another check for the title when I already have the information, surely there is an 'angular' way to do this??
Please try this I am not sure but it might help you
<li ng-repeat="event in events.events">
<div ng-if="actionType(event)" >
{{event.number}}
{{event.shots}}
{{event.goals}}
</div>
<a class="showPlayer" ng-click="showPlayer(event.number,event.shots,event.goals)">
View more stats
</a>
</li>
Try using $rootScope.
Define a rootscope variable where event is handled and write your title in html like you did. {{title}}
$rootScope.title = "example";

Categories