Paul Cavacas
Paul Cavacas

Reputation: 4454

PrimeNG Dropdown not selecting item when options loaded after model is set

I have a PrimeNG drop down defined like this

<p-dropdown id="businessType" name="businessType" required placeholder="select one"
            [style]="{'width': '100%'}" [styleClass]="hasError(ideaInitiatedForm?.controls?.businessType)"
            [options]="businessTypes" [(ngModel)]="stage.BusinessType"></p-dropdown>

The component for this is defined like this

export class IdeaInitiatedComponent implements OnInit {
    businessTypes: SelectItem[] = [];

ngOnInit(): void {
        this.loadReferenceList(this.businessTypesService.get, this.businessTypesService, this.businessTypes);
    }

loadReferenceList(loadMethod: () => Observable<string[]|Points[]>, service: any, lookupList: SelectItem[]): any {
        const method = loadMethod.bind(service);

        method()
            .subscribe(((items: string[] | Points[]) => {
                _.each(items,
                    (item: string|Points) => {
                        const label = item.hasOwnProperty('description') ? (item as Points).description : item as string;
                        const value = item.hasOwnProperty('points') ? (item as Points).points.toString() : item as string;

                        lookupList.push({ label: label, value: value });
                    });
            }));
    }

    constructor(private readonly pointsService: PointsService, private readonly pppcaTypesService: PppcaTypesService,
        private readonly pppcaSubTypesService: PppcaSubTypesService, private readonly businessTypesService: BusinessTypesService,
        private readonly businessSubTypesService: BusinessSubTypesService, private readonly projectValuesService: ProjectValuesService,
        private readonly strategiesService: StrategiesService, private readonly strategicTacticalTypesService: StrategicTacticalTypesService,
        private readonly channelsService: ChannelsService, private readonly businessUnitsService: BusinessUnitsService) { }

}

The business unit service is structured like this

@Injectable() 
export class BusinessTypesService extends BaseLookupService<string> {

    constructor(http: Http) {
        super(http, 'api/businessTypes/');
    }

}

export class BaseLookupService<T> {

    constructor(private readonly http: Http, private readonly baseApiUrl: string) { }

    private items: T[];

    get(): Observable<T[]> {
        if (this.items) {
            return Observable.of(this.items);
        }

        return this.http.get(this.baseApiUrl + 'Get')
            .map((res: Response) => {
                this.items = this.extractData(res);
                return this.items;
            })
            .catch(this.handleError);
    }

    private extractData(res: Response) {
        const rspObject = res.json();
        return rspObject || {};
    }

    private handleError(error: Response | any) {
        const errMsg = 'Error with Business Types service API response.';
        return Observable.throw(errMsg);
    }

}

What is happening is that when the main information is loaded first, i.e. stage.BusinessType then nothing is selected in the label portion of the drop down. If the options are loaded first then everything works as expected.

If I put an ngIf on the div that surrounds the drop down to not show it until the options are loaded then everything works then as well, but I don't really like the way that looks.

How can I get the options to work correctly. I'm using version 4.2.1 of PrimeNG "primeng": "^4.2.1",

Upvotes: 7

Views: 2146

Answers (1)

noamyg
noamyg

Reputation: 3104

If by saying:

nothing is selected in the label portion of the drop down

You mean that the item is selected (model-wise) but the value is not shown on the template, you may try to refresh the selected option directly on the dropdown component.

This has helped me several times before when I selected the option programmatically before loading the initial data.

TL;DR: add this.dropdown.selectedOption = yourSelectedInitialOption

Template:

<p-dropdown #dropdown id="businessType" name="businessType" required placeholder="select one"
            [style]="{'width': '100%'}" [styleClass]="hasError(ideaInitiatedForm?.controls?.businessType)"
            [options]="businessTypes" [(ngModel)]="stage.BusinessType"></p-dropdown>

Component:

export class IdeaInitiatedComponent implements OnInit {
    @ViewChild('dropdown', { static: false }) dropdown: Dropdown;
    businessTypes: SelectItem[] = [];

   /*** Other stuff... ***/

   loadReferenceList(loadMethod: () => Observable<string[]|Points[]>, service: any, lookupList: SelectItem[]): any {
        const method = loadMethod.bind(service);

        method().subscribe(((items: string[] | Points[]) => {
            _.each(items,
                (item: string|Points) => {
                    const label = item.hasOwnProperty('description') ? (item as Points).description : item as string;
                    const value = item.hasOwnProperty('points') ? (item as Points).points.toString() : item as string;

                    lookupList.push({ label: label, value: value });
                }
            );
            // THIS LINE RIGHT HERE --> 
            this.dropdown.selectedOption = this.stage.BusinessType;
        }));
    }

Upvotes: 0

Related Questions