primefaces / primeng

The Most Complete Angular UI Component Library
https://primeng.org
Other
10.21k stars 4.55k forks source link

Dropdown: selected option is not displaying correctly. #14734

Closed vaibhavsingh-09 closed 2 weeks ago

vaibhavsingh-09 commented 7 months ago

Describe the bug

On selecting value for the first time, the selected value is not displayed on UI. In subsequent selections, previously selected value is being displayed. My component is using OnPush change detection strategy and listing to onChange emitter from p-dropdown to invoke callback when value of dropdown changes. Inside my callback i am calling markForCheck() and detectChanges().

This code was working as expected till version primeng 17.3.2.

I have created a similar stackblitz example as a reproducer.

Environment

Mac OS 13.6.4

Reproducer

https://stackblitz.com/edit/ifkxeb?file=src%2Fapp%2Fdemo%2Fdropdown-basic-demo.html

Angular version

17.1.2

PrimeNG version

17.5.0

Build / Runtime

Angular CLI App

Language

TypeScript

Node version (for AoT issues node --version)

20.11.0

Browser(s)

Chrome Version 121.0.6167.139

Steps to reproduce the behavior

No response

Expected behavior

No response

rosenthalj commented 7 months ago

To get your reproducer to work, change:

oncahnge(){
    this.cdr.markForCheck();

     this.cdr.detectChanges()
}

To:

oncahnge(){
    setTimeout(()=>{
        this.cdr.markForCheck();

        this.cdr.detectChanges()
    },0);
}

Note: Your callback is consistently misspelled in your reproducer.

Cr3aHal0 commented 7 months ago

Hi vaibhavsingh-09,

I don't get the need of using such a mechanism for something that is already done on PrimeNG side, could you tell us why you're trying to do with markForCheck() & detectChanges ? FYI, markForCheck() is the way to go with OnPush components and is only required when bound data outside of events and inputs has changed on a given component. Since this mechanism on dropdown value change is already triggered by primeNG and since nothing changed within DropdownBasicDemo component strict scope, your onChange callback is useless there. Also FYI, markForCheck() only marks the component as dirty for the next change detection cycle, so calling detectChanges() right after is an overkill as Angular will perform (and not schedule) another change detection cycle anyway. And please don't use setTimeout this way, especially when this is a hack rather than a solution :)

vaibhavsingh-09 commented 7 months ago

Hi @Cr3aHal0 ,

The reproducer that i have given is just an example of my actual use case. The reason for using detectChanges() in my project is that we have a reusable form component which is acting as a wrapper over primeng components like input, dropdown, autocomplete etc. So in our component we have certain data which needs to be updated onchange of primeng component for example i am creating a dynamic form field on certain condition. Also this component is being hosted as private npm repo and used by many teams.

This behaviour was working till version primeng 17.3.2. Also we have this wrapper in place since 3-4 years.

rosenthalj commented 7 months ago

An alternative solution (that has not been tested) to fix this issue would be to modify PrimeNG's dropwdown.ts.

throughout the file replace

this.onChange.emit(...)

with

setTimeout(()=>{
       this.onChange.emit(...))
},0);

Note: there are 3 instances of the call to emit and 1 (corresponding to editable) actual is inside a setTimeout.

jacqueslareau commented 7 months ago

Might be a related to https://github.com/primefaces/primeng/issues/14734

reidecarvalho commented 4 months ago

I have the same problem using optionValue.

[options]="(gruposServico$ | async)!"

gruposServicos$ is an object with this structure: { id: number, nome: string }

Dropdown config: optionLabel="nome" optionValue="id" dataKey="id" formControlName="idGrupoServico"

I dont want the whole object as value, but just the id, and that's ok, it's works.

However, when I am editing the form and loading with values, using "setValue" method from form, your value is loaded but not update the component on screen (if I to print the form, "idGrupoServico" is equal to value passed in the "setValue", but on the screen is not reflected, stay no selected)

github-actions[bot] commented 3 weeks ago

This issue has been automatically marked as stale. If this issue is still affecting you with the latest version, please leave any comment, and we will keep it open. We are sorry that we have not been able to prioritize it yet. If you have any new additional information, please include it with your comment!

github-actions[bot] commented 2 weeks ago

Closing this issue after a prolonged period of inactivity. If this issue is still present in the latest release, please create a new issue with up-to-date information. Thank you for your understanding!