angular: Question: Binding to undefined object produces error, but binding to empty object cast to interface is OK

When I go to the hero details component (see below), I get a binding error briefly in the console because the Hero.name binding fails as the Hero is not yet back from the promise from the http service (however briefly). Makes sense. I prefer not to ngIf things either. So I did this to make the Hero initialize to an object cast to the Hero interface. Should we have to do that?

  hero: Hero = <Hero>{};

and the original code …

import {Component, View} from 'angular2/angular2';
import {RouteParams} from 'angular2/router';
import {Hero} from './hero';
import {HeroService} from './hero-service';
import {HERO_DIRECTIVES} from './hero-directives';

@Component({selector: 'my-hero-detail'})
@View({
  templateUrl: 'app/hero-detail-component.html',
  directives: [HERO_DIRECTIVES]
})
export class HeroDetailComponent {
  hero: Hero; // this is what I changed to cast it

  constructor(private _heroService: HeroService, private _routeParams: RouteParams) {
    let id = +_routeParams.get('id');
    this._heroService.getHero(id).then(hero => this.hero = hero);
  }
}

About this issue

  • Original URL
  • State: closed
  • Created 9 years ago
  • Comments: 19 (11 by maintainers)

Most upvoted comments

I get a binding error briefly in the console because the Hero.name binding fails as the Hero is not yet back from the promise

@johnpapa are you talking about a binding in a template? Sth like {{hero.name}}? If so you can use the Elvis operator - sth like {{hero?.name}}.

Should we have to do that?

Hope that the above answers the question so going to close this one for now. Happy to re-open if more discussion is needed and / or your use-case is different.

I am just curious why this fixes it too hero: Hero = <Hero>{};

Well, assuming that in your template you’ve got sth like {{hero.name}} in a template the hero: Hero = <Hero>{}; line “works” since it initialises the hero field to an empty object instead of null.

I have a input box bound to a property path like so, and the trailing elvis operator is what I need

<input type="text" [value]="path?.to?.mypropertyThatIsANumber" />

and my textbox says “undefined” instead of empty.

I tried adding a .toString() with the elvis operator and it works

<input type="text" [value]="path?.to?.mypropertyThatIsANumber?.toString()" />

in .ts file while declaring object of class type i did below heroes :hero= new hero; that helps me

My two cents @wardbell , the reason why you don’t need the Elvis operator on the name property is because you can parse a null, in the case of Angular, it parses null in the presentation as an empty string, which is a nice behaviour. However you cannot access a property of a null object, that’s why you use the elvis in the parent as a null check shortcut, not as a null parser.

Yes … that discussion explains the Elvis operator.

the html just has a ng-model on the hero. Since it is coming back asyncly, it is not there for a tick, and thus could fail. So the ? would help that. I am just curious why this fixes it too hero: Hero = <Hero>{};