how to bind auto-complete selected value to form C

2019-08-21 07:45发布

问题:

I'm having an Angular(6) reactive form with a (prime-ng) autocomplete control. I'm managing to populate it correctly with values (of streets), but I'm missing something when trying to bind the streetID (and not street name) to the form control. I tried to use the value attribute, but it still didn't fixed it. See my Html code:

<div class="form-group">
        <label>Street
          <p-autoComplete formControlName="StreetID" [dropdown]="true" [suggestions]="autoCompleteStreetsNames" (completeMethod)="searchStreet($event)" [disabled]=!frm.value.CityID value = "autoCompleteStreetsValues"  [mcFieldValidation]="frm.controls.StreetID"></p-autoComplete>
        </label>
      </div>

This is the complete method with variable declarations:

autoCompleteStreets : Map<number, string> = new Map(); 
autoCompleteStreetsNames : string[];
autoCompleteStreetsValues : number[];

searchStreet(event) : void{
this.autoCompleteStreetsValues = [];
if (event.query == '')
{
  this.generalService.GetStreetsListByCity(this.frm.value.CityID).subscribe(items =>this.populateAutoCompleteStreets(items));
} 
else
{
  this.generalService.GetCityListByPrefix(this.frm.value.CityID, event.query).subscribe(items => this.populateAutoCompleteStreets(items));
}

}

populateAutoCompleteStreets(lutItems : UnifiedLut[])
{
 this.autoCompleteStreetsNames = lutItems.map(item => item.Value);
 this.autoCompleteStreetsValues = lutItems.map(item => item.Code);
 lutItems.map(lutItem =>  this.autoCompleteStreets.set(lutItem.Code, 
lutItem.Value));
}

回答1:

I found out that the suggestions can contains objects instead of atomic types, and using their properties names for the field attribute:

<div class="form-group">
        <label>{{title.StreetID}}
          <p-autoComplete formControlName="StreetID" [dropdown]="true" [suggestions]="streetsList" [field] ="'StreetName'" (completeMethod)="searchStreet($event)" [disabled]=!frm.value.CityID (onSelect)="onSelect($event)" ></p-autoComplete>
        </label>
      </div>

component code:

streetsList : SysStreetApi[];
selectedStreet : SysStreetApi;

onSelect(street : SysStreetApi)
{
  this.selectedStreet = street;
  this.frm.value.StreetID = this.selectedStreet.StreetId;
}


回答2:

OK - Found a solution: the problem was that there wasn't an appropriate form control to bind to - meaning - there was no object in the data model (which afterwards was populate the main form group by "form.reset") which contained both the streetId and StreetName. The solution was to extend the data model (I created a new class which inherits from the original one and has one more property object of selectedStreet): This is the street Object:

 public class StreetApi 
{
    public int StreetId { get; set; }
    public int CityId { get; set; }
    public string StreetName { get; set; }
}

This is the extended class:

public class ExtendedUser : User
{...
    public StreetApi SelectedStreet { get; set; }
}

Now - the reactive form is based on the extended model, and here is how the auto complete works perfectly (the onSelect event is no longer needed), the streetsList type is an array of StreetApi:

<p-autoComplete formControlName="SelectedStreet" [dropdown]="true" 
 [suggestions]="streetsList" [field] ="'StreetName'" 
 (completeMethod)="searchStreet($event)" [disabled]=!frm.value.CityID 
  ></p- autoComplete>