What is the best way to access a value from a service scope in Angular 2?

I am working on an Angular 4 app and have a function to print content. Below is a snippet from my TypeScript file:

print(id) {
// console.log(temp)
this.templateservice.getTemplateById(id).subscribe(template => {
  if (!template.success) {
    this.snackbar.open(template.message, '', {
      duration: 2000,
      extraClasses: ['success-snackbar']
    });
  } else {
    let headContents, innerContents, signContents, popupWin;
    headContents = document.getElementById('head-section').innerHTML;
    innerContents = document.getElementById('inner-section').innerHTML;
    signContents = document.getElementById('sign-section').innerHTML;

    console.log(headContents);
    popupWin = window.open('', '_blank', 'top=0,left=0,height=100%,width=auto');
    console.log(popupWin)
    popupWin.document.open();
    popupWin.document.write('<html><head><style></style></head><body onload="window.print();window.close()"><p class="head">' + headContents + '</p> <p class="inner">' + innerContents + '</p> <p class="sign">' + signContents + '</p></body></html>');
    popupWin.document.close();
  }
});// end of subscribe
}//end of print

And this is part of my HTML file:

<md-tab>
          <ng-template md-tab-label>Outgoing Mail</ng-template>
          <md-card-content >
            <div fxLayout="column" fxLayoutAlign="center center" class="mt-1" >
              <div class="template" style="@page  {size: A4};width: 210mm;height: 297mm;border-width: 2px;border-style: solid;border-color: #e6e6e6;padding-top: 23mm;padding-left: 2cm;padding-right: 2.5cm;padding-bottom: 55mm">
                <p class="head" id="head-section" style="line-height: 1cm;padding-left: 152mm;">Mail Number: {{mail_number}} <br> Date: {{created_at| date:'yyyy MMM dd'}}</p>
                <p class="inner" id="inner-section" style="max-height: 873px;line-height: 25px;word-spacing:1px;text-align: justify;padding-right: 20mm;padding-left: 25mm;padding-top: 21mm;padding-bottom: 5mm;white-space: pre-wrap; width: 166mm; word-wrap: break-word;">{{content}}</p>
                <p class="sign" id="sign-section" style="padding-left: 33mm;padding-right: 147mm ;padding-bottom: 70mm;line-height: 1cm;">Sincerely <br> {{sender}}</p>
              </div>
            </div>
          </md-card-content>
        </md-tab>

Currently, I am encountering an error "cannot read property document of undefined." Moving the print codes outside of the subscribe block does not allow me to access the template returned by the service. When I use console.log(headContents), I get a response. However, when I use console.log(popupwin), I get the image below! The popupWin is null and I receive an error relating to the document.

https://i.sstatic.net/UdK0H.jpg

Answer №1

getTemplateById operates asynchronously. The issue arises because you are logging the output before the observable is resolved. Ensure your operations are executed inside the subscribe function.

data;

print(id) {
    this.templateService.getTemplateById(id).subscribe(temp => {
        if (!temp.success) {
        } else {
            this.data = temp;
            console.log(this.data);

            var printContents = document.getElementById(divName).innerHTML;
            var popupWin = window.open('', '_blank', 'width=300,height=300');
            popupWin.document.open();
            popupWin.document.write('<html><head><link rel="stylesheet" type="text/css" href="style.css" /></head><body onload="window.print()">' + printContents + '</body></html>');
            popupWin.document.close();
        }
    }
}

Answer №2

this.service.getTemplateById(id).subscribe(temp => {
    if (!temp.success) {
        // handle error
    } else {
        this.content = temp;
    }
});
console.log(this.content);

You can retrieve the this.content variable outside of the initial scope, but please note that it may not be immediately available due to the asynchronous nature of getTemplateById function.

Since getTemplateById is asynchronous, the console log statement will execute before the data is retrieved.

Resolution:

print(id){
    this.service.getTemplateById(id).subscribe(temp => {
        if (!temp.success) {
            // handle error
        } else {
            console.log(this.content);
            this.content = temp;
            var printContents = document.getElementById(divName).innerHTML;
            var popupWin = window.open('', '_blank', 'width=300,height=300');
            popupWin.document.open();
            popupWin.document.write('<html><head><link rel="stylesheet" type="text/css" href="style.css" /></head><body onload="window.print()">' + printContents + '</body></html>');
            popupWin.document.close();
        }
    });
}

Answer №3

Implement .finally() in your Observable, Here's how to do it:

this.templateService.getTemplateById(id)
.finally(() => {
      console.log(this.data);
})
.subscribe(temp => {
    if (!temp.success) {
      // handle error
    } else {
      this.data = temp;
    }
  });

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

Support for ViewEncapsulation.ShadowDom now available in Edge, Internet Explorer, and legacy browsers

I am working with Angular 7 and material design. Some of my components utilize ShadowDOM ViewEncapsulation, leading to errors in older versions of IE, Edge, Chrome, and Firefox. Below is the error message I am encountering: Object doesn't support pr ...

Retrieve the content text while handling errors using RxJs

When my Node.js server encounters an error with status 401, it sends out a message: https://i.stack.imgur.com/bOOF3.png https://i.stack.imgur.com/Kcv27.png The code responsible for this is as follows: res.status(401).send('Invalid user or password & ...

Error: When trying to run the `ng build` command in Git Bash, TypeScript module cannot be

When attempting to execute ng build using Git Bash, I encountered this error message, even though I had previously executed npm install -g typescript. Where should I place the typescript installation so that Git can detect it? Error $ npm install -g typ ...

Building SVG components in React with TypeScript and styling them using SCSS

I've been experimenting with using Webpack to import SVG files as components in React Typescript. However, I'm running into trouble when it comes to styling the SVGs with SCSS. I've tried targeting a custom attribute in my CSS selector, but ...

Is it possible to create a tuple with additional properties without needing to cast it to any type?

To accommodate both array and object destructuring, I have defined the following `Result` type: type Errors = Record<string, string | null>; type Result = [Errors, boolean] & { errors: Errors; success: boolean }; I attempted to create a result of t ...

Prevent Promise / Property not found error in Angular2 by Instantiating Class

When working with my "export class", I encountered an issue that led to a Promise error if I didn't include this line of code: purchase = new Purchase(); right before the constructor. The error indicated that the property "name" was not found. Alth ...

What is the best way to bring in a SCSS file within another SCSS file?

When working with SCSS, I find myself using a lot of variables. To keep things organized, I create a separate file that contains all of my SCSS variables. The next step is to import this file into other SCSS files. Here's what I tried: Create a fil ...

The synergy between JSDoc and type mapping

I am in search of a comprehensive and reliable source that provides detailed information on how TypeScript's JSDoc interacts with types, their mappings, and modifications. It is widely known that Pick and Omit maintain the original JSDoc: const any: ...

Angular Elements: the crucial link to Material Dependencies

Currently in the process of developing an Angular Element for integration into various projects. This element will serve as a component housing Angular Material components within its template, necessitating the inclusion of a linked Material theme CSS file ...

Troubleshooting: Angular version 4.3 Interceptor malfunctioning

I have been trying to implement new interceptors in Angular 4.3 to set the authorization header for all requests, but it doesn't seem to be working. I placed a breakpoint inside the interceptor's 'intercept' method, but the browser didn ...

Leveraging Typescript in Firebase Cloud Functions to effectively work with intricate interfaces

When querying a collection on the app side, I am able to automatically cast the result as an interface using Positions constructor that takes in interface IPosition. However, attempting to do the same on the cloud functions side prevents the functions fro ...

Does Vetur have additional undefined types in the type inference of deconstructed props?

When reviewing the code below, Vetur concluded that x,y are of type number | undefined. The presence of undefined is leading to numerous warnings when using x,y further in the code. Is there a way to eliminate the undefined from the type inference? <s ...

Modifying Views on the Fly with Ionic 2

When the toggle button on the page is clicked, the current page view will switch to a different HTML layout. I attempted to modify @Page, but after it loads once, I am unable to change it again. @Page({ templateUrl: isTrue ? 'build/pages/detail/ ...

Is there a way to determine if an npm package is compatible with a specific version of Angular

As I work on my project, I realize that I have many dependencies on libraries that support Angular2 but not Angular6. It can be challenging to determine if a library supports Angular2 from just reading their GitHub pages. One idea is to check the package ...

Encountering a blank page and slow loading when launching the VSCode debugger using VS Code version 1.76.1 and Chrome 111

Recently, I've encountered a problem with the VS Code debugger while trying to debug an Angular application. I created a new Angular app using the ng new command and made some changes to the ngOnInit function. When attempting to start the Chrome deb ...

Convert a TypeScript array of strings to a boolean array: a step-by-step guide

Upon receiving a list of objects from the front end as: item=["false","true"] I proceed to check a column within my records to identify values containing "true" or "false" using the following code: this.records.filter(x=> items.includes(x.column)) Unf ...

Updating form values using ngModel in Angular 6

After upgrading from Angular 5 to 6, I attempted to update my form: In Angular 5, I had: <select [ngModel]="toto" (ngModelChange)="onChange($event)" <option *ngFor="let toto of totos" [ngValue]="toto.id">{{toto.libelle}}</option ...

Guide on transitioning from @ngrx/store syntax version 2.2.1 to the latest version 6.1.2

Need help upgrading the syntax usage of @ngrx/store from version 2.2.1 to version 6.1.2 Upon recently upgrading my Angular project from Angular ^2.0.0 to Angular ^6.0.0 along with related npm plugins, I encountered issues with the usage of @ngrx/store and ...

"Error: Authentication failed in JWT authentication using Node.js/Express due to

I'm encountering an issue with Jwt, specifically the "Invalid Signature" error. After a user logs in, I generate a token using jsonwebtoken: userSchema.methods.generateJwt = function() { var expiry = new Date(); //expiry.setDate(expiry.getDate() ...

Develop an Angular 15 function that generates observables by utilizing local variables

The function being observed is not executed through HTTP; it must be a local function, but still needs to be subscribed to. Below is the implementation I came up with based on online examples: export class AppComponent implements OnInit { title = 'S ...