evolmind
evolmind

Reputation: 359

Angular 2 : how to populate a dropdown list from a json file with my service?

I have a service :

@Injectable()
export class LostFoundEditService {
    public lostForm: FormGroup;
    public countries: any[] = [];
    private countriesUrl = 'assets/countries.json';

    constructor(private http: HttpClient) { }

    init() {
        this.initForm();

        this.http.get(this.countriesUrl).subscribe(data => {
            this.countries = this.countries.concat(data['countries']);
        },
        (err: HttpErrorResponse) => {
            console.log(err.message);
        });
    }

    private initForm() {
        this.lostForm = new FormGroup({
            'title': new FormControl('', Validators.required),
            'description': new FormControl('', Validators.required),
            'country': new FormControl('', Validators.required),
            'state': new FormControl('', Validators.required),
            'city': new FormControl('', Validators.required),
            'zipCode': new FormControl(''),
            'street': new FormControl('')
        });
    }
}

and a class thats uses this service :

@Component({
  selector: 'app-lost-edit',
  templateUrl: './lost-edit.component.html',
  styleUrls: ['./lost-edit.component.css']
})
export class LostEditComponent implements OnInit {
  lostForm: FormGroup;
  countries: any[] = [];
  states: any[] = [];
  cities: any[] = [];

  constructor(
    private http: HttpClient,
    private lostFoundEditService: LostFoundEditService) { }

  ngOnInit() {
    this.lostFoundEditService.init();
    this.lostForm = this.lostFoundEditService.lostForm;
    this.countries = this.lostFoundEditService.countries;
  }

  onCancel() {
  }

}

Also I have the template associated with that class :

(...)
                  <select
                    id="country"
                    formControlName="country"
                    class="form-control">
                    <option value="">Countries</option>
                    <option *ngFor="let country of countries" value="{{country['id']}}">{{country['name']}}</option>
                  </select>
                </div>
            </div>
          </div>
          (...)

My question is : how to wait for the end of subscribe method (in init() of LostFoundEditService) to have all countries of the json file entered in countries array of LostEditComponent. Nothing appears in the dropdown list for the moment...

Upvotes: 1

Views: 6942

Answers (1)

Molik Miah
Molik Miah

Reputation: 132

You could possibly try this.

What i'm doing here is changing the countries property from an Array to a BehaviourSubject which means your component can subscribe to this property. We can subscribe by using the async pipe in your template which in the angular world calls the subscribe.

In your service, when we finish getting the data via the subscribe you can set the value by doing this.countries.next(data['countries']).

service :

import {BehaviorSubject} from 'rxjs/BehaviorSubject';

@Injectable()
export class LostFoundEditService {
    public lostForm: FormGroup;
    public countries: Subject = new BehaviorSubject<Array<any>>(null);
    private countriesUrl = 'assets/countries.json';

    constructor(private http: HttpClient) { }

    init() {
        this.initForm();

        this.http.get(this.countriesUrl).subscribe(data => {
            this.countries.next(this.countries.concat(data['countries']));
        },
        (err: HttpErrorResponse) => {
            console.log(err.message);
        });
    }

    private initForm() {
        this.lostForm = new FormGroup({
            'title': new FormControl('', Validators.required),
            'description': new FormControl('', Validators.required),
            'country': new FormControl('', Validators.required),
            'state': new FormControl('', Validators.required),
            'city': new FormControl('', Validators.required),
            'zipCode': new FormControl(''),
            'street': new FormControl('')
        });
    }
}

component :

@Component({
  selector: 'app-lost-edit',
  templateUrl: './lost-edit.component.html',
  styleUrls: ['./lost-edit.component.css']
})
export class LostEditComponent implements OnInit {
  lostForm: FormGroup;
  countries;
  states: any[] = [];
  cities: any[] = [];

  constructor(
    private http: HttpClient,
    private lostFoundEditService: LostFoundEditService) { }

  ngOnInit() {
    this.lostFoundEditService.init();
    this.lostForm = this.lostFoundEditService.lostForm;
    this.countries = this.lostFoundEditService.countries;
  }

  onCancel() {
  }

}

template :

(...)
                  <select
                    id="country"
                    formControlName="country"
                    class="form-control">
                    <option value="">Countries</option>
                    <option *ngFor="let country of countries | async" value="{{country['id']}}">{{country['name']}}</option>
                  </select>
                </div>
            </div>
          </div>
          (...)

Upvotes: 1

Related Questions