3

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,

Investigator
  • 1,431
  • 2
  • 17
  • 24

2 Answers2

5

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.

Jeto
  • 14,596
  • 2
  • 32
  • 46
  • Hi Jeto, I still have one more problem. I receive a response from a server request and the select box does not show the correct selection. I still use the compareFn ans I show before. Why this is happening ? the drop down is empty nothing is selected. – Investigator Mar 16 '18 at 14:27
  • @Investigator I'm not sure what you need `compareFn` for. Can you update your code with your server request and how it changes the `config` property? – Jeto Mar 16 '18 at 15:34
  • @Investigator Just saw your updated post. Can you `console.log` the value of `config` within `onSaveSuccess` and tell me what it prints? – Jeto Mar 16 '18 at 18:30
  • encryptionProtocol:"SSL" It is returned as a string. – Investigator Mar 18 '18 at 15:36
  • I found that if I do not use Enumerations and I simply enter the options like this : it will work. I would prefer to use enumerations of course. It must be related with the types. – Investigator Mar 18 '18 at 15:45
  • @Investigator It can't work if the value is a string. Try replacing your enum with `export enum EncryptionProtocol { NONE = 'NONE', SSL = 'SSL', TLS = 'TLS' }` then. – Jeto Mar 18 '18 at 17:27
  • now the NONE value is not being displayed at the drop down box. Only the SSL and the TLS. The defailt value is again empty. – Investigator Mar 19 '18 at 09:33
  • It didn't work out with the enumeration and I will change it to hard coded values since I need to move on. Thank you @Jeto about your support. – Investigator Mar 19 '18 at 16:13
  • @Investigator I was going to take another look tonight (need to test code), but glad you found a solution :) – Jeto Mar 19 '18 at 16:14
1
<option *ngFor="let encryptionProtocol of encryptionProtocolKeys()" 
  [ngValue]="encryptionProtocolValues[encryptionProtocol]" [value]="encryptionProtocol">
    {{encryptionProtocol}}
</option>

Thank you for your post...it helped me out alot...the only thing i would added to the answer is the binding to the value [value]="encryptionProtocol" ... this will retain the choice the user selected.

Daron
  • 113
  • 2
  • 13