I'm working on an application where I have to handle vehicules (items) defined by their brand, model and phase. Here is a simple version on Plunker : http://plnkr.co/edit/gA9mzMde4i9hpDfeOdWe
I have created 3 select based on a list of brand. Each brand has a list of models, and each models has a list of phases.
<select ng-options="brand as brand.label for brand in list track by brand.id" ng-model="itemTemp.brand" ng-change="itemTemp.model=''; itemTemp.phase='';">
<option value="">Choose a brand</option>
</select>
When I saved the informations in my database, I realized that I was saving the whole models array in my item.brand and the whole phases array in my item.model, which in reality is way bigger than the example on Plunker. In order to save lighter item in my database, I decided to save only the labels of my brand and model. I reduced the weight of my item by 10.
The problem of doing so is that later when I need to retrieve the informations of the item I saved in my selects, I can't. If I save the whole arrays in item.brand ans item.models, my selects can retrieve the informations and take the correct value.
My question is : Is there any way to have the same result by only saving the labels and not the whole arrays ?
You can retrieve saved data by comparing it with your source array.
Unfortunately it requires looping over data and find the matching entry.
I have edited your Plunker: http://plnkr.co/edit/dC1hMD2ZL79z37kPHAzE?p=preview
$scope.restoreItem = () => {
$scope.itemTemp.brand = findInArray($scope.list, $scope.itemSaved.brand, 'label');
$scope.itemTemp.model = findInArray($scope.itemTemp.brand.models, $scope.itemSaved.model, 'label');
$scope.itemTemp.phase = findInArray($scope.itemTemp.model.phases, $scope.itemSaved.phase);
};
Related
I'm trying to get data from an array dynamically without having to right every object like this:
<option value="City" selected="selected">City</option>
<option data-option="USA" value="LA">{{countries.data[0].cities[0].name}}</option>
<option data-option="USA" value="CA">{{countries.data[0].cities[1].name}}</option>
unfortunately, i cannot post the source code here because it belongs to my company but i can describe my issue
I need to not to have to write every city in a new option element, i need the elements to be generated dynamically as long as there are still index in the array, i tried to use ngfor but i dont know the right syntax for it to generate every index in an element.
I can describe further if anything is missing or not clear, just comment.
I am a beginner.
trying to make a simple soccer game.
All values are initialized to 0.
select 2 different teams from the dropdown >> enter final score (cannot be negative).
On clicking 'Final score' button,
function should increment the value of 'Played' to 1 for both the teams.
as well as display in the table.
function updateTeam(winner,looser){
if (var a = $scope.Ligateams.lastIndexOf(winner)){
$scope.Ligateams.played = "1";
}
}
Code here
I took a look here, found a few things. I did not change everything, but you should have the tools to make other changes (ex. updating the draw count).
You had two controllers, one was basically acting just to retrieve the list of teams. This complicated the manipulation of the data, so I changed to use $http, and loaded from a .json file.
In your UI, you iterated over the teams, and stored the name. I changed this to store the index for the two teams that were selected. This is used throughout the code to access that team. Since iteration was already occurring in the UI, it made sense to store those indices vs. searching it again in the controller. This grants us access to the object in the teams array with which to increment values.
Relevant bits of code follow.
Load Data via HTTP
$http.get('teams.json').then(function(resp){
$scope.Ligateams = resp.data;
})
Using the index vs. Name
<select ng-model="Matchteam2.idx" ng-disabled="editButton1">
<option ng-repeat="Matchteam2 in Ligateams"
value={{$index}}>{{Matchteam2.name}}
</option>
</select>
Accessing Team info in the Controller
Now we can get the team object from the array of teams with the index.
var team1 = $scope.Ligateams[$scope.Matchteam1.idx];
var team2 = $scope.Ligateams[$scope.Matchteam2.idx];
team1.played++;
team2.played++;
Accessing Team info in the UI
Since the basic 'name' field is no longer on Matchteam#, we can access the name property on the team object in the Ligateams array, again using the index.
Goal by Team <b>{{Ligateams[Matchteam1.idx].name}}</b
Here's a sample with some things fixed: https://plnkr.co/edit/Yby8D0z8IIEGXNxlwX4D?p=preview.
I have a stored object literal which returns 2 or more objects depending on the users actions. This is then filtered further depending on if they are complete or not, so there are generally 2 object arrays that are sent to the view.
in the view i do a simple ngFor
<ion-card *ngFor="let item of inProgressList">
...
Which is a segment of the complete list held in a variable programsList
In order to change an item from in progress to complete i need to update the object, which works fine, however i cannot correctly pass the index.
filledOutFormsData[this.index].complete = true;
As i cannot get the correct index based on the array that has been filtered.
I cannot use
<ion-card *ngFor="let item of inProgressList; let i = index">
Because that will return a index of the looped items which will be incorrect once one other object is equal to complete
Basically i need to get the object key from the original object literal into the filtered array to use in the view so that i can pass the index.
So i got this working by adding a custom pipe which filters the programsList instead of passing in two separate lists, I can then use the trackBy option to pass the correct index.
I am querying for a collection of IDs from Parse.com and showing them in my $scope as an array.
I would like to apply a class to the items in my $scope that match any one of these IDs, placing a border around the object illustrating that it is already contained in the 'saved' array. I have tried the following however not having any luck.
ng-class="{'approved': ParseSavedExercises.indexOf(exercise.id) == -1}"
in this case my ParseSavedExercisesis my array to check against and exercise.id is what I am checking for.
here is a quick fiddle
Please see here http://jsfiddle.net/e9pr4yqj/
Yours ParseSavedExercises contains string and id is number so no id existed in ParseSavedExercises
$scope.ParseSavedExercises = ['2','3'];
change to
$scope.ParseSavedExercises = [2,3];
or use
ng-class="{'approved': ParseSavedExercises.indexOf(exercise.id.toString()) == -1}"
like here http://jsfiddle.net/1ujgvL80/
I have the following code
<table>
<thead><td>Id</td><td>Name</td><td>Ratings</td></thead>
<tbody>
<tr ng-repeat="user in users">
<td>{{user.id}}</td>
<td>{{user.name}}</td>
<td><div ng-repeat="item in items">{{item.rating}}</div></td>
</tr>
</tbody>
</table>
users is an array of user objects with only id and name. number of user objects in array - 150
items is an array of item objects with only id and rating. number of item objects in array - 150
When i render this in browser, it takes about 250MB of heap memory when i tried profiling in my chrome - v23.0.1271.95.
I am using AngularJS v1.0.3.
Is there an issue with angular or am i doing anything wrong here?
Here is the JS fiddle
http://jsfiddle.net/JSWorld/WqSGR/5/
Well it's not the ng-repeat per se. I think it's the fact that you are adding bindings with the {{item.rating}}.
All those bindings register watches on the scope so:
150 * 2 = 300(for the 2 user infos)
150 * 150 = 22500(for the rating info)
Total of 22800 watch functions + 22800 dom elements.
That would push the memory to a conceivable value of 250MB
From Databinding in angularjs
You can't really show more than about 2000 pieces of information to a
human on a single page. Anything more than that is really bad UI, and
humans can't process this anyway.
I want to say the leak is in the second array because you are potentially looping through the same array and displaying every item for every user row in users so depending on how large your test data is that view could get rather large. I could do a little more investigating. btw your fiddle is something entirely different.
Right now you are looping through 150 X 150 = 22500 items. And registering a watch (or through a directive just adding item rating) to each one.
Instead - consider adding the user's rating to the user object itself. It will increase the size of each user object but you will only loop through 150 items and register watches only on them.
Also - consider looking into Indexes. It's apparent that there could be similar users or item ratings. Just index them, so instead of looping through heavy objects, you can reduce them.
One more thing - if you are going to be running the directive the same instance, at least change the code:
var text = myTemplate.replace("{{rating}}",myItem.rating);
to a concat style string calculation:
var text = '<div>' + myItem.rating + '</div>';
This will save you a HUGE chunk on calculation. I've made a JSperf for this case, notice the difference, it's about 99% faster ;-)