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.
Related
Let's say I have struct :
struct Planet {
var id : UUID
var name: String
...
}
I have an array of such structs which is constructed from data fetched from a database. I use this for a form in a browser where the user can:
edit the fields (eg change the name of Planet)
create one or more new Planets
at this time the user may not delete a Planet but it would be great if the solution would support that too
When the form is submitted I get an array with those structures (the order is also not the same as the original). What is the best/most efficient way to do update the data in the original array with the data from the second.
My current idea is:
map the original array to a dictionary with key= id, value= aPlanetStructure
loop over the second array (with the edited data) and if that 'key' can be retrieved in the dictionary (=data from first array)-> update the struct there, if not create an additional planet in the first array.
I'm not sure if this is a good approach, it seems like there could be a more efficient way (but I can't think of it). It would also not support deleting a Planet
In general, if you can separate out the elements of the array by action, you'll make your life easier.
For example:
var created= [Planet]()
var updated= [Planet]()
var deleted = [Planet]()
In your UI layer, when an edit is made, add the edited planet to the
updated array, when a planet is deleted, add it to the deleted array, etc.
Submit all 3 arrays with your form.
Loop over the results of each and pass too your create, update, and delete methods that access your database.
That will require restructuring your form code a bit, but... in general it's easier in your UI layer to tell whether someone is doing a create, an update, or a delete, than it is to mush them all together and try to figure it out after the fact by doing comparisons.
I'm using React Native and Open Weather Map API to build a small weather app. The data I retrieve from the API call is more than I want to use so I parse out just the pieces I need and store them in an array. I then take the array and set it to a state object. I can reference the object, but instead of saying my array is an array, it says it's an object, and thus won't let me use any array methods on it. How do I get around this?
//reponseData is the data retrieved from the API call; the data retrieved is an object with arrays and objects
within. The forecast data for the next five days is given in 3 hour increments, so you have a 40 item array of
data pieces. I loop through this list of 40 items, pull out just what I need...
let forecastArray = [];
for (let i=0; i<responseData.list.length; i++) {
let day = responseData.list[i].date
let high = responseData.list[i].weather[0].hiTemp
let low = responseData.list[i].weather[0].loTemp
let condition = responseData.list[i].sys.condition
forecastArray.push(day)
forecastArray.push(high)
forecastArray.push(low)
forecastArray.push(condition)
this.setState({
forecastData: forecastArray
})
When I log, I get an array....
console.warn("forecast is: ", this.state.forecastData)
OUTPUTS: forecast is: ["11-06-2019", 52.5, 47.3, "sunny", "11-06-2019", 63.9, 39.7, "sunny", ...]
Referencing this.state.forecastData[2], for example, however was giving me errors. So I checked the typeof this.state.forecast to see why and it says the array is an Object? I need to further divide out the array data and manipulate it. The first several items (e.x. forecastData[0] through forecastData[9] would be for the forecasted weather for 11-06-2019 at 3pm, ,6pm, 9pm so I need to pull those items, get the highest high and lowest low, etc. I can't do that since I can't even reference the items in the array.
Things I've tried:
using Object.entries and Object.assign methods, but that just splits the items into several arrays, with the first item being the location number and the second item being the array item content. I've tried manipulating the array within the component that uses it, but it still is an Object not an Array, so I can't reference the individual items. The data set is large enough I don't think it would be best practice to push each of the 40+ items into their own state object key.
in Javascript array is a subset of object , i'e it has the same prototype. So typeof Array will be an object. Thats not an issue. Can you update with the error which you are getting while accessing this.state.forecastData[2] coz what i . believe its something not with syntax , rather with the duration of API call.
I would recommend when accessing this.state.forecastData[2] first check if its length is greater than 0 , that way you are sure that there is data inside the array.
constructor(props){
forecastData:[]
}
and when you use it ,
if(this.state.forecastData.length > 0){
this.state.forecastData[2]
}
Try this, and revert with doubts.
Thank you, Gaurav Roy! You were partly correct. The typeof didn't matter at all. But the issue wasn't with the duration of my API, it was that my component was trying to render when it didn't have the data from the API call yet! I put in a conditional
{this.state.forecast !== null && <Forecast forecast=this.state.forecastData />}
and got things working now. Thanks for the quick reply!
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);
};
Pretty new to AngularJS and Firebase here, I am trying to convert angular-dragdrop.js as per the following link below to work with angularFire 0.8.0 $asArray feature:
https://github.com/codef0rmer/angular-dragdrop/blob/master/src/angular-dragdrop.js
I was just wondering if the following changes would be sufficient:
1) Include firebase within function declaration
(function (window, angular, firebase, undefined) {
2) Include $firebase within jqyoui callback function
var jqyoui = angular.module('ngDragDrop', []).service('ngDragDropService', ['$firebase', '$timeout', '$parse', function($timeout, $parse) {
3) Change all the "push" and "splice" update on the dropModelValue and dropModelValue to $add and $remove instead.
dropModelValue.$add(dragItem);
4) Add $save after dropModelValue and dropModelValue assignments
dragModelValue[dragSettings.index] = dropItem;
dragModelValue[dragSettings.index].$save(dragSettings.index);
Your help is much appreciated. Much thanks in advance.
You can utilize $extendFactory to override the push/splice behaviors instead of hacking on the drag drop lib. Ideally, you would just update the priority on the records and let the server move them.
Keep in mind that Firebase data is a JSON object (not an array and therefore not ordered in JavaScript), so moving items in the array has no effect on their position on the server. You must use priorities if you want to enforce an order on the data, other than lexicographical sorting by keys.
Also, you aren't using $save correctly--you call array.$save(item), not item.$save(itemIndex). Judging by these misconceptions, there are likely to be lots of other issues. A trip through the Angular Guide and the Firebase JS Guide be a great primer here.
One technique I have used to reorder a Firebase array using drap & drop, is to rebind the keys to the values so that their lexicographical order match the new order set by the user. Since Firebase will enforce lexicographical order of keys, swapping the keys of 2 values will swap the values. Every time the user drops an item, rebind the keys:
_(myFirebaseArray)
.map('$id')
.sortBy()
// at this stage we have the array of keys sorted lexicographically
// we pair each key with the values, which are sorted by the user
.zipObject(myFirebaseArray)
// for each pair, bind the key to the value and save
.each(function (value, newKey) {
value.$id = newKey
myFirebaseArray.$save(value)
})
This is probably sub-optimal. I was not aware of priorities. This technique can probably be adapted fairly easily to use priorities. The code above should be compatible with lodash from 2 to 4.
Example of this technique in an application here. The ranking array is bound to the drap & dropping through Angular UI.Sortable.
I'm making a realtime app with AngularJS and Firebase. I'm storing an array of data (players).
Below you can see a sample of my datastructure.
I can get all the players of this particular game, but how do I get for instance the player 'test'? The key is a generated value:
Game.find(gameId).child('/players/').push(player);
Then I thought, why don't I just 'update' '/players/'+name and set the name there. But unfortunatly I'm getting back objects inside an object:
{
players : {
"name":"...",
"test":"moretest"
}
}
I can access these properties but I cannot loop over them because it's not an array.
So basically what I want to do is "linq-wise" getting a player out of an array.
Game.find(gameId).child('/players/').where( name == ...);
Thanks in advance
Edit:
You are on the right track with storing just the name of the player instead of using push to generate an ID. You'll need to make sure your player names are unique though, otherwise you risk not being able to accommodate two players with the same name.
Every key in Firebase must have a value, so the best way to store a list of players where you want them to be accessible by the player name is to simply set them to a boolean value like 'true':
Game.find(gameId).child('/players').child(player).set(true);