Angular Data Structuring - arrays

I am new to Angular, so apologies in advance if this seems an obvious question...
I know how to display a simple array of objects using the ng-repeat directive, but I'm not sure how to structure more complex layers of information.
For example: If I wanted to list Premier League football clubs, I could simply create an array of objects, the array listing clubs, with each club being an objects containing key-value pairs on various pieces of information or data relating to that club:
$scope.clubs = [
{
name: "Arsenal",
nickname: "Gunners",
clubBadge: "arsenal.jpg",
founded: "1886"
},
{
name: "Newcastle United",
nickname: "Magpies",
clubBadge: "newcastle.jpg",
founded: "1892"
}
// etc...
]
That's fine. But then what I might want to list the players within each club. For example:
// the following being the team of Newcastle United...
{
GK: "Rob Elliot",
LB: "Paul Dummett",
CB: "Fabricio Coloccini",
CB: "Chancel Mbemba",
RB: "Daryl Janmaat",
LW: "Andros Townsend",
MF: "Georginio Wijnaldum",
MF: "Jack Colback",
RW: "Moussa Sissoko",
ST: "Ayoze Perez",
ST: "Aleksander Mitrovic",
}; // and so on for other clubs...
How would I attach the above object to Newcastle Utd (and likewise for other clubs) in the original array, given that it is only a random index within an unordered array? What would be correct way of structuring this information holistically?
I could take this even further by providing stats on each individual player, such as:
{ // stats for Moussa Sissoko
speed: "86",
ballControl: "71",
strength: "85",
vision: "79"
}
{ // stats for Ayoze Perez
speed: "78",
ballControl: "83",
strength: "69",
vision: "78"
}
Again, I have listed these as individual objects. But I don't know what array to link them to their respective clubs, or how to connect each array (assuming there were three separate arrays: $scope.clubs, $scope.players, $scope.attributes).
If Newcastle Utd is the 10th club in the array, it would be $scope.clubs[9], but I don't want to have to create an entirely new array for the players that has no link to the $scope.clubs[] array. Ideally I want it all to be connected.
Is ng-repeat sufficient to access the model data in these cases or would a more sophisticated directive be required? I'm looking to build the information so it is easy to update and display the data in the view.
Sorry this is a little long-winded - if I knew how to phrase my problem more succinctly, I would!
Any advice here would be massively appreciated. Thanks in advance.

Var clubs = [
{
Name : "clubname",
Players: [
{
Name: "name"
},
{
Name:"othername"
}
];
}
];
enter code here

You can put objects inside objects, with you example will look like this:
$scope.clubs = [
{
name: "Arsenal",
nickname: "Gunners",
clubBadge: "arsenal.jpg",
founded: "1886",
players: [
{
//all the player stuff
},
{
//Other player stuff
}
//Continue with all the players
]
},
{
name: "Newcastle United",
nickname: "Magpies",
clubBadge: "newcastle.jpg",
founded: "1892",
players: [
{
//all the player stuff
},
{
//Other player stuff
}
//Continue with all the players
]
}
// etc...
]
And you can access like this $scope.clubs[0].players, I recommend you to give the clubs an Id, that way is going to be much easier to play with the data. To do this, if you have access to the source you can add it from there, if not, you could use foreach loop on the object and add the Id property

Related

Many to Many relationships in Redux store

I created many to many relationship in Laravel and I want to create store with it. For example I have this code:
const INITIAL_PEOPLE = {
all: [
{name: "John", city: "NY"}
]
}
Any people has a tags (many to many relationships). The best way for me would be if my store look like this (unless you have another idea how can I implement and display elements with this relationship):
const INITIAL_PEOPLE = {
all: [
{name: "John", city: "NY", tags: [id: 1, name: "new_tag"]}
]
}
This is example like store looks but only data was the server and add by reducers. So how can I create this structure of store (or solve this problem with another way) with reducer?
You can normalize the data objects in api-response, before storing them into redux.
You can save the data as follows:
Assumption: There is a unique ID for each person.
ReduxStoreState:
{
"people":{
"id_1":{
"id":"id_1",
"name":"John",
"city":"NY"
},
"id_2":{
"id":"id_2",
"name":"Matt",
"city":"NJ"
}
},
"tagsByPeople":{
"id_1":[
{
"id":1,
"name":"new_tag"
}
]
}
}
Now you can write selectors to fetch Tags by providing person-ID

How to model recursively nested data in state

I have a data structure typed like:
export interface IGroup {
id: number;
name: string;
groupTypeId: number;
items: IItem[];
groups: IGroup[];
}
Which recursively represents many to many relationships between a "Group" and a "Group" and an "Group" and an "Item". Groups are made up of items and child groups. An item derives to just a simple type and other meta data, but can have no children. A single group represents the top of the hierarchy.
I currently have components, hooks, etc to recursively take a single group and create an edit/create form as shown below:
I have this form "working" with test data to produce a standard data output as below on save:
{
"1-1": {
"name": "ParentGroup",
"groupType": 2
},
"2-4": {
"name": "ChildGroup1",
"groupType": 1
},
"2-9": {
"name": "ChildGroup2",
"groupType": 3
},
"2-1": {
"itemType": "FreeForm",
"selectedName": "Testing",
"selectedClass": 5
},
"2-2": {
"itemType": "FreeForm",
"selectedName": "DisplayTest",
"selectedClass": 5
},
"3-4": {
"itemType": "EnumValue",
"selectedItem": {
"id": 12900503,
"name": "TRUE"
}
},
"3-5": {
"itemType": "EnumValue",
"selectedItem": {
"id": 12900502,
"name": "FALSE"
}
},
"3-9": {
"itemType": "FreeForm",
"selectedName": "Test",
"selectedClass": 5
},
"3-10": {
"itemType": "FreeForm",
"selectedName": "Tester",
"selectedClass": 5
},
"3-11": {
"itemType": "FreeForm",
"selectedName": "TestTest",
"selectedClass": 5
}
}
The "key" to these objects are the grid column and row since there are no other guaranteed unique identifiers (if the user is editing, then it is expected groups have ids in the db, but not if the user is adding new groups in the form. Otherwise, the name is an input form that can be changed.) It makes sense and it is easy to model the keys this way. If another group or item is added to the hierarchy, it can be added with its column and row.
The problem that I have is that I would love to be able to have an add button that would add to a groups items or group arrays so that new rows in the hierarchy could be created. My forms should handle these new entries.
Ex.
"1-1": {
groups: [..., {}],
items: [..., {}]
}
But the only data structure that I have is the IGroup that is deeply nested. This is not good for using as state and to add to this deeply nested state.
The other problem I have is that I need to be able to map the items and groups to their position so that I can translate to the respective db many to many tables and insert new groups/items.
Proposed solution:
I was thinking that instead of taking a group into my recursive components, I could instead create normalized objects to use to store state. I would have one object keyed by column-row which would hold all the groups. Another keyed by column-row to hold all the items. Then I think I would need two more objects to hold many to many relationships like Group to Group and Group to Item.
After I get the data from the form, I hopefully can loop through these state objects, find the hierarchy that way and post the necessary data to the db.
I see that this is a lot of data structures to hold this data and I wasn't sure if this was the best way to accomplish this given my modeling structure. I have just started using Redux Toolkit as well, so I am somewhat familiar with reducers, but not enough to see how I could apply them here to help me. I have been really trying to figure this out, any help or guidance to make this easier would be much appreciated.
Go with normalizing. Each entity having a single source of truth makes it much easier to read and write state.
To do this, try normalized-reducer. It's a simple higher-order-reducer with a low learning curve.
Here is a working CodeSandbox example of it implementing a group/item composite tree very similar to your problem.
Basically, you would define the schema of your tree:
const schema = {
group: {
parentGroupId: { type: 'group', cardinality: 'one', reciprocal: 'childGroupIds' },
childGroupIds: { type: 'group', cardinality: 'many', reciprocal: 'parentGroupId' },
itemIds: { type: 'item', cardinality: 'many', reciprocal: 'groupId' }
},
item: {
groupId: { type: 'group', cardinality: 'one', reciprocal: 'itemIds' }
}
};
Then pass it into the library's top-level function:
import normalizedSlice from 'normalized-reducer';
export const {
emptyState,
actionCreators,
reducer,
selectors,
actionTypes,
} = normalizedSlice(schema);
Then wire up the reducer into your app (works with both React useReducer and the Redux store reducers), and use the selectors and actionCreators to read and write state.

How do I print certain elements of a struct in Swift?

I am trying to create a collection of car makes and models. I would like to be able to print either all the makes within my collection or all the models within my collection in Swift. Thanks in advance.
I have been able to create a small collection of car makes and models but I am struggling to work out the final part of printing certain parts of it.
struct Section {
var make: String!
var model: [String]!
}
var Cars = [
Section(make: "BMW", model: ["A","B","C"]),
Section(make: "Ford", mode: ["D","E","F"])
]
//Print a list of all makes
//Print a list of all models
There are many ways to do this.
You can use for loops:
// all makes
for car in Cars {
print(car.make)
}
// all models
for car in Cars {
for model in car.models {
print(model)
}
}
Or you can use higher-order functions like map and flatMap:
// all makes
print(Cars.map { $0.make })
// all models
print(Cars.flatMap { $0.models })

RethinkDB Update the element in the nested array

{
id: "a",
deck_list: [{
name: 'Deck1',
job: 'mage',
cards: []
}],
match: []
}
Hi I am trying to make a DB for card game Decks. In 'deck_list', there are list of decks that created by users. Whenever user adds a new deck, then it would be inserted into deck_list.
However, when the name of the deck is already there, then the deck should be updated, rather than inserted.
Ex. If some deck named 'Deck2' is inserted, then it should be added to form
{
id: "a",
deck_list: [{
name: 'Deck1',
job: 'mage',
cards: []
},
{
name: 'Deck2',
job: 'mage',
cards: []
}],
match: []
}
But when 'Deck1' is added, then old 'Deck1' should be replaced with newer 'Deck1'.
You probably want to make deck_list an object rather than an array, and map from the name of the deck to its job/cards. Then you can use update normally, and it will create the deck if it doesn't exist or update it if it does.

Backbone: Creating models from a Collection of Models that contain a Collection of Models

I have an API that is producing GeoJSON data of a number of Venues and Events that are occurring at each Venue.
See an example output:
{
"crs":null,
"type":"FeatureCollection",
"features":[
{
"geometry":{
"type":"Point",
"coordinates":[
-122.330056,
47.603828
]
},
"type":"Feature",
"id":39,
"properties":{
"city_slug":"seattle",
"neighborhood_name":"Downtown",
"events__all":[
{
"category__category":"Gallery",
"eventid":16200847,
"description":"A Wider View, curated by Onyx Fine Arts Collective, features 60 works by 23 artists of African descent.",
"title":"A Wider View",
"cost":"Free",
"category__slug":"gallery",
"slug":"a-wider-view"
}
],
"venue_name":"City Hall Lobby Gallery",
"venue_address":"600 4th Avenue, Seattle, WA 98104, USA",
"city_name":"Seattle",
"neighborhood_slug":"downtown",
"venue_slug":"city-hall-lobby-gallery"
}
},
{
"geometry":{
"type":"Point",
"coordinates":[
-122.348512,
47.6217233
]
},
"type":"Feature",
"id":42,
"properties":{
"city_slug":"seattle",
"neighborhood_name":"Downtown",
"events__all":[
{
"category__category":"Museums",
"eventid":15455000,
"description":"The Art of Video Games tackles a 40-year history, with a focus on video game as art form. Nerdy heartstrings will be tugged in this nostalgia-inducing retrospective, including everything from the Atari VCS to Playstation 3.",
"title":"The Art of Video Games",
"cost":"$20",
"category__slug":"museums",
"slug":"the-art-of-video-games"
},
{
"category__category":"Museums",
"eventid":15213972,
"description":"There's just something about the black leather jacket. It's a garment that invariably comes with context, that cannot help but be an icon. Worn to Be Wild: The Black Leather Jacket explores the evolution of the leather jacket from \"protective gear to revolutionary garb.\"",
"title":"Worn to Be Wild: The Black Leather Jacket",
"cost":"$20",
"category__slug":"museums",
"slug":"worn-to-be-wild-the-black-leather-jacket"
}
],
"venue_name":"Experience Music Project | Science Fiction Museum.",
"venue_address":"325 5th Avenue North, Seattle, WA 98109, USA",
"city_name":"Seattle",
"neighborhood_slug":"downtown",
"venue_slug":"experience-music-project-science-fiction-museum"
}
}
],
"bbox":[
-122.348512,
47.6035448,
-122.3233742,
47.6217233
]
}
I want to map this into a Collection called VenueEvents. VenueEvents contains models called JsonVenues, and each of these Venues then have contain a collection called EventSet, containing a number of Event models (side topic: is naming a model 'Event' a recipe for disaster?).
My models are outlined as such:
var Event = Backbone.Model.extend({
parse: function(response){
return {
id: response.eventid,
slug: response.slug,
title: repsonse.title,
description: response.description,
category: response.category__category,
cost: response.cost
}
}
});
var EventSet = Backbone.Collection.extend({
model: Event,
}
});
var JsonVenue = Backbone.Model.extend({
initialize: function(attributes) {
console.log(attributes)
},
parse: function(response){
// var eventSet = new EventSet(response.properties.events__all);
return {
name: response.properties.venue_name,
address: response.properties.venue_address,
neighborhood: response.properties.neighborhood_name,
//eventSet: eventSet
}
}
});
// Is this actually a model?
var VenueEvents = Backbone.Collection.extend({
model: JsonVenue,
url: '/json/',
parse: function(response){
return response.features;
}
});
The VenueEvents and JsonVenue objects get created as expected, with the exception that the response.properties.events__all object doesn't seem to make it's way to the JsonVenue model (which is where I'd expect to use it to create the EventSet collection). I've put a console.log(attributes) in the initialize parameter of the JsonVenue object and it shows that while all the other values within features.properties of a JsonVenue make its way to the model, the events__all does not.
Is there any reason why this would be happening? Is this method of loading nested JSON data into models even possible? In most examples, people are only including the id of the nested object in their JSON output, and then (I assume) building a model out of that object in another JSON string and relating them based on the ID. This seems like it would require more traffic between the server and client. I also see people side-loading data, is this the recommended method of relating models in a single API call?
Thanks!
Well.. Ive just tried your code, using:
new VenueEvents(json, {parse: true});
to create your collection. And... it works just fine it seems...
Still, Backbone-relational might have the behavior you want to simplify your code (this is just an assumption, I've never tested it myself, nor have had a real look at it).

Resources