#replace an (array?) with an http request

114 messages · Page 1 of 1 (latest)

rough loom
#

as title, I have a dropdown menu that get populated automatically instead of having many <option value> (that was my first task to complete), so I completed my first by using this code:

<select cSelect id="idColor" [(ngModel)]="color">
  <option disabled>Choose...</option>
  <option *ngFor="let color of colors" [(ngModel)]="color.idColor">{{color.colorName}}</option>
</select>

Well, I now have a second task to complete, and I'm unable to understand where am I doing wrong, since I didn't familiarised yet with this language bases, I have a generated service .ts file containing this code:

public getColors(): Observable<any> {
    return __request(OpenAPI, this.http, {
        method: 'GET',
        url: '/api/Colors/colors',
    });
}

Well I should use this method getColors() for getting rid of this, since this data should be obtained by an api request:

colors = [
  {
    "idColor": "1",
    "colorName": "White"
  },
  {
    "idColor": "2",
    "colorName": "Yellow"
  },
  {
    "idColor": "3",
    "colorName": "Orange"
  }

Do someone have an idea on how should I proceed?

vague prairie
#
<option *ngFor="let color of colors | async">
rough loom
#

async?

cerulean blaze
#

Instead of assigning the array with colors, you assign the observable returned by the getColors method. Also, provide types for your data, don't use any

colors: Observable<Colors[]> = this.servicename.getColors() 

and in html like Raziel said.

rough loom
#

you mean this should go in the .html file?

cerulean blaze
#

the snippet I posted goes in the component.ts file, where you now have the colors property

rough loom
#

apparently it give me 2 errors:

  • Cannot find name 'Observable'.ts(2304)
  • Property 'servicename' does not exist on type 'mytask'.ts(2339)
#

I guess for the first one I can solve using

import { Observable } from 'rxjs';
cerulean blaze
#

You have to import Observable from rxjs and the servicename was just an example since you never mentioned the name of the service that contains the getColors method

rough loom
#

I thought to replace servicename with the name of the .ts in my case ColorsService.ts but it didn't worked

cerulean blaze
#

have you injected it in your component? ```ts
constructor(private colorsService: ColorsService) {}

#

if you did that, you can use it like this this.colorsService.getColors()

rough loom
#

oh I think I forgot it, I tried to do it reading a past tutorial but I deleted it due to lot of errors, and outdated guide

#

I think the problem is that it does not accept multiple constructors

#

I already have a constructor

cerulean blaze
#

No, you can have only 1 constructor per class

rough loom
#
    constructor(private _sanitizer: DomSanitizer)
  {

  }

Should I add it after this, like an argument?

cerulean blaze
#

so, add the private colorsService: ColorsService to that constructor

#

constructor(private _sanitizer: DomSanitizer, private colorsService: ColorsService){}

rough loom
#

ok it seems worked

#

colorsService is just a declaration name if I und good, for this reason che small c at the beginning

cerulean blaze
#

Yeah, it could be any name you want. But it's kind of a convention to keep it the same name as the class you inject but with lowercase

rough loom
#

ok

#

I think I did all ok, but it say

Property 'colorsService' does not exist on type 'mytask'.ts(2339)

cerulean blaze
#

can you post the code?

rough loom
#

sure

rough loom
# cerulean blaze can you post the code?
import { HttpClient } from '@angular/common/http';
import { Component, OnInit, Sanitizer, SecurityContext } from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';
import { Observable } from 'rxjs';
import { ColorsService } from '../../../services';

export class MyTask implements OnInit {
  isRefreshing: boolean = false;

  colors: Observable<ColorsService[]> = this.colorsService.getColors()

  oldcolors = [
    {
      "idColor": "1",
      "colorName": "White"
    },
    {
      "idColor": "2",
      "colorName": "Yellow"
    },
    {
      "idColor": "3",
      "colorName": "Orange"
    }
  ];

    constructor(private _sanitizer: DomSanitizer, colorsService: ColorsService)
  {

  }
  ngOnInit(): void {

  }
}
#

I already tried to put the constructor at the top

#

oh I think I have to specify the modifier

#

didn't seen it was missing 🤦‍♂️

cerulean blaze
#

You don't have a @Component, or did you leave it out the pasted code?

rough loom
#
constructor(private _sanitizer: DomSanitizer, colorsService: ColorsService)
constructor(private _sanitizer: DomSanitizer, private colorsService: ColorsService)

I think this was the error, now I try to run the page

cerulean blaze
#

ok, and you ColorsService does it have @Injectable above the class?

rough loom
#
@Component({
  selector: 'mytask',
  templateUrl: './mytask.component.html',
  styleUrls: ['./mytask.component.scss']
})
cerulean blaze
#

ok, did the change to the constructor work?

rough loom
#

yes for the .ts side, not for the .html side, I think I have to change something

#

Type 'Observable<ColorsService[]>' is not assignable to type 'NgIterable<any> | null | undefined'.ngtsc(2322)

#

should I truncate all and put | async ?

cerulean blaze
#

colors: Observable<ColorsService[]> = this.colorsService.getColors() this is not correct. The type is not Observable<ColorsService[]> but should be something like Observable<Colors[]>. You will need to define a type Colors that describes the shape of the colors object.

interface Colors = {
  idColor: string;
  colorName: string;
}
rough loom
#

it's like a model?

rough loom
#
constructor(private _sanitizer: DomSanitizer, private colorsService: ColorsService)
constructor(private _sanitizer: DomSanitizer)
constructor(private colorsService: ColorsService)

I tried all possible cases, the page show correctly only when private colorsService: ColorsService is missing in the constructor, the page also show correctly if I completely delete the constructor, but it breaks when I put in ColorsService

rough loom
#

This is console log
ERROR NullInjectorError: R3InjectorError(AppModule)[ColorsService -> ColorsService -> ColorsService]: NullInjectorError: No provider for ColorsService! at NullInjector.get (core.mjs:7599:27) at R3Injector.get (core.mjs:8020:33) at R3Injector.get (core.mjs:8020:33) at R3Injector.get (core.mjs:8020:33) at ChainedInjector.get (core.mjs:12179:36) at lookupTokenUsingModuleInjector (core.mjs:3255:39) at getOrCreateInjectable (core.mjs:3300:12) at Module.ɵɵdirectiveInject (core.mjs:10135:12) at NodeInjectorFactory.MyTask_Factory [as factory] (mytask.component.ts:13:32) at getNodeInjectable (core.mjs:3485:44)

cerulean blaze
rough loom
#

done but same error, maybe I should add something other

cerulean blaze
#

Take a look at the link I posted above

rough loom
#

I found something like that (sample)

providers: [
    AngularFirestore,
    FireserviceService
  ],
cerulean blaze
#

No, providedIn: 'root' adds the service for you. no need to manually provide it.

rough loom
#

hm

rough loom
rough loom
#

well yes, in this way the webpage correctly show

#

lets see if it works

#

almost done^^ I have n. options, but blanks

cerulean blaze
#

does your getColors method return the colors correct?

rough loom
#

how do I know?

cerulean blaze
#

You can add a pipe and console.log the values of what getColors returns.

colors: Observable<Colors[]> = this.colorsService
    .getColors()
    .pipe(tap((item) => console.log(item))); // add this after the getColors()
#

You will have to import tap from rxjs as well

rough loom
#

ok

#

I added it, but nothing being showed

cerulean blaze
#

well, then it seems your getColors() does not fetch colors

rough loom
#
  colors: Observable<ColorsService[]> = this.colorsService
    .getColors()
    .pipe(tap((item) => console.log("asd" + item)));

I tried to add some text before, shouldn't it print it 3 times anyway?

cerulean blaze
#

no, item should be the array of colors

rough loom
#

hm

#

I mean, I putted "asd" before item but the console not showing even this text

#

I putted it for see if it get printed 3 times or not

cerulean blaze
#

do you have *ngFor="let color of colors | async" in your html?

rough loom
#

yes

rough loom
#

Compiled with problems:X

ERROR

src/app/views/mytask/mytask.component.ts:16:18 - error TS2304: Cannot find name 'Observable'.

16 colors: Observable<ColorsService[]> = this.colorsService.getColors()

rough loom
cerulean blaze
#

have you looked at the stackblitz I posted earlier? It shows exactly what to do

rough loom
#

hm, maybe the module.ts could be the last problem

cerulean blaze
rough loom
#

yes

cerulean blaze
#

also, i told you earlier that Observable<ColorsService[]> is not correct

rough loom
cerulean blaze
#

But you already have a ColorsService, how do you know it's using the correct one?

rough loom
#

I know have

colors: Observable<Colors[]> = this.colorsService.getColors()
cerulean blaze
#

ok, and what happens now when you do ng serve?

rough loom
#

It's already running, normally the web page refresh automatically, should I stop and serve again?

cerulean blaze
#

No

#

Is it showing any errors in the terminal?

rough loom
#

no

cerulean blaze
#

ok, I've lost track of what you did so please can you show the code for the mytask component and html again?

rough loom
#
import { HttpClient } from '@angular/common/http';
import { Component, Injectable, OnInit, Sanitizer, SecurityContext } from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';
import { Observable, tap } from 'rxjs';
import { ColorsService } from '../../../services';
import { Colors } from '../../../services/models/Colors';

@Component({
  selector: 'mytask',
  templateUrl: './mytask.component.html',
  styleUrls: ['./mytask.component.scss']
})

export class MytaskComponent implements OnInit {
  isRefreshing: boolean = false;

  colors: Observable<Colors[]> = this.colorsService.getColors()

  /*colors: Observable<Colors[]> = this.colorsService
  .getColors()
  .pipe(tap((item) => console.log("asd" + item))); */

    constructor(private _sanitizer: DomSanitizer, private colorsService: ColorsService)
  {

  }
  ngOnInit(): void {

  }
}
#
<select cSelect id="idColor" [(ngModel)]="colors">
  <option disabled>Choose...</option>
  <!--<option *ngFor="let color of colors" [(ngModel)]="color.idColor">{{color.colorName}}</option>-->
  <option *ngFor="let color of colors | async"></option>
</select>
cerulean blaze
#

ok, so no items are showing up in the select right?

rough loom
#
export interface Colors {
  idColor: number;
  colorName: string;
}
rough loom
cerulean blaze
#

oh, your html is missing the colors

<select cSelect id="idColor" [(ngModel)]="colors">
  <option disabled>Choose...</option>
  <!--<option *ngFor="let color of colors" [(ngModel)]="color.idColor">{{color.colorName}}</option>-->
  <option *ngFor="let color of colors | async" [value]="color.idColor">{{color.colorName}}</option>
</select>
#

[(ngModel)]="colors" should be a different name, now it collides with the colors property. make it [(ngModel)]="color" (since you only select 1 color) and add color: string = ''; to your component ts

rough loom
#

I was recommended to add this at the end

color: number = 0;
#

for what is it?

cerulean blaze
#

No, it's a string since idColor is a string and that's what you're assigning to color

#

unless your old colors array was wrong

rough loom
#

it works now

#

damn^^ this Angular is out of mind

cerulean blaze
#

Ok, good to hear.

#

Have you done the tutorial on angular.io? A lot of what I explained can be learned there

rough loom
#

I found it hard to understand so I just seen some yt videos

#

which is the grade of difficult of what I made? I suppose very low

cerulean blaze
#

yeah, this is all very basic. I strongly recommend you to do the tutorial, it will help you to get more familiar with the basics: https://angular.io/tutorial

#

Just code along, and things will become more familiar

rough loom
#

ok, I'll try making more experience, btw I learned somehting from this, I love learning method

#

is Angular harder than C# ?

cerulean blaze
#

I would say no, but I guess it depends on who you ask

rough loom
#

ok so I just have to understand better how does it works

#

I'm C# beginner I'd say but I realized hard projects using low knowledge, yeah maybe writing bad code, but I found out how to complete my tasks

this Angular at first impact seemed to me really hard to understand

cerulean blaze
#

Yup, you just need to keep repeating things and it will become much easier

rough loom
#

understood, tomorrow I'll make more practice and I'll finish build this test page completing all dropdowns, really thanks for your time and your support