Asked  9 Months ago    Answers:  5   Viewed   183 times

My component

export class MoviedetailComponent implements OnInit {
 movie:any

 constructor(
  private getmovie: GetmovieService,
  private router: Router,
  private rout: ActivatedRoute
 ) { }

 ngOnInit() {
   this.rout.params
   .switchMap((params: Params) => 
   this.getmovie.getMovieById(+params['id']))
   .subscribe(movie => {
    this.movie = movie;
    console.log(this.movie);
 });

 }

}

my html

<p>{{movie.title}}</p>

So when I load the page, it shows the content of movie.tittle, but there is also an error in console saying "Cannot read property 'title' of undefined"

Any ideas?

 Answers

2

The subscribe() function is asynchronous, meaning the code inside of the callback (including this.movie = movie) can be executed after the completion of the ngOnInit() method.

As @kirk and @jonrsharpe pointed out in the comments, you could add a test before the value inside of the template. But this is not the most elegant solution.

I would suggest instead reading up on Observables, and in particular, the async pipe. This makes your code a lot simpler:

this.movie = this.route.params
  .switchMap((params: Params) => 
      this.getmovie.getMovieById(+params['id']))

and then your HTML would look like:

<p>{{ (movie | async)?.title }}</a>

Note the ?- this checks that the title property actually exists, so that an error doesn't occur if the object is invalid. You should also add a template block somewhere else which handles cases of errors.

Friday, September 3, 2021
 
spassen
 
4

The variable selectedHero is null in the template so you cannot bind selectedHero.name as is. You need to use the elvis operator ?. for this case:

<input [ngModel]="selectedHero?.name" (ngModelChange)="selectedHero.name = $event" />

The separation of the [(ngModel)] into [ngModel] and (ngModelChange) is also needed because you can't assign to an expression that uses the elvis operator.

I also think you mean to use:

<h2>{{selectedHero?.name}} details!</h2>

instead of:

<h2>{{hero.name}} details!</h2>
Tuesday, June 1, 2021
 
2

Thats kinda tricky to explain:

Date is a class, this means that values of type Date need to be created through a constructor call. In other words, create a class instance with new Date(...).

The Response.json method will only return an object in JSON format, and such doesnt contain an instance of any class, only maps of key:property.

So what you need to do, is to manually convert the value returned from .json() to a Base object. This can be done as follows:

public getSingle = (keys: any[]): Observable<Badge> => {
        return this._http.get(this.actionUrl + this.getKeysUrl(keys))
            .map(r => r.json())
            .map(v => <Badge>{
              badgeNumber: v.badgeNumber,
              authorizationLevel: v.authorizationLevel,
              endOfValidity: new Date(v.endOfValidity)
              // preferably this string should be in ISO-8601 format
             })
            //the mapping step can be done in other ways most likely
            .catch(this.handleError);
}
Saturday, June 26, 2021
 
EastSw
 
2

The error is very clear and specific

Error: Cannot call a namespace ('moment') at error (/Users/chris/angular-library/node_modules/rollup/dist/rollup.js:185:14)

This is per the ES Module Specification.

That means the following is an invalid way to import moment, or anything you intend to call, because a module namespace object, such as that created by * as ns may not be called.

import * as moment from 'moment';

The correct form is the form that ngc is raising an error on

import moment from 'moment';

Firstly to make this work, you need to specify the --allowSyntheticDefaultImports flag.

tsconfig.json

{
  "compilerOptions": {
    "allowSyntheticDefaultImports": true
  }
}

Assuming that ngc will recognize the option, you still have an additional problem to work out.

The flag above is for users of tools such as SystemJS or Webpack which perform the synthesis, allowing such code to typecheck.

As of TypeScript 2.7, you can now specify the --esModuleInterop flag to have the language provide the synthesis as part of the transpilation process.

{
  "compilerOptions": {
    "allowSyntheticDefaultImports": true,
    "esModuleInterop": true
  }
}

Note that if you are using a version of TypeScript prior to 2.7 and if you are compiling to CommonJS, AMD, or UMD modules (e.g. with --module commonjs) the correct import syntax is rather

import moment = require('moment');

The import = require syntax is a TypeScript specific construct, now largely unnecessary. It exists to acquire both the type and the value of the module exports of an AMD, CommonJS, or UMD module. The "and" is important because a const, var, or let = require invocation only creates a name in the value space not in the type space.

Wednesday, August 4, 2021
 
1

You'll run into this A TON in angular unless you familiarize yourself with the Angular Template Syntax. Specifically the use of the *ngIf and the elvis operator ?.

For example, if you are just wanting to display the title you could do the following to make sure the page doesn't try to render the title until it has one.

<h1 *ngIf="title">{{ title }}</h1>

Furthermore if you have an object with a property you can forgo the *ngIf and check to make sure the object has resolved. For instance let's say you save all of the page's data into the page object and like above, want to display the title.

<h1>{{ page?.title }}</h1>

If you wanted to be really safe, you could still wrap it in an *ngIf statement that checks the title specifically, but usually if you have data within the page object, it's safe to assume there's a title in there.

Wednesday, August 18, 2021
 
maerics
 
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :  
Share