What could be causing the variable in my Angular application, written in typescript, not to update within a function?

I'm encountering a peculiar issue.

Within my CategoryComponent component, I have a variable in scope as follows:

@Input() category: CategoryModel;

Whenever I perform a simple post request using a service and receive data back, I modify this variable. To achieve this, I created a function:

if (category.uploading) {
  this.checkMedia(this.category, this.module);
}

Within the checkMedia function, I implement the following logic:

checkMedia(model: any, module: String) {
    let counter = 0;
    var refreshIntervalId = setInterval(() => {
      const service =
        model instanceof CategoryModel
          ? this.categoryService
          : this.foodService;
      service
        .hasMedia(model)
        .pipe(
          switchMap((hasMedia) => {
            if (hasMedia) {
              return service.show(model, module);
            }
            return of(undefined);
          }),
          catchError((_) => {
            clearInterval(refreshIntervalId);
            return of(undefined);
          })
        )
        .subscribe(
          (newModel) => {
            if (newModel) {
              if(newModel.hasMedia) {
                model.hasMedia = newModel.hasMedia;
                model.images = newModel.images;
                model.uploading = false;
                console.log(model);
                console.log(this.category);
                clearInterval(refreshIntervalId);
                this.cd.detectChanges();
              }
            }
          },
          (_) => {
            clearInterval(refreshIntervalId);
          }
        );
      counter++;
      if (counter == 3) {
        if (refreshIntervalId) {
          model.uploading = false;
          clearInterval(refreshIntervalId);
          this.cd.detectChanges();
        }
      }
    }, 8000);
  }

However, I am puzzled by the fact that when I make changes within this section:

        model.hasMedia = newModel.hasMedia;
        model.images = newModel.images;
        model.uploading = false;
        console.log(model);
        console.log(this.category);
        clearInterval(refreshIntervalId);
        this.cd.detectChanges();

The changes only reflect on the screen when I directly reference the specific variable like this.category.name = "TESTE";. However, when I use it with the parameter model:any, the global variable appears to be updated according to console.log(), but the desired state is not reflected on the front end. Why does this discrepancy occur?

Answer №1

THE MAIN ISSUE

I am confused about your approach with the model. Why are you not utilizing this.model? It seems like you should be referencing the model in your HTML and updating a class member variable like so: this.model = {blah-blah-blah}. Have you declared a public property for the model in your class? Why is it not being updated? Make sure to declare the following in your class:

@Input() category: CategoryModel;
model: any;

Then in your code:

this.model = something

And in your HTML:

{{ model | json }}

OTHER POSSIBLE ISSUES

What change detection strategy are you using? OnPush or default? Avoid object mutation as it may prevent change detection from triggering. To resolve this, consider adding the following line:

model.hasMedia = newModel.hasMedia;
model.images = newModel.images;
model.uploading = false;
model = {...model}; // creates a new object reference triggering Angular change detection

OR

import {cloneDeep} from 'lodash-es';

model.hasMedia = newModel.hasMedia;
model.images = newModel.images;
model.uploading = false;
model = cloneDeep(model); // creates a new object reference triggering Angular change detection

In my opinion, the second approach is more clear. Let me know if it resolves your issue. Good luck!

This is mutating the object (NOT RECOMMENDED):

model.hasMedia = newModel.hasMedia;
model.images = newModel.images;
model.uploading = false;

This is NOT mutating the object (RECOMMENDED):

model = {
  ...model,
  hasMedia: newModel.hasMedia,
  images: newModel.images,
  uploading: false
}

REVISED... USING RETURN VALUES

this.checkMedia(this.category, this.module).then((cat) => {
  this.category = cat;
});

Remember to return a value from checkMedia

checkMedia(model: any, module: String): Promise<any> {
  return new Promise((resolve) => {
    // your existing code
    resolve(model)
  })
}

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

Navigating with Conditions in Angular 2

I have two main components in my Angular application - Home and Login. The Login component serves as the default page, and once a user logs in, I want them to navigate to the Home component. Within my app.router.ts file, the routing configuration is set u ...

Ensuring ES module exports are statically type checked in TypeScript

Can TypeScript handle static type checking for ES module exports in the following code snippet? // file.ts export const x = 4 export const y = 'whatever' export const foo = () => 2 // The interface describes what the module exports interf ...

The firebase-generated observable is causing the notorious differ error as it is not iterable

Hey there, I'm encountering an issue that's preventing the route from rendering correctly. I initially thought that unwrapping an observable into an iterable using the async pipe would solve it, but this error indicates otherwise. Sometimes obser ...

What is the preferred method for validating an Angular form - ng-model or form input name?

When it comes to validating an input field and providing feedback, there are two methods that I have noticed: <form name="myform" ng-submit="myform && myFunc()"> <input name="foo" ng-model="foo" ...

Exploring the attrTween function in Angular with D3 insights

I'm currently trying to grasp the concept of utilizing the function attrTween in D3. My goal is to create a pie-chart using the example found at http://bl.ocks.org/mbostock/5100636. However, I've encountered some challenges when it comes to the ...

Adjusting the ng-turnstile Dimensions

Looking for a way to adjust the width of CloudFlare Turnstile to match its parent container's layout without causing any issues with the Iframe. Is there a more efficient method to achieve this? The current solution I have seems to be messy: import { ...

Angular 2 is throwing an error because it is unable to access the property 'comments' of an undefined value

After ensuring that all {{article.}} properties are functioning properly and displaying correctly on the webpage, there seems to be an issue with article.comments (located at the bottom of the HTML) showing as undefined even though it is the input for the ...

Enhancing the Appearance of Input Range Elements with Bootstrap 5 and Angular

Currently, I am facing a challenge in changing the color of the thumb slider in a Bootstrap 5 range control. Despite my efforts, I have not yet discovered the right combination to achieve this. If you would like to take a look, here is the link to the Sta ...

Error: The configuration property is not defined, causing a TypeError at Class.run ~/node_modules/angular-cli/tasks/serve.js on line 22

I'm encountering a persistent error on my production server that indicates a missing angular.json file, even though the file is present in the root of my project! Every time I run npm start, npm build, or npm test, I receive the same error message. ...

Can one obtain a public IP address using Typescript without relying on third-party links?

Though this question has been asked before, I am currently working on an Angular 4 application where I need to retrieve the public IP address of the user's system. I have searched on Stackoverflow for references, but most posts suggest consuming a th ...

Enhancing many-to-many relationships with additional fields in Objection.js

I have a question that I haven't been able to find a clear answer to in the objection.js documentation. In my scenario, I have two Models: export class Language extends BaseId { name: string; static tableName = 'Languages'; st ...

Angular Material sidebar small version with dropdown menus

I am currently using Angular 5 in conjunction with Material design. My application features a side navigation menu with an angular material navigation drawer mini variant, where the items are hidden, leaving only the icons when collapsed (see image). My g ...

The required property 'intersect' is not found in the type 'import("cesium").BoundingSphere'

Incorporating Cesium into a ReactJs application has been my recent project. I have successfully displayed various factories in the cesium viewer and drawn polygon grids on their coordinates. However, I am encountering confusion with one particular aspect. ...

Node.js is known for automatically adding double quotes to strings. However, is there a way to eliminate them?

After creating a unit test, I noticed that both logics I used led to the same issue. Logic 1: describe('aresFileCopier', () => { test('log error', async () => { await registerDB('ares-test', { client: ' ...

How will the presence of @types/react impact the higher-level files in my project?

https://i.sstatic.net/TfsLf.png https://i.sstatic.net/RqmMS.png Here is the structure of my directories vue node_modules src react_app node_modules @types/react package.json ...other file package.json Why does the presenc ...

Scroll horizontally based on mouse movement

My angular directive that enables me to choose the content of table cells is performing as expected. However, I encountered an issue when attempting to select multiple cells at once - the scrollbar does not move, hindering my ability to select the cells. ...

tips for managing response time in firebase authentication state

I've been facing an issue with my web application in efficiently checking if it is firebase authenticated. The 'auth state object' doesn't seem to be functioning correctly on my template, as the expected sections are not appearing at al ...

Implementing Authorization keys in Angular's Swagger UI using code

I am currently in the process of integrating swagger ui into an Angular 7 application. Utilizing the npm package swagger-ui 3.37, the API documentation is structured with swagger 2.0. The integration works smoothly when authorization is not required within ...

Problems with the zoom functionality for images on canvas within Angular

Encountering a challenge with zooming in and out of an image displayed on canvas. The goal is to enable users to draw rectangles on the image, which is currently functioning well. However, implementing zoom functionality has presented the following issue: ...

Find out if a dynamically imported component has finished loading in Nextjs

Here is a simplified version of my current situation import React, { useState } from 'react'; import dynamic from 'next/dynamic'; const DynamicImportedComponent = dynamic(() => import('Foo/baz'), { ssr: false, loading ...