Components: MdSelect not properly providing NG_VALUE_ACCESSOR

Created on 19 Aug 2017  路  7Comments  路  Source: angular/components

Bug:

The MdSelect component implements the ControlValueAccessor interface but does not export itself as an NG_VALUE_ACCESSOR.

What is the expected behavior?

MdSelect should contain a provider for NG_VALUE_ACCESSOR (like MdCheckbox already does correctly), i.e. add the following:

export const MD_SELECT_CONTROL_VALUE_ACCESSOR: any = {
  provide: NG_VALUE_ACCESSOR,
  useExisting: forwardRef(() => MdSelect),
  multi: true,
};

and then add this to the @Component annotation:

  providers: [MD_SELECT_CONTROL_VALUE_ACCESSOR],

In addition, it should not assign itself to the valueAccessor property of the injected control, but leave that to the @angular/forms infrastructure.

What is the use-case or motivation for changing an existing behavior?

Currently, the MdSelect component only works with @angular/forms and not with any other "form-like" library that requires access to the NG_VALUE_ACCESSOR (in my case I am trying to write a forms library for ngrx in which I completely sidestep everything from @angular/forms except the ControlValueAccessor mechanism.

Which versions of Angular, Material, OS, TypeScript, browsers are affected?

Current master of material2.

All 7 comments

This is a legitimate pattern for setting custom value accessors that is necessary to gain access to the control (which in turn is necessary to support our current feature set). It's not possible to both inject the control and provide the class as an accessor. As changing this would introduce regressions in the select, closing.

I believe there is a way to do it. You can inject the Injector and then get the NgControl through that. That way you can get the control while at the same time being injected into the control as a value accessor.

@kara could you please investigate this solution and re-open the issue if you think it has merit?

  _control: NgControl;

  constructor(
    private _viewportRuler: ViewportRuler,
    private _changeDetectorRef: ChangeDetectorRef,
    private _overlay: Overlay,
    private _platform: Platform,
    renderer: Renderer2,
    elementRef: ElementRef,
    injector: Injector,
    @Optional() private _dir: Directionality,
    @Optional() private _parentForm: NgForm,
    @Optional() private _parentFormGroup: FormGroupDirective,
    @Attribute('tabindex') tabIndex: string,
    @Optional() @Inject(MD_PLACEHOLDER_GLOBAL_OPTIONS) placeholderOptions: PlaceholderOptions,
    @Inject(MD_SELECT_SCROLL_STRATEGY) private _scrollStrategyFactory) {

    super(renderer, elementRef);

    // there seems to be an issue when calling the injector during the constructor call, so 
    // we can either use the trick below or we can use the injector in ngOnInit
    Promise.resolve().then(() => this._control = injector.get(NgControl));

    this._tabIndex = parseInt(tabIndex) || 0;
    this._placeholderOptions = placeholderOptions ? placeholderOptions : {};
    this.floatPlaceholder = this._placeholderOptions.float || 'auto';
  }

I am facing the same issue writing a library that aims to use the ControlValueAccessor infrastructure. It's a shame this was closed and I strongly vote in favor of reopening this as well.

@MrWolfZ Another idea (also for ngrx-forms): Couldn't you optionally inject the NgControl and if it could be injected and NG_VALUE_ACCESSOR is empty, wrap its value accessor into your view adapter?

(I haven't tried this yet)

@Airblader in my case there will be no NgControl instance to inject since that only exists if a control is associated with the select via reactive forms. Since my library is a complete replacement for that your idea won't work. Not sure if it will work in your case though.

My case is actually pretty much the same as yours (my library is also a kind of replacement for forms) and you're right, I forgot about that... This is really a shame.

I think I'll reopen this issue as a new one later and reference this one to get attention back to it.

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._

Was this page helpful?
0 / 5 - 0 ratings

Related issues

RoxKilly picture RoxKilly  路  3Comments

kara picture kara  路  3Comments

julianobrasil picture julianobrasil  路  3Comments

crutchcorn picture crutchcorn  路  3Comments

jelbourn picture jelbourn  路  3Comments