Troubleshooting: Why is the Array in Object not populated with values when passed during Angular App instantiation?

While working on my Angular application, I encountered an issue with deserializing data from an Observable into a custom object array. Despite successfully mapping most fields, one particular field named "listOffices" always appears as an empty array ([]). This is unexpected since it should contain either one or two elements.

The code snippet within the component that handles this mapping involves nested for loops to iterate through the JSON objects and map their values to properties of a new class instance. It seems like the problem lies in Closure, as I can see the correct values for "officeval" when logged before assigning them to the object.

Although I am aware that performing this deserialization logic within the service might be cleaner, I don't believe it's the cause of the issue. Once I resolve this bug, I plan to refactor the code accordingly.

Below is the method in my component responsible for the subscription:

getContracts() {

  this.contractService.getContracts().subscribe(
    (res) => {

        let officeval = new Array<string>();

        for (var x = 0; x < res.length; x++) {
          for (var z = 0; z < res[x].length; z++) {
             if (res[x][z].resources.office !== undefined){
               for (var a = 0; a < res[x][z].resources.office.values.length; a++) {
                 officeval.push(res[x][z].resources.office.values[a]);
               }
             }
            else {
                  officeval.push("Not a Hive Policy");
                 }

            this.createContract(res[x][z].id, res[x][z].name,"placeholder for type",res[x][z].isEnabled, res[x][z].service,
            officeval, ["q", "w"], ["q", "w"],["q", "w"], ["q", "w"],["q","r"]);

          } console.log(this.contractsList);       
    }
  },
    (err) => console.log(err))
  console.log("logging contracts");
  }

  createContract(id:number, contractName:string, type:string, isEnabled:boolean,
     service:string, listOffices:string[], listRooms:string[],
     listSeats:string[], contractItemsEntries:string[], contractItemsOwners:string[], contractItemsSessions:string[]) {

    this.contractsList.push (new Contract (id, contractName, type, isEnabled,
     service, listOffices, listRooms,
    listSeats, contractItemsEntries, contractItemsOwners, contractItemsSessions ));

  }
}

In the Chrome console, the output sometimes looks like this:

[Contract, Contract, Contract...] x6 
-opened Contract Array:
0:Contact
1:Contract
2:Contract
...
-opened Contract:
listOffices: Array(0) -- ???
listRooms: Array(2) --contain correct values
listSeats: Array(2) --contain correct values
id:1
isEnabled: true
service: contractService
type: "placeholder for type"

Answer №1

We have limited information about your res object, so it's important to verify that

res[x][z].resources.office.values.length > 0

This may be the sole scenario where your officeVal is not populated. (As there is no loop present)

Therefore, I am inclined to believe this is the case.

Answer №2

Upon reviewing the code, it is evident that office.values should have a length of 0, indicating that nothing is being added to it and therefore remains as an Array with a length of 0. To confirm this, please provide the JSON data returned from the getContracts function.

Furthermore, when populating items into the officeval Array, you may observe that it contains more items than expected due to not clearing out officeval in each iteration of the loop. While this could be intentional, my assumption is that it is unintentional.

Answer №3

The primary root cause of the issue stemmed from:

  1. Failure to recognize that javascript passes complex data types by reference (please refer to this insightful article) (I found valuable guidance on addressing pass by value versus pass by reference in these posts: post one, post two)
  2. Omission of resetting the officeval array to 0 after each iteration of the inner for loop

To rectify the situation, I took the following steps:

  1. Repositioned the declaration of the officeval array outside of the outer function to enable reference within the inner function using the this keyword
  2. Utilized the slice method to generate a copy of officeval by value, which was then passed into the inner function for creating new contracts and appending them to the contractsList array.
  3. Immediately reset the value of officeval after adding a new contract to the contractsList.

Below presents the revised version of the code:

officeval: string[] = []

getContracts() {

  this.contractService.getContracts().subscribe(
    (res) => {

        //let officeval = new Array<string>();

        for (var x = 0; x < res.length; x++) {
          for (var z = 0; z < res[x].length; z++) {
             if (res[x][z].resources.office !== undefined){
               for (var a = 0; a < res[x][z].resources.office.values.length; a++) {
                 officeval.push(res[x][z].resources.office.values[a]);
               }
             }
            else {
                  officeval.push("Not a Hive Policy");
                 }

            var testArray = this.officeval.slice(0);

            this.createContract(res[x][z].id, res[x][z].name,"placeholder for type",res[x][z].isEnabled, res[x][z].service,
            testArray, ["q", "w"], ["q", "w"],["q", "w"], ["q", "w"],["q","r"]);

          } console.log(this.contractsList);       
    }
  },
    (err) => console.log(err))
  console.log("logging contracts");
  }

  createContract(id:number, contractName:string, type:string, isEnabled:boolean,
     service:string, listOffices:string[], listRooms:string[],
     listSeats:string[], contractItemsEntries:string[], contractItemsOwners:string[], contractItemsSessions:string[]) {

    this.contractsList.push (new Contract (id, contractName, type, isEnabled,
     service, listOffices, listRooms,
    listSeats, contractItemsEntries, contractItemsOwners, contractItemsSessions ));

    this.offiveval.length = 0;

  }
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Validate that a string is a correct file name and path in Angular without using regular expressions

Currently, I am using regex to determine if a string is a valid file name and path. However, when the string length becomes longer, it ends up consuming a significant amount of CPU, resulting in browser performance issues. public static readonly INVALID_F ...

What causes Angular to consistently redirect to the homepage?

Whenever I attempt to access the '/' route, it consistently displays the static-root-component (the main page component). However, if I try to access the '/welcome' route, it immediately redirects back to '/' and loads the sta ...

Introduce a specialized hierarchical data structure known as a nested Record type, which progressively ref

In my system, the permissions are defined as an array of strings: const stringVals = [ 'create:user', 'update:user', 'delete:user', 'create:document', 'update:document', 'delete:document&ap ...

Nesting objects within arrays using Typescript Generics

Hello, I am currently attempting to assign the correct type to an object with nested values. Here is a link to the code in the sandbox: https://codesandbox.io/s/0tftsf interface Product { name: string, id: number productList?:ProductItem[] } interf ...

ngx-translate-multi-http-loader: An error occurred while trying to load the specified translation file

While working on my Ionic 5 App, I decided to use the library ngx-translate-multi-http-loader in order to load multiple language files. Even though there were no errors, I encountered an issue where the translations were not functioning properly. To reso ...

Exploring nested promises in TypeScript and Angular 2

I have a method called fallbackToLocalDBfileOrLocalStorageDB, which returns a promise and calls another method named getDBfileXHR, also returning a promise. In the code snippet provided, I am unsure whether I need to use 'resolve()' explicitly o ...

After migrating from Angular 11 to Angular 12, I am facing issues with compiling my project using optimization parameters

Recently, I upgraded an environment using nrwl from angular version 11 to 12 including two angular applications and multiple libraries. Upon updating, I encountered an issue when trying to compile with optimization settings: angular.json { .... "op ...

Retrieving the innerHTML or innerText of a structural DOM element generated by *ngFor in Selenium

Having trouble accessing the innerHTML/innerText of a structural DOM element, only getting a commented element instead of the child elements. <div class="snap-box"> <label class="snap-heading">Recommendations</label> <div class="r ...

Ag-grid allows for the creation of multiple individual detail grids that are connected to a single

I noticed in the ag-grid documentation that all the master/detail examples feature only a single detail grid implementation. Is it possible to incorporate multiple (different) detail grids within one master grid, specifically in one row? ...

Access to Firebase using Google authentication is currently restricted (permission denied)

Currently, I am utilizing Firebase to authenticate users with Google in my Angular project, "project1." When signing anonymously into Firebase, everything runs smoothly. However, if I attempt to sign in with Google using the popup feature, an error occurs: ...

Verify role declarations and display components if valid

I am currently developing an application using Angular on the front-end and ASP.NET on the back-end. Within this application, there are two roles: user and admin. I have implemented a navigation bar with several buttons that I need to hide based on the use ...

Is there a way to reset useQuery cache from a different component?

I am facing an issue with my parent component attempting to invalidate the query cache of a child component: const Child = () => { const { data } = useQuery('queryKey', () => fetch('something')) return <Text>{data}& ...

Unpacking the information in React

My goal is to destructure coinsData so I can access the id globally and iterate through the data elsewhere. However, I am facing an issue with TypeScript on exporting CoinProvider: Type '({ children }: { children?: ReactNode; }) => void' is no ...

How to easily switch between multiple side navigation menus using Angular 4

Below is the structure of my components: app --app.component.html --app.component.ts -dashboard --dashboard.component.html --dashboard.component.ts -sales --sales.component.html --sales.component.ts -taxreports --taxreports.c ...

Visibility in classes can shift once a new file is imported

Currently, I am encountering a puzzling issue in my angular2 project using typescript. In my main.ts file, which contains a component along with some imports at the start of the file, there is a custom type class (let's call it TypeFoo) located in mod ...

Customizing Material UI CSS in Angular: A Guide

Recently, while working with the Mat-grid-tile tag, I noticed that it utilizes a css class called .mat-grid-tile-content, which you can see below. The issue I am encountering is that the content within the mat-grid-tile tag appears centered, rather than f ...

Is there a way to stop Material UI from dulling the color of my AppBar when using dark mode in my theme?

When I use mode: "dark" in my Material UI theme, it causes the color of my AppBar to become desaturated. Switching it to mode: "light" resolves this issue. This is how my theme is configured: const theme = createTheme({ palette: { ...

A guide on obtaining the date format according to locale using Intl.DateTimeFormat within JavaScript

Can someone assist me in obtaining the standard date format (such as MM/DD/YYYY) based on a specified local id? The code snippet provided below is not returning the desired format. Any guidance on how to achieve this would be greatly appreciated. var da ...

How to trigger a component programmatically in Angular 6

Whenever I hover over an <li> tag, I want to trigger a function that will execute a detailed component. findId(id:number){ console.log(id) } While this function is executing, it should send the id to the following component: export class ...

Typescript: Subscribed information mysteriously disappeared

[ Voting to avoid putting everything inside ngOnit because I need to reuse the API response and model array in multiple functions. Need a way to reuse without cluttering up ngOnInit. I could simply call subscribe repeatedly in each function to solve the p ...