Assigning a value to an angular object

In my current project with Angular 16, I am executing a query on the database and assigning the returned number to a document number.

Data Model

export class Document {
    doc_data: string ="";
    doc_for: string="";
    doc_number: number = 0;
    doc_year: number = 0;
    doc_subject: string = "";
    doc_send: number = 0;
    doc_employee: number = 0;
}

Service File

number_doc(year: number): any {
    // return the value
    return this.http.get(`${this.url + 'numberdoc'}/${year}`).pipe(
        map((res) => {
        let resInt = +res;
        return resInt;
      })
    );
  }

App Component File


export class AppComponent {
  ...
   doc = new Document();
  ...

 find_number_doc(year: number): number {
    return this.service.number_doc(year).subscribe((res: number) => {
      //this.number_doc = res;
      this.doc_number = res;
      return res;
    });
  }

ngOnInit() {

    //initialization of some properties. I put it more as the shape you are assigning
    this.year = formatDate(new Date(), 'yyyy');
    this.doc.doc_data = formatDate(new Date(), 'dd/MM/yyyy');
    this.doc.doc_year = new Date(), 'yyyy';

}


onClick() {
      ...
      this.find_number_doc(this.year);

      
      this.document.download(this.doc);

}

The issue lies in retrieving the database number and assigning it to the property. The first call to "this.doc_number" passes zero to the child component. Upon a second call, it maintains the previous number instead of updating.

Object -> 0
document.service.ts:47 ---- Object -----
document.service.ts:48 {"doc_data":"02/11/2023","doc_for":"","doc_number":0,"doc_year":2023,"doc_subject":"","doc_send":0,"doc_employee":0}
document.service.ts:179 Blob {size: 8593, type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'}
document.service.ts:181 Document created successfully
app.component: 29 

Although the number 29 should have been passed, zero was erroneously passed.

Further Investigation

Object -> 29
document.service.ts:47 ---- Object  -----
document.service.ts:48 {"docdata":"02/11/2023","doc_for":"","doc_number":29,"doc_year":2023,"doc_subject":"","doc_send":0,"doc_employee":0}
document.service.ts:179 Blob {size: 8594, type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'}
document.service.ts:181 Document created successfully
app.component.ts:131 app.component: 30

Even though the expected outcome was passing the number 30, it passed 29 instead, causing confusion and complexity when attempting to rectify.

30
document.service.ts:47 ---- Object -----
document.service.ts:48 {"doc_data":"02/11/2023","doc_for":"","doc_number":30,"doc_year":2023,"doc_subject":"","doc_send":0,"doc_employee":0}
document.service.ts:179 Blob {size: 8594, type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'}
document.service.ts:181 Document created successfully
app.component.ts:131 app.component: 31 

In this scenario, the intention was to pass the number 31, but 30 was inadvertently passed.

I am striving to efficiently transfer the database value to generate a word document. Despite my efforts to troubleshoot prior to reaching out for help, the resolution remains elusive.

Answer №1

After examining your code, it appears that the function find_number_doc is expected to return a number, but in reality, it returns a Subscription.

Considering that you are using subscribe to call the service function, find_number_doc() should have a return type of void since it does not actually return anything. Also, it would be more appropriate to rename this function to something like setNumberDoc(). If it is named as findSomething(), users may mistakenly expect it to return a value.

If doc_number will eventually receive a value from the backend, there are two ways to manage this scenario:

Reactive Approach

@Component({...})
export class ParentComponent {
  docNumber$!: Observable<number | undefined>;
  
  setDocNumber(year: number): void {
    this.docNumber$ = this.service.number_doc(year);
  }
}
<child-component [theDocumentNumber]="docNumber$ | async"></child-component>

In this approach, manual subscription is avoided by utilizing the async pipe, which automatically handles data changes without concerns about subscriptions. The template HTML reacts to any value modifications.

Imperative Approach

@Component({...})
export class ParentComponent implements OnDestroy {
   docNumber = 0;
   private _sub = new Subscription();

   setDocNumber(year: number): void {
     this._sub.add(
       this.service.number_doc(year).subscribe(res => this.docNumber = res)
     );
   }

   ngOnDestroy(): void {
     this._sub?.unsubscribe();
   }
}
<child-component [theDocumentNumber]="docNumber"></child-component>

In this method, manual subscription to the service observable is required, and managing the subscription is crucial to prevent memory leaks.

A few points to note: In JavaScript/TypeScript, classes, interfaces, types, etc., should start with a capital letter, so export class document should be renamed to export class Document. Additionally, function names should adhere to camelCase convention, such as renaming find_number_doc to findNumberDoc, and functions should be named with a verb for clarity, like getNumberDoc or retrieveNumberDoc.

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

TypeScript utility function that retrieves properties from an interface based on a specified type

Is there a way to create a new object type that includes only properties from another Object that match specific types, as opposed to property names? For example: interface A { a: string; b: number; c: string[]; d: { [key: string]: never }; } int ...

Error: No injection provider found for function(){}!

After countless hours of setting up a custom AOT in Angular 7 project without CLI and debugging, I have encountered the following error: Uncaught Error: StaticInjectorError(Platform: core)[function(){}]: NullInjectorError: No provider for function(){}! ...

After the installation of Storybook, there is a duplicate identifier error that arises with 'LibraryManagedAttributes'

Upon running the command npx storybook@latest init for setting up Storybook, which results in modifying package.json, I encounter an issue where I cannot run the project using npm due to: Error: node_modules/@types/react-dom/node_modules/@types/re ...

Exploring Angular2 Components: Utilizing ViewChild and ContentChild based on class

I am working on creating a flexible component structure that can expand and collapse based on certain conditions: <collapsable [expanded]="myFlag"> <div title>Summary</div> <div alternate-title>Heading</div> <div con ...

Enhancing current interfaces

I'm exploring Koa and the module system in Node.js. Although I'm not asking about a specific koa question, all the code I'm working with involves using koa. In Koa, every request is defined by the Request interface: declare module "koa" { ...

Cross-site request forgery (CSRF) vulnerability spanning multiple applications

I am managing 2 separate applications under the same domain. One is hosted on a PHP 5.6 server with a Laravel 5.2 backend and an Angular2 frontend, while the other is on a PHP 5.3 server with a custom framework and a flat JavaScript frontend. Both applicat ...

"Resulting in 'undefined' due to an asynchronous function call

Encountering an issue with async method implementation. In my authServices, there is a loginWithCredential function which is asynchronous: async loginWithCredential(username, password){ var data = {username: username, password: password}; api.pos ...

Receiving intelligent suggestions for TypeScript interfaces declared within function parameters

Here is a simple example I put together: https://i.sstatic.net/Fdtfa.png In this example, intellisense provides suggestions for the interface of the object named test in the foo function. It works perfectly and I love it! However, if you declare that in ...

How to Modify CSS in Angular 6 for Another Element in ngFor Loop Using Renderer2

I have utilized ngFor to add columns to a table. When a user clicks on a <td>, it triggers a Dialog box to open and return certain values. Using Renderer2, I change the background-color of the selected <td>. Now, based on these returned values, ...

Navigating through an array's contents with RxJs

Is there a more efficient way to iterate over an array fetched from an observable using RxJS operators in order to generate and emit new individual ListingItem objects? onGetItemData(){ this.dataService.getItemData().subscribe((itemData) => { this.it ...

What is the best way to create an array of strings that can include multiple elements from a set of strings?

Exploring different roles for authorization: ['admin', 'manager', 'user'] Is there a way to create a specific type, named Roles, which is essentially a string array ( string[] ) that is limited to only containing values from ...

Fetching data from React Router v6 Navigate

When I navigate to a new route, I am encountering an issue with passing state data in TypeScript. The error message says: Property 'email' does not exist on type 'State'." The parent functional component looks like this: naviga ...

Unleash the power of drag-and-drop functionality with cdkDrop

I am currently tackling a project that requires the implementation of a drop zone functionality where elements can be dragged from a list and dropped in a zone for free movement. I intend to utilize a cdkDropList for the zone due to its comprehensive list ...

Ways to eliminate unnecessary items from a JavaScript object array and generate a fresh array

My JavaScript object array contains the following attributes: [ { active: true conditionText: "Really try not to die. We cannot afford to lose people" conditionType: "CONDITION" id: 12 identifier: "A1" ...

Retrieving the name of the current page in ionViewCanEnter

While working with Ionic 2, I am currently facing a challenge in identifying the name of the page that triggered the navigation (PUSHER) before entering the destination page (PUSHEE). Within the PUSHEE page, I have an ionViewCanEnter function where I need ...

Jasmine Destiny - Error Encountered: macroTask 'setTimeout': unable to switch to 'active' state, expecting 'planned' state, but it was 'notScheduled'

I am currently using Angular 7 with the Zone.js version of approximately ~0.8.26. Inside my test.ts file, I have included the import statement for 'zone.js/dist/zone-testing'. Below is a snippet from my spec file: import { HttpClientTestingModul ...

Error 404 occurs when attempting to retrieve a JSON file using Angular's HTTP

I'm having an issue with my service code. Here is the code snippet: import {Injectable} from '@angular/core'; import {Http, Headers, RequestOptions} from '@angular/http'; import 'rxjs/add/operator/map'; import {Client} f ...

Angular: Understanding Render Delay Caused by *ngIf and Expression Changes from Filters

ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'ngIf: false'. Current value: 'ngIf: true'. Encountering the above error in the console. In my code, I have filters that control ...

Meteor - The dependency specified in [email protected] or [email protected] is unmet

I am facing an issue with my meteor project using angular2. When I try to install the package rxjs5.0.0-beta.11 using 'meteor npm install', it gives me the following message: @angular/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" ...

What is the purpose of running tsc --build without any project references?

Out of curiosity, I decided to experiment by executing tsc --build on a project without any project references. Surprisingly, the command ran smoothly and completed without any issues. I expected there to be a warning or error since the build flag is typic ...