0

I'm create interfaces for some returns in my API The page works fine, but in console show many errors "Cannot read property "example" of undefined" My error dont are the same of javascript, because I return data in typescript and this error show only because the angular interpolation

I tried to make diferent interfaces, with help of some devs But the error never die

Interface:

export interface Banner {
  ds_Imagem: string;
  ds_titulo: string;
}

banner.component.html

<div id="inicio">


  <div class="carousel" style="min-height: 43vh">

    <a [style.backgroundImage]="'url('+ banner[0]?.ds_Imagem +')'" class="carousel-item" href="{{banner[0].ds_link}}" style="width: 100vw; min-height: 43vh;
      background-repeat: space; background-size: 100% 100%;">
      <div class="textoCentral">
        <span>{{banner[0]?.ds_titulo}}</span>
      </div>
    </a>

    <a [style.backgroundImage]="'url('+ banner[1].ds_Imagem +')'" class="carousel-item" href="{{banner[1].ds_link}}" style="width: 100vw; min-height: 43vh;
      background-repeat: space; background-size: 100% 100%;">
      <div class="textoCentral">
        <span>{{banner[1]?.ds_titulo}}</span>
      </div>
    </a>

    <a [style.backgroundImage]="'url('+ banner[2].ds_Imagem +')'" class="carousel-item" href="{{banner[2].ds_link}}" style="width: 100vw; min-height: 43vh;
      background-repeat: space; background-size: 100% 100%;">
      <div class="textoCentral">
        <span>{{banner[2]?.ds_titulo}}</span>
      </div>
    </a>

  </div>
</div>

Error:

ERROR TypeError: Cannot read property '0' of undefined
    at Object.eval [as updateRenderer] (SLIDERComponent.html:6)
    at Object.debugUpdateRenderer [as updateRenderer] (core.js:23937)
    at checkAndUpdateView (core.js:23312)
    at callViewAction (core.js:23548)
    at execComponentViewsAction (core.js:23490)
    at checkAndUpdateView (core.js:23313)
    at callViewAction (core.js:23548)
    at execComponentViewsAction (core.js:23490)
    at checkAndUpdateView (core.js:23313)
    at callWithDebugContext (core.js:24177)

Object from API

[
{
ds_Imagem: "http://gtw4.ska.com.br/desk_target_magnus/Files/bannertarget-06.png",
ds_titulo: null
},
{
ds_Imagem: "http://gtw4.ska.com.br/desk_target_magnus/Files/Unimed-Banner.png",
ds_titulo: null
},
{
ds_Imagem: "http://gtw4.ska.com.br/desk_target_magnus/Files/setembro-amarelo_2019092603245511.png",
ds_titulo: null
}
]

Banner Service

@Injectable({
  providedIn: 'root'
})
export class BannerService {

  private readonly api = 'http://gtw4.ska.com.br:5007/Banner';

  constructor(private http: HttpClient) {
  }

  list() {
    return this.http.get<Banner[]>(this.api)
      .pipe(
        tap(console.log)
      );
  }
}

banner.component.ts

export class SLIDERComponent implements OnInit {

  banner: Banner[] = [];
  //banner$: Observable<Banner[]>;
  constructor(private service: BannerService) {
  }

  ngOnInit() {
    // this.banner = this.service.list();
    this.service.list()
      .subscribe(dados => this.banner = dados);
  }

}
W311
  • 11
  • 2

3 Answers3

1

I would try

public banners:Banner[] = undefined;

list():void {
    this.http.get<Banner[]>(this.api).subscribe(
      (data) => this.banners = data,
      (err) => console.log(err)
    )
}

then in your html you could do something like

<a *ngIf="banners != undefined">
    <span>{{banners[0].ds_titulo}}</span>
</a>

you could also use the service which returns the observable and then subscribe into your component

JSmith
  • 4,519
  • 4
  • 29
  • 45
1

If it appears at the runtime, then it's not an interface problem and it's not a TypeScript problem, it's that you're trying to access a property of undefined object. Before accessing banner[0].someProperty make sure that banner exists and that banner[0] exists:

<ng-container *ngIf="banner?.length">
    <a [style.backgroundImage]="'url('+ banner[0].ds_Imagem +')'">
...
mbojko
  • 13,503
  • 1
  • 16
  • 26
  • If it did not exist, it would not appear on the screen. Right? But the information is passed correctly to the screen. Everything looks fine, but these errors continue on the console. – W311 Oct 02 '19 at 14:38
  • These errors are from _before_ `banner` is populated with data. A check will protect you from that (and possibly from Angular messing up the view in an unexpected way - BTDT...) – mbojko Oct 02 '19 at 14:39
  • What check I can make? – W311 Oct 02 '19 at 14:42
  • This `*ngIf` in my answer. – mbojko Oct 02 '19 at 14:42
  • If i use *ngIf banner[0] no have changes, and the error is the same And if I use *ngIf banner.lenght, dont show anything on screen and in console I receive "SLIDERComponent.html:4 ERROR TypeError: Cannot read property 'length' of undefined" – W311 Oct 02 '19 at 14:46
  • It's `"banner?.length"`. With the `?` safe navigation operator. Again, to avoid accessing a property of _undefined_. – mbojko Oct 02 '19 at 14:47
  • The error goes away, but does not display anything on the screen. – W311 Oct 02 '19 at 14:51
  • Nothing appears because you dont have nothing to show. – Ricardo Ferreira Oct 02 '19 at 15:57
  • How not? If I using banner[0] works, but banner without [0] is undefined. I dont understand this – W311 Oct 02 '19 at 16:04
0

Add a template property check using the "?" before access your property:

.link {
 width: 100vw;
 min-height: 43vh;
 background-repeat: space;
 background-size: 100% 100%;
}
<a [style.backgroundImage]="'url(' + banner[0]?.ds_Imagem +')'"
   class="carousel-item link"
   href="#">
  <div class="textoCentral">
    <span>{{banner[0]?.ds_titulo}}</span>
  </div>
</a>

Edition

you must also to set the banner to an empty array as default value before you set from the api.

banner: Banner[] = [];