angularprimeng

How to use in reactive form count of items in Picklist in PrimeNg


I have a reactive that user need to fill up and in addition to that user need to select topics that we want to be assigned for. Everything is ok when I create a new user, but when I use the same form to update the user information, but I only want to change list of topics my "Create/Update" button stays disabled.

I can't find out how I can use selectedTopics that would allow me to incorporate into myForm and would mark the form dirty.

html code:

...
<p-pickList class="w-full" [source]="topics" [target]="selectedTopics" sourceHeader="Available" targetHeader="Selected" [dragdrop]="true" [responsive]="true" [sourceStyle]="{ height: '30rem' }" [targetStyle]="{ height: '30rem' }" breakpoint="1400px" filterBy="name" sourceFilterPlaceholder="Search by name" targetFilterPlaceholder="Search by name" [showSourceControls]="false">
    <ng-template let-topics pTemplate="topic">
        <div class="flex flex-wrap align-items-center gap-3">                            
            <div class="flex-1 flex flex-column gap-2">
                <span class="font-bold">{{ topic.name }}</span>
            </div>
        </div>
    </ng-template>
</p-pickList>
...
<div class="flex justify-content-end gap-2">
    <p-button label="Cancel" severity="secondary" styleClass="p-button-secondary" (onClick)="cancel()" />
    <p-button label="Create/Update" (onClick)="onSubmit()"
        [disabled]="myForm.invalid || !myForm.dirty" />
</div>

I looked over the primeng documentation and can't find any information how they suggest to use picklist together with reactive form.


Solution

  • You haven't shared your component code to understand how you organized your reactive form. And you have not lister version of angular and primeng in your project.

    As an option you can use the following: update your form to have count of topics: *.component.ts

    myForm= this.fb.group({
        //...
        // whatever you have from before
        topics: [0]
      });
    
    ...
    
    markTopicsAsDirty(): void {
      this.myForm.patchValue({
        topics: this.selectedCategories.length
      });
      this.myForm.get('topics')?.markAsDirty();  
    }
    

    in your html code you would need the following changes to your picklist component:

    ...
    <p-pickList class="w-full" [source]="topics" [target]="selectedTopics" sourceHeader="Available" targetHeader="Selected" [dragdrop]="true" [responsive]="true" [sourceStyle]="{ height: '30rem' }" [targetStyle]="{ height: '30rem' }" breakpoint="1400px" filterBy="name" sourceFilterPlaceholder="Search by name" targetFilterPlaceholder="Search by name" [showSourceControls]="false"
    (onTargetReorder)="markTopicsAsDirty()" 
    (onMoveToSource)="markTopicsAsDirty()" 
    (onMoveAllToSource)="markTopicsAsDirty()" 
    (onMoveToTarget)="markTopicsAsDirty()" 
    (onMoveAllToTarget)="markTopicsAsDirty()">
        <ng-template let-topics pTemplate="topic">
            <div class="flex flex-wrap align-items-center gap-3">                            
                <div class="flex-1 flex flex-column gap-2">
                    <span class="font-bold">{{ topic.name }}</span>
                </div>
            </div>
        </ng-template>
    </p-pickList>
    ...
    
    

    In this case you will cover all events related to modification of your selectedTopics variable.

    One more thing, if you want to re-sort your source/target list after you moved items in or from, then you need to add additional logic to proper events. You can read more about it in picklist API - https://primeng.org/picklist#api.picklist.emitters

    If you don't use FormBuilder, I suggest to look into this post: https://medium.com/@krishsurya1249/angular-reactive-forms-c3effd9be1f0