Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

select html element doesn't react to changes of model in component code. #14121

Closed
dmytro-y-dev opened this issue Jan 26, 2017 · 4 comments
Closed

Comments

@dmytro-y-dev
Copy link

dmytro-y-dev commented Jan 26, 2017

I'm submitting a ... (check one with "x")

[x ] bug report => search github for a similar issue or PR before submitting
[ ] feature request
[ ] support request => Please do not submit support request here, instead see https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question

Current behavior

select HTML element doesn't react to changes of model (like when we do this.selectedValue = obj; in component, when in template we have [(ngModel)]="selectedValue"). Therefore, initial select value is not proper.

Expected behavior

This code should initialize value of select HTML element properly, i.e. listen to selectedValue changes and select proper option.

Minimal reproduction of the problem with instructions

I have the next code

choice-input.view.html

<select *ngIf="!options.multiple" class="form-control" [(ngModel)]="selectedValue" (blur)="onTouchedCallback()">
        <option value="" [disabled]="options.required" [ngValue]="null">No value</option>
        <option *ngFor="let choice of options.choices" [ngValue]="choice.value">{{choice.label | trans }}</option>
</select>

choice-input.component.ts

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(() => 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) => void = (() => {}); // Empty callback (does nothing)
    protected onTouchedCallback: () => void           = (() => {}); // Empty callback (does nothing)

    protected onChoicesLoaded: ReplaySubject<any> = new ReplaySubject<any>(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) => {
            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 
    }
}

What is the motivation / use case for changing the behavior?

I want to make select html element work with objects that have structure {id:'some-id',modelId:'some-other-id'} without any additional effort with binding/updating values from my side.

Please tell us about your environment:

  • Angular version: 2.4.5
  • Browser: [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 ]

all

  • Language: [all | TypeScript X.X | ES6/7 | ES5]
    TypeScript 2.1.5

  • Node (for AoT issues): node --version =
    7.4.0

@DzmitryShylovich
Copy link
Contributor

Duplicate of #13349

@dmytro-y-dev
Copy link
Author

dmytro-y-dev commented Jan 26, 2017

angular/components#2250 (comment)
In terms of selecting objects, currently the value comparison is by object reference. This does work (as you can see in the plunker above), but we do not perform deep checking that object properties are equal so the identities must be the same.

Exactly, but I am not 100% sure that the problem is only with comparison. When #13349 will be merged, I will try to use [compareWith] to check if this issue still exists and then notify here. I killed entire day dealing with it :( .

@DzmitryShylovich
Copy link
Contributor

@pkozlowski-opensource #13349 was merged so this can be closed

@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Sep 10, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants