1

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...

10
  • you should be initializing the form inside the subscribe Commented Mar 8, 2018 at 14:13
  • 1
    public countries: Observable<any[]> in init() this.countries = this.http.get(this.countriesUrl).map(data=> data['countries']) and in html: <option *ngFor="let country of countries | async" value="{{country['id']}}">{{country['name']}}</option> It's better to avoid subscribing as much as possible. Angular's Async pipe handles subscribing for you Commented Mar 8, 2018 at 14:20
  • @Aravind With that it gives me an error : formGroup expects a FormGroup instance. Please pass one in. It seems that the form is not initialized... Commented Mar 8, 2018 at 14:23
  • you could make the init() return this.http.get(this.countriesUrl); after the initForm(). then in the LostEditComponent you can do the this.lostFoundEditService.init().subscribe(data => { // set countries property in here after you get the data }); Commented Mar 8, 2018 at 14:23
  • @SebOlens It gives me compilation error : property map does not exist on type Observable<Object> ... Commented Mar 8, 2018 at 14:42

1 Answer 1

1

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>
          (...)
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.