Search code examples
angularangular-routerbootstrap-duallistbox

Loading ng2-dual-list-box selected items with angular routes


I am quite new to Angular 4 and have already spent several hours trying to figure out how to solve this problem so any help is much appreciated.

I am using an the ng2-dual-list-box component in my project and I am having problems dynamically loading large arrays of selected items from the api in the selected items listbox side. Somehow it appears like the control is rendered before the items in the selected items are loaded. For example, when the app runs by itself, the selected items list is empty but when I run in debug mode and put a break on the loadCourses function and wait for 10-20seconds before resuming, the selected items control is populated with the selected items. Am I doing this right? are there workarounds?

Here is what my code looks like:

## user.component.ts ##
import { Component, OnInit } from '@angular/core';
import { UserService } from '../../_services/UserService.service';
import { CourseService } from '../../_services/CourseService.service';


@Component({
  selector: 'app-user',
  templateUrl: './user.component.html',
  styleUrls: ['./user.component.css']
})
export class MyUserComponent implements OnInit {

  availableCourses: Course[];

  constructor(private userService: UserService, 
      private courseService: CourseService,
          private route: ActivatedRoute) {

  }

ngOnInit() {
    this.route.data.subscribe(data => this.user = data['user'] );
    this.loadCourses();

    //Selected list items do not load at all without this line  
    //this line also seems to return data after the component has loaded. Selected items in the components.html is empty
    this.loadUserDetails();     
}

loadCourses(){
 this.courseService.getCourses()
        .subscribe(courses => this.availableCourses = courses);
}

loadUserDetails(){
    this.userService
        .getUser(this.route.snapshot.params['id'])
        .subscribe(user => this.user = user)
}

## UserService.ts ##
import { Injectable } from '@angular/core';
import { Http, Headers, RequestOptions, Response } from '@angular/http';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/throw';
import 'rxjs/add/observable/of';
import { Observable } from 'rxjs/Observable';
...


@Injectable()

constructor(private http: Http) { }
getUser(): Observable<User> {
     return this.http
                .get(this.baseUrl + 'user')
                .map( response => <user>response.json())
                .catch(this.handleError);
}

## CourseService.ts ##
//same as userService
getCourses(): Observable<Course[]> {
    return this.http
                .get(this.baseUrl + 'courses')
                .map( response => <Courses[]>response.json())
                .catch(this.handleError);    
}

## user-detail.resolver.ts##
import { Component, OnInit, Injectable } from '@angular/core';
import { Resolve, Router, ActivatedRouteSnapshot } from '@angular/router';
import { Observable } from 'rxjs/Rx';
import { UserService } from '../_services/user.service';
...


@Injectable()
export class UserDetailResolver implements Resolve<User> {

  constructor(private userService: UserService,
              private router: Router) { }

resolve(route: ActivatedRouteSnapshot): Observable<User> {
  return this.userService.getUser(route.params['id'])
                            .catch(error ....);
                             this.router.navigate(['/userList']);
                              return Observable.of(null);
                            });
  }

}

## user.Component.html ##
 <form  role="form" #editForm="ngForm" name="editForm"   (ngSubmit)="SaveUser()">
  <ng2-dual-list-box [data]="availableCourses" 
        valueField="id" textField="name" #courseList name="courseList"
       (onAvailableItemSelected)="log($event)" 
        [(ngModel)]="user.Courses"
       (onSelectedItemsSelected)="log($event)"
       (onItemsMoved)="log($event)" ng-disabled="true">
   </ng2-dual-list-box>
</form>

Solution

  • It turns out that instead of calling this.loadCourses() and this.loadUserDetails() separatedly, I needed to call this.loadUserDetails() from within the subscription of this.loadCourses in the component.

    loadCourses(){
     this.courseService.getCourses()
                       .subscribe((courses) => {
                             this.availableCourses = courses;
                             //If this.available courses
                             this.loadUserDetails();
    

    }); }