Problems implementing dropdown list Cascade with Angular 4?

0

As the title says, I'm having trouble implementing the Dropdown Cascade, it's about loading the first Dropdown with the state and the second Dropdown will automatically load according to the state selected in the first Dropdown.

Look at the template I found on the internet and it's working.

Cascading Dropdown

This template above is working perfectly because I tested it on my local computer, trying to adapt it for my project can not.

I'm just needing help adapting it to my project.

I do not think it's so complicated!

When you make the first changes, you already have problems with the components file without first compiling, first look at the changes made in the services file.

Note the changes

It used to be this way:

import { Cidade, Estado, Country, State } from './../core/model';
import { Injectable } from '@angular/core';
import { Http, URLSearchParams, Headers } from '@angular/http';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/of';

@Injectable()
export class CidadesService {

 // cidadesUrl = 'http://localhost:8080/cidades';
 // estadosUrl = 'http://localhost:8080/cidades/estados';



  constructor(private http: HttpClient) { }

  getCountries() {
    return [
     new Country(1, 'USA' ),
     new Country(2, 'India' ),
     new Country(3, 'Australia' )
    ];
  }


  getStates() {
   return [
     new State(1, 1, 'Arizona' ),
     new State(2, 1, 'Alaska' ),
     new State(3, 1, 'Florida'),
     new State(4, 1, 'Hawaii'),
     new State(5, 2, 'Gujarat' ),
     new State(6, 2, 'Goa'),
     new State(7, 2, 'Punjab' ),
     new State(8, 3, 'Queensland' ),
     new State(9, 3, 'South Australia' ),
     new State(10, 3, 'Tasmania')
    ];
  }


}

Then I changed to look like this:

import { Cidade, Estado, Country, State } from './../core/model';
import { Injectable } from '@angular/core';
import { Http, URLSearchParams, Headers } from '@angular/http';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/of';

@Injectable()
export class CidadesService {

 cidadesUrl = 'http://localhost:8080/cidades';
 // estadosUrl = 'http://localhost:8080/cidades/estados';



  constructor(private http: HttpClient) { }

  getCountries(): Observable<any> {
    return Observable.of([
     this.getTodasCidades()
    ]);
  }

  getTodasCidades() {
    return this.http.get<any[]>('${this.cidadesUrl}');
  }



  getStates() {
   return [
     new State(1, 1, 'Arizona' ),
     new State(2, 1, 'Alaska' ),
     new State(3, 1, 'Florida'),
     new State(4, 1, 'Hawaii'),
     new State(5, 2, 'Gujarat' ),
     new State(6, 2, 'Goa'),
     new State(7, 2, 'Punjab' ),
     new State(8, 3, 'Queensland' ),
     new State(9, 3, 'South Australia' ),
     new State(10, 3, 'Tasmania')
    ];
  }


}

The only change I made to the service file was in the getCountries () method, now we'll see the component file.

Before it was like this:

import { Estado, Cidade, Country, State } from './../../core/model';
import { CidadesService } from './../cidades.service';
import { Component, OnInit } from '@angular/core';
import 'rxjs/add/operator/map';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/of';


@Component({
  selector: 'app-cidades-pesquisa',
  templateUrl: './cidades-pesquisa.component.html',
  styleUrls: ['./cidades-pesquisa.component.css']

})
export class CidadesPesquisaComponent implements OnInit {

  //cidades: Cidade[];
  //estados: Estado[];



  selectedCountry: Country = new Country(0, 'Rio Branco');
  countries: Country[];
  states: State[];


  constructor(private cidadesService: CidadesService) {
    this.countries = this.cidadesService.getCountries();
   }

  ngOnInit() {
    //    this.carregarCidades();
     //   this.carregarEstados();

  }


  onSelect(countryid) {
    this.states = this.cidadesService.getStates().filter(( item ) => item.countryid == countryid);
  }

}

After the changes, it looks like this:

import { Estado, Cidade, Country, State } from './../../core/model';
import { CidadesService } from './../cidades.service';
import { Component, OnInit } from '@angular/core';
import 'rxjs/add/operator/map';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/of';


@Component({
  selector: 'app-cidades-pesquisa',
  templateUrl: './cidades-pesquisa.component.html',
  styleUrls: ['./cidades-pesquisa.component.css']

})
export class CidadesPesquisaComponent implements OnInit {

  cidades: Cidade[];
  estados: Estado[];



  selectedCountry: Cidade = new Cidade(1, 'Rio Branco', '1');
 // countries: Country[];
  states: State[];


  constructor(private cidadesService: CidadesService) {
    this.cidades = this.cidadesService.getCountries();
   }

  ngOnInit() {
    //    this.carregarCidades();
     //   this.carregarEstados();

  }


  onSelect(countryid) {
    this.states = this.cidadesService.getStates().filter(( item ) => item.countryid == countryid);
  }

}

The changes that were made were in this code snippet;

cidades: Cidade[];
  estados: Estado[];



  selectedCountry: Cidade = new Cidade(1, 'Rio Branco', '1');

The missing piece of code is:

constructor(private cidadesService: CidadesService) {
    this.cidades = this.cidadesService.getCountries();
   }

Notice that he is complaining about the Observable absence in the services file, because the services file in the getCountries () method is implemented incorrectly anyway I tried compiling and generated this error below;

ERROR in src/app/cidades/cidades-pesquisa/cidades-pesquisa.component.ts(28,5): error TS2322: Type 'Observable<any>' is not assignable
to type 'Cidade[]'.
  Property 'includes' is missing in type 'Observable<any>'.
src/app/core/model.ts(59,12): error TS2554: Expected 3 arguments, but got 0.

In order to continue the code adaptation I need to correctly implement the getCountries () method in the services file.

I will place the mapping of entity cities only for clarification criteria;

export class Cidade {
  constructor(
    codigo: number,
    nome: string,
    codigoEstado: string)
  { }
  estado = new Estado();
}
    
asked by anonymous 06.02.2018 / 12:03

1 answer

0

As I already know the answer I decided to post here to contribute to the forum;

Services file:

import { Cidade, Estado} from './../core/model';
import { Injectable } from '@angular/core';
import { Http, URLSearchParams, Headers } from '@angular/http';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';



@Injectable()
export class CidadesService {

 cidadesUrl = 'http://localhost:8080/cidades';
 estadosUrl = 'http://localhost:8080/cidades/estados';



  constructor(private http: Http) { }

  listarTodasCidades(): Observable<Cidade[]> {
    return this.http.get('${this.cidadesUrl}')
    .map(response => response.json());
    }

    listarTodosEstados(): Observable<Estado[]> {
    return this.http.get('${this.estadosUrl}')
    .map(response => response.json());
    }


}




 /* listarTodas(): Promise<any> {
    return this.http.get(this.cidadesUrl)
      .toPromise()
      .then(response => console.log(response.json()));
  }



   listarTodasCidades() {
    return this.http.get<any[]>('${this.cidadesUrl}');
  }

  listarTodosEstados() {
    return this.http.get<any[]>('${this.estadosUrl}');
  }




getCountries(): Observable<any> {
    return Observable.of([
     this.getTodosEstados()
    ]);
  }

  getTodosEstados() {
    return this.http.get<any[]>('${this.estadosUrl}');
  }




  */

Component files:

import { Estado, Cidade} from './../../core/model';
import { CidadesService } from './../cidades.service';
import { Component, OnInit } from '@angular/core';

import 'rxjs/add/operator/map';



@Component({
  selector: 'app-cidades-pesquisa',
  templateUrl: './cidades-pesquisa.component.html',
  styleUrls: ['./cidades-pesquisa.component.css']

})
export class CidadesPesquisaComponent implements OnInit {

  uf: string;

  cidades: Cidade[];
  estados: Estado[];

  constructor(private cidadesService: CidadesService) { }

  ngOnInit() {
    this.cidadesService.listarTodosEstados()
    .subscribe(estados => this.estados = estados);
  }

  buscarCidades() {
    console.log("Estado: " + this.uf);
      this.cidades = [];

     if(this.uf) {
        this.cidadesService.listarTodasCidades()
        .subscribe(cidades => {
          if (cidades.length > 0) {
            console.log("Qtd total de cidades: " + cidades.length);
          }
          for (let cidade of cidades) {
            if ( parseInt( cidade.codigoEstado) == parseInt(this.uf)) {
              console.log(cidade);
              this.cidades.push(cidade);
          }
        }
      });
    }
  }
}




  /*carregarCidades() {
    return this.cidadesService.listarTodas()
      .then(() => null);

  }

carregarCidades() {
    this.cidadesService.listarTodasCidades()
      .subscribe(dados => {
       console.log(this.cidades = dados);
      });
  }


  carregarEstados() {
    this.cidadesService.listarTodosEstados()
    .subscribe(dados => {
      this.estados = dados;
     });
  }


  console.log(this.cidades.map((e) => <any>e.codigoEstado));


  */

HTML page:

<div class="container">
  <form>
        <div class="ui-g">
                <div class="ui-g-3">
                    <select name="estado" id="estado" [(ngModel)]="uf" (change)="buscarCidades()">
                        <option *ngFor="let estado of estados" [value]="estado.codigo">{{estado.nome}}</option>
                    </select>
                </div>

            <div class="ui-g-3">
                <select name="cidade" id="cidade">
                      <option *ngFor="let cidade of cidades" [value]="cidade.codigoEstado">{{cidade.nome}}</option>
                </select>
            </div>

        </div>

  </form>
  </div>
    
06.02.2018 / 14:45