<p dir="auto"><strong>I'm submitting a ...</strong>  (check one with "x")</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="[x ] bug report =&gt; search github for a similar issue or PR before submitting
[ ] feature request
[ ] support request =&gt; Please do not submit support request here, instead see https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question"><pre class="notranslate"><code class="notranslate">[x ] bug report =&gt; search github for a similar issue or PR before submitting
[ ] feature request
[ ] support request =&gt; Please do not submit support request here, instead see https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question
</code></pre></div>
<p dir="auto"><strong>Current behavior</strong></p>

<p dir="auto"><code class="notranslate">select</code> HTML element doesn't react to changes of model (like when we do <code class="notranslate">this.selectedValue = obj;</code> in component, when in template we have <code class="notranslate">[(ngModel)]="selectedValue"</code>). Therefore, initial <code class="notranslate">select</code> value is not proper.</p>
<p dir="auto"><strong>Expected behavior</strong></p>

<p dir="auto">This code should initialize value of <code class="notranslate">select</code> HTML element properly, i.e. listen to <code class="notranslate">selectedValue</code> changes and select proper option.</p>
<p dir="auto"><strong>Minimal reproduction of the problem with instructions</strong></p>

<p dir="auto">I have the next code</p>
<p dir="auto"><strong>choice-input.view.html</strong></p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="&lt;select *ngIf=&quot;!options.multiple&quot; class=&quot;form-control&quot; [(ngModel)]=&quot;selectedValue&quot; (blur)=&quot;onTouchedCallback()&quot;&gt;
        &lt;option value=&quot;&quot; [disabled]=&quot;options.required&quot; [ngValue]=&quot;null&quot;&gt;No value&lt;/option&gt;
        &lt;option *ngFor=&quot;let choice of options.choices&quot; [ngValue]=&quot;choice.value&quot;&gt;{{choice.label | trans }}&lt;/option&gt;
&lt;/select&gt;"><pre class="notranslate"><span class="pl-c1">&lt;</span><span class="pl-ent">select</span> <span class="pl-c1">*</span><span class="pl-c1">ngIf</span><span class="pl-c1">=</span><span class="pl-s">"!options.multiple"</span> <span class="pl-c1">class</span><span class="pl-c1">=</span><span class="pl-s">"form-control"</span> <span class="pl-kos">[</span><span class="pl-kos">(</span><span class="pl-c1">ngModel</span><span class="pl-kos">)</span><span class="pl-kos">]</span><span class="pl-c1">=</span><span class="pl-s">"selectedValue"</span> <span class="pl-kos">(</span><span class="pl-c1">blur</span><span class="pl-kos">)</span><span class="pl-c1">=</span><span class="pl-s">"onTouchedCallback()"</span><span class="pl-c1">&gt;</span>
        <span class="pl-c1">&lt;</span><span class="pl-ent">option</span> <span class="pl-c1">value</span><span class="pl-c1">=</span><span class="pl-s">""</span> <span class="pl-kos">[</span><span class="pl-c1">disabled</span><span class="pl-kos">]</span><span class="pl-c1">=</span><span class="pl-s">"options.required"</span> <span class="pl-kos">[</span><span class="pl-c1">ngValue</span><span class="pl-kos">]</span><span class="pl-c1">=</span><span class="pl-s">"null"</span><span class="pl-c1">&gt;</span>No value<span class="pl-c1">&lt;</span><span class="pl-c1">/</span><span class="pl-ent">option</span><span class="pl-c1">&gt;</span>
        <span class="pl-c1">&lt;</span><span class="pl-ent">option</span> <span class="pl-c1">*</span><span class="pl-c1">ngFor</span><span class="pl-c1">=</span><span class="pl-s">"let choice of options.choices"</span> <span class="pl-kos">[</span><span class="pl-c1">ngValue</span><span class="pl-kos">]</span><span class="pl-c1">=</span><span class="pl-s">"choice.value"</span><span class="pl-c1">&gt;</span><span class="pl-kos">{</span><span class="pl-kos">{</span>choice<span class="pl-kos"></span><span class="pl-kos">.</span><span class="pl-c1">label</span> <span class="pl-c1">|</span> <span class="pl-s1">trans</span> <span class="pl-kos">}</span><span class="pl-kos">}</span><span class="pl-c1">&lt;</span><span class="pl-c1">/</span><span class="pl-ent">option</span><span class="pl-c1">&gt;</span>
<span class="pl-c1">&lt;</span><span class="pl-c1">/</span><span class="pl-ent">select</span><span class="pl-c1">&gt;</span></pre></div>
<p dir="auto"><strong>choice-input.component.ts</strong></p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="import {Component, forwardRef, Input, Renderer, ViewChild, ElementRef} from &quot;@angular/core&quot;;
import {ControlValueAccessor, NG_VALUE_ACCESSOR} from &quot;@angular/forms&quot;;
import * as _ from &quot;lodash&quot;;
import {ModelStore} from &quot;../../sio-model-module/store/model.store&quot;;
import {QueryClient} from &quot;../../sio-dynamic-list-module/client/query.client&quot;;
import {QueryResult} from &quot;../../sio-dynamic-list-module/model/query-result.interface&quot;;
import {ReplaySubject} from &quot;rxjs/ReplaySubject&quot;;
import {QueryRequest} from &quot;../../sio-dynamic-list-module/model/query-request.interface&quot;;


@Component(
    {
        selector:    'sio-form-choice-input',
        templateUrl: 'choice-input.view.html',
        providers: [
            { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() =&gt; ChoiceInputComponent), multi: true }
        ]
    }
)
export class ChoiceInputComponent implements ControlValueAccessor
{
    protected choices: any[];
    protected selected: any;

    protected defaults: any = {
        choices:  [],
        multiple: false,
        expanded: false,
    };

    _options: any;

    protected onChangeCallback:  (value: any) =&gt; void = (() =&gt; {}); // Empty callback (does nothing)
    protected onTouchedCallback: () =&gt; void           = (() =&gt; {}); // Empty callback (does nothing)

    protected onChoicesLoaded: ReplaySubject&lt;any&gt; = new ReplaySubject&lt;any&gt;(1);

    constructor(protected modelStore: ModelStore, protected renderer: Renderer, protected queryClient: QueryClient)
    {
    }

    @Input('options')
    get options(): any
    {
        return this._options;
    }

    set options(options: any)
    {
        this._options = _.extend({}, this.defaults, options);

        this.loadChoiceItems();
    }

    get selectedValue(): any {
        return this.selected;
    };

    set selectedValue(newValue: any) {
        if (!_.isEqual(newValue, this.selected)) {
            this.writeValue(newValue);
            this.onChangeCallback(newValue);
        }
    };

    writeValue(newValue: any)
    {
        // Wait until possible choices are loaded and then set current choice

        this.onChoicesLoaded.subscribe((status) =&gt; {
            if (_.isEqual(newValue, this.selected)) {
                return;
            }

            this.selected = newValue;
        });
    }

    registerOnChange(fn: any)
    {
        this.onChangeCallback = fn;
    }

    registerOnTouched(fn: any)
    {
        this.onTouchedCallback = fn;
    }

    private loadChoiceItems()
    {
       // Some complicated logic for loading this.options.choices
       // After it is done, this.onChoicesLoaded.next('loaded.choices.query.model'); is being executed 
    }
}"><pre class="notranslate"><code class="notranslate">import {Component, forwardRef, Input, Renderer, ViewChild, ElementRef} from "@angular/core";
import {ControlValueAccessor, NG_VALUE_ACCESSOR} from "@angular/forms";
import * as _ from "lodash";
import {ModelStore} from "../../sio-model-module/store/model.store";
import {QueryClient} from "../../sio-dynamic-list-module/client/query.client";
import {QueryResult} from "../../sio-dynamic-list-module/model/query-result.interface";
import {ReplaySubject} from "rxjs/ReplaySubject";
import {QueryRequest} from "../../sio-dynamic-list-module/model/query-request.interface";


@Component(
    {
        selector:    'sio-form-choice-input',
        templateUrl: 'choice-input.view.html',
        providers: [
            { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() =&gt; ChoiceInputComponent), multi: true }
        ]
    }
)
export class ChoiceInputComponent implements ControlValueAccessor
{
    protected choices: any[];
    protected selected: any;

    protected defaults: any = {
        choices:  [],
        multiple: false,
        expanded: false,
    };

    _options: any;

    protected onChangeCallback:  (value: any) =&gt; void = (() =&gt; {}); // Empty callback (does nothing)
    protected onTouchedCallback: () =&gt; void           = (() =&gt; {}); // Empty callback (does nothing)

    protected onChoicesLoaded: ReplaySubject&lt;any&gt; = new ReplaySubject&lt;any&gt;(1);

    constructor(protected modelStore: ModelStore, protected renderer: Renderer, protected queryClient: QueryClient)
    {
    }

    @Input('options')
    get options(): any
    {
        return this._options;
    }

    set options(options: any)
    {
        this._options = _.extend({}, this.defaults, options);

        this.loadChoiceItems();
    }

    get selectedValue(): any {
        return this.selected;
    };

    set selectedValue(newValue: any) {
        if (!_.isEqual(newValue, this.selected)) {
            this.writeValue(newValue);
            this.onChangeCallback(newValue);
        }
    };

    writeValue(newValue: any)
    {
        // Wait until possible choices are loaded and then set current choice

        this.onChoicesLoaded.subscribe((status) =&gt; {
            if (_.isEqual(newValue, this.selected)) {
                return;
            }

            this.selected = newValue;
        });
    }

    registerOnChange(fn: any)
    {
        this.onChangeCallback = fn;
    }

    registerOnTouched(fn: any)
    {
        this.onTouchedCallback = fn;
    }

    private loadChoiceItems()
    {
       // Some complicated logic for loading this.options.choices
       // After it is done, this.onChoicesLoaded.next('loaded.choices.query.model'); is being executed 
    }
}
</code></pre></div>
<p dir="auto"><strong>What is the motivation / use case for changing the behavior?</strong></p>

<p dir="auto">I want to make <code class="notranslate">select</code> html element work with objects that have structure <code class="notranslate">{id:'some-id',modelId:'some-other-id'}</code> without any additional effort with binding/updating values from my side.</p>
<p dir="auto"><strong>Please tell us about your environment:</strong></p>

<ul dir="auto">
<li><strong>Angular version:</strong> 2.4.5</li>
</ul>

<ul dir="auto">
<li><strong>Browser:</strong> [all | Chrome XX | Firefox XX | IE XX | Safari XX | Mobile Chrome XX | Android X.X Web Browser | iOS XX Safari | iOS XX UIWebView | iOS XX WKWebView ]</li>
</ul>

<p dir="auto">all</p>
<ul dir="auto">
<li>
<p dir="auto"><strong>Language:</strong> [all | TypeScript X.X | ES6/7 | ES5]<br>
TypeScript 2.1.5</p>
</li>
<li>
<p dir="auto"><strong>Node (for AoT issues):</strong> <code class="notranslate">node --version</code> =<br>
7.4.0</p>
</li>
</ul>
<p dir="auto">is there a plan to add the <code class="notranslate">angular.copy</code> function into facade/lang? If not anywhere in the project?</p>