Search code examples
angularselectdrop-down-menuenumerationdefault-value

Angular 5 select and default value with enum values


I am trying to set a default value at a select option with Angular 5. I have read about the [compareWith] but it does not seem to help. Here is the code:

My enumeration:

export enum EncryptionProtocol {
    NONE,
    SSL,
    TLS }

My Config Model

export class Config implements BaseEntity {
    constructor(
        public id?: number,
        ...
        public encryptionProtocol?: EncryptionProtocol,
        ...
    ) {
    }
}

My HTML:

    <div class="form-group">
        <label class="form-control-label" for="field_encryptionProtocol">Encryption Protocol</label>
        <select  [compareWith]="compareFn" class="form-control" name="encryptionProtocol" [(ngModel)]="config.encryptionProtocol"
                id="field_encryptionProtocol">
            <option *ngFor="let encryptionProtocol of encryptionProtocolKeys()" [ngValue]="encryptionProtocol">
                {{encryptionProtocol}}
            </option>
        </select>
    </div>

EDIT: My TS:

...
    encryptionProtocols = EncryptionProtocol;

    encryptionProtocolKeys() : Array<string> {
        var keys = Object.keys(this.encryptionProtocols);
        return keys.slice(keys.length / 2);
    }

...

compareFn(c1: EncryptionProtocol, c2: EncryptionProtocol): boolean {
    console.log('compare function');
    console.log(c1);
    console.log(c2);
    console.log(c1 && c2 ? c1.valueOf() === c2.valueOf() : c1 === c2);
    return c1 && c2 ? c1.valueOf() === c2.valueOf() : c1 === c2;
}
...    
    ngOnInit() {
       this.config = {encryptionProtocol: EncryptionProtocol.NONE, headers: []};
    }

and the output at the console is:

compare function
NONE
undefined
false
compare function
NONE
undefined
false
compare function
SSL
undefined
false
compare function
NONE
undefined
false
compare function
SSL
undefined
false
compare function
TLS
undefined
false
{encryptionProtocol: 0, headers: Array(0)}
0
compare function
NONE
null
false
compare function
SSL
null
false
compare function
TLS
null
false
compare function
NONE
0
false
compare function
SSL
0
false
compare function
TLS
0
false
compare function
NONE
SSL
false
compare function
SSL
SSL
true

You will notice that at the end the last 'compare function' block is true. And the pre-selected value at the drop down is the SSL although I have set the NONE at the onInit method. Do you have any idea why this is happening and what should I do in order to select the correct value?

UPDATE: Here is the response from the server:

{
  "id" : 50000,
  ...
  "encryptionProtocol" : "SSL",
  "keystoreType" : "PKCS12",
  ...
}

and here is the code that assigns this object to the model:

private subscribeToSaveResponse(result: Observable<HttpResponse<Config>>) {
    result.subscribe((res: HttpResponse<Config>) =>
        this.onSaveSuccess(res.body), (res: HttpErrorResponse) => this.onSaveError());
}

private onSaveSuccess(config: Config) {
    this.isSaving = false;
    this.config = config;
}

but although the default selection works ok when we set it from the onInit method it does not when it comes back from the server. I suspect the reason is that it comes as a string. Should I convert it to an enumeration value? What is the best way to do this?

Thank you in advance,


Solution

  • Add the following property to your component's script:

    encryptionProtocolValues = EncryptionProtocol;
    

    Then on HTML side, do this:

    <option *ngFor="let encryptionProtocol of encryptionProtocolKeys()" 
      [ngValue]="encryptionProtocolValues[encryptionProtocol]">
        {{encryptionProtocol}}
    </option>
    

    Explanation: when you define an enum with only keys, the names you define are that, keys. But behind the scenes their actual implicit values are 0, 1, 2, etc, that you can access via EnumTypeName[EnumKey].

    Note that you can use [value] instead of [ngValue]. I believe it's the proper thing to do with recent Angular versions at least.