DropDownList : set and get value with ControlValueAccessor

Hello,

I have issues with handle dropdownlist with ControlValueAccessor. 
I create a component with a dropdwonlist (with item, value and footer template) and I want to use it in a reactive form.

example : 

 <account-lookup formControlName="counterpart" [dataSource]="counterpartData" showAddAction="true" (addAction)="onAdd()"
   (filtering)="onFiltering($event)"></account-lookup>

my component :

<ejs-dropdownlist #accountLookup id="accountLookup" [dataSource]='dataSource' [value]="accountingAccountDto" (valueChange)="onValueChanged($event)"
    [allowFiltering]='true' (filtering)="onFiltering($event)" [fields]="accountFields"
    [itemTemplate]="accountItemTemplate" [valueTemplate]="accountValueTemplate"
    [footerTemplate]="accountFooterTemplate">
    <ng-template #accountItemTemplate let-data>
        <!--set the value to itemTemplate property-->
        <div class="account__fields_container">
            <div class="field__number">{{ data.number }}</div>
            <div class="field__label">{{ data.label }}</div>
        </div>
    </ng-template>
    <ng-template #accountFooterTemplate let-data="">
        <!--set the value to footerTemplate property-->
        <div *ngIf="showAddAction" class="accountFooter">
            <button ejs-button class="e-outline e-info account-foot-button" type="button" i18n="@@action.ajouter"
                (click)="onClicked()"><i class="fa fa-plus"></i>Ajouter</button>
        </div>
    </ng-template>
    <ng-template #accountValueTemplate let-data>
        <div>{{ data.number }} - {{ data.label }}</div>
    </ng-template>

    <ng-template #noRecordsTemplate>
        <span>Aucun compte</span>
    </ng-template>
</ejs-dropdownlist>

ts file : 
@Component({
  selector: 'account-lookup',
  templateUrl: './account-lookup.component.html',
  styleUrls: ['./account-lookup.component.scss'],
  providers: [
    { provide: NG_VALUE_ACCESSORuseExisting: forwardRef(() => AccountLookupComponent), multi: true }
  ]
})
export class AccountLookupComponent implements OnInitOnDestroyControlValueAccessor {

  @Input() public dataSourceAccountingAccount[];
  @Input() public showAddActionboolean = false;
  @Output() public readonly addActionEventEmitter<any> = new EventEmitter();
  @Output() public readonly filteringActionEventEmitter<FilteringEventArgs> = new EventEmitter();
  @Output() public readonly accountChangeEventEmitter<ChangeEventArgs> = new EventEmitter();

  public accountFieldsObject = { text: 'number'value: 'number' };
  public accountingAccountDtoAccountingAccount;
  public unsub$Subject<void> = new Subject();

  constructor() { }

  public ngOnInit(): void {
  }

  public writeValue(valueAccountingAccount): void {
    this.accountingAccountDto = value;
  }

  public registerOnChange(fnany): void {
    this._onChange = fn;
  }

  public registerOnTouched(fnany): void {
    this._onTouched = fn;
  }

  public setDisabledState?(isDisabledboolean): void {
  }

  public onValueChanged(eventAccountingAccount) {
    this.writeValue(event);
    this._onChange(event);
  }

  private _onChange = (valueany=> { };
  private _onTouched = () => { };

......
.......

Issues:
1. In control value accesssor WriteValue method, the property type is a string instead of and object (here and AccountingAccountDto, -> load with dataSource)
2. I have multiple exception : 
     - Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value for 'ng-pristine': 'true'. Current value: 'false'.
     - errors TypeError: Cannot read property 'number' of undefined -> due to valueTemplate <ng-template #accountValueTemplate let-data>
        <div>{{ data.number }} - {{ data.label }}</div>
    </ng-template>

Can you help me please ? :) 

Best regards,
Charlotte

1 Reply 1 reply marked as answer

SN Sevvandhi Nagulan Syncfusion Team June 17, 2020 12:43 PM UTC


Hi Charlotte, 



Greetings from Syncfusion support. 


Query 1: In control value accesssor WriteValue method, the property type is a string instead of and object (here and AccountingAccountDto, -> load with dataSource) 


Solution:  

Specify the change event args type as ChangeEventArgs. Refer to the code below, 


onValueChanged(event:ChangeEventArgs){ 




Query 2: Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value for 'ng-pristine': 'true'. Current value: 'false'. 

Solution:  

The cause of the issue is due to manipulating the dom directly. Angular will not detect these changes and react properly always. To get rid of the issue, we suggest detecting the changes explicitly as mentioned below code example.   
  
constructor(private cd: ChangeDetectorRef) {  
  
  }  
  ngAfterViewChecked()  
{  
    this.cd.detectChanges();  
}  
  
Also, please refer the below blogs to now more about this angular issue.  


 
 
Query 3:  errors TypeError: Cannot read property 'number' of undefined -> due to valueTemplate <ng-template #accountValueTemplate let-data> 


Solution:  

We suspect that you have bind the value that not in the datasource. Please ensure once whether you have read the value that available in the datasource. 


Please find the sample from the below link. 



Regards, 
Sevvandhi N 



Marked as answer
Loader.
Up arrow icon