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

refactor(input): rename input-container to form-field... #6331

Merged
merged 8 commits into from
Aug 10, 2017

Conversation

mmalerba
Copy link
Contributor

@mmalerba mmalerba commented Aug 7, 2017

and move all communication with mdInput into a well defined interface. This is a pre-requisite to making md-select share a container element with mdInput.

This is a first-pass PR that tries to avoid breaking changes as much as possible. We can update Google's codebase and remove the old selectors and class names in the future.

@tinayuangao This should also allow you to integrate md-chip-list with the input more easily.

Incremental step toward #2124

BREAKING CHANGE: MdInputContainer is now MdFormField and MdInputDirective is now MdInput

@googlebot googlebot added the cla: yes PR author has agreed to Google's Contributor License Agreement label Aug 7, 2017
@mmalerba
Copy link
Contributor Author

mmalerba commented Aug 7, 2017

here's a demo with the changes: https://mmalerba-demo2.firebaseapp.com/, basically nothing should change from a user's perspective

@@ -410,8 +411,9 @@ export class MdAutocompleteTrigger implements ControlValueAccessor, OnDestroy {

// If it's used in a Material container, we should set it through
// the property so it can go through the change detection.
if (this._inputContainer) {
this._inputContainer._mdInputChild.value = inputValue;
if (this._inputContainer &&
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename _inputContainer to _formField?

if (this._inputContainer) {
this._inputContainer._mdInputChild.value = inputValue;
if (this._inputContainer &&
this._inputContainer._control instanceof MdInput) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does this need to check MdInput specifically now? Add a comment?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm now that I think about it, its probably better to make the value property part of the MdFormFieldControl interface so this doesn't have to be hardcoded for MdInput. I was only thinking aboutmdInput and md-select when I wrote this, but its reasonable to want autocomplete to work with a user's custom input control as well

host: {
// Remove align attribute to prevent it from interfering with layout.
'[attr.align]': 'null',
'class': 'mat-input-container mat-form-field',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a comment that mat-input-container is deprecated and will be removed?

// MdInput is a directive and can't have styles, so we need to include its styles here.
// The MdInput styles are fairly minimal so it shouldn't be a big deal for people who aren't using
// MdInput.
styleUrls: ['form-field.css', '../input/input.css'],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This may be a problem in Google-land (but maybe not; not totally sure)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it winds up being a problem I can move the file under form-field/ with a note about why its there

],
host: {
// Remove align attribute to prevent it from interfering with layout.
'[attr.align]': 'null',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we still use align on this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, but we do on md-hint, so moved this to there

changeDetection: ChangeDetectionStrategy.OnPush,
})

export class MdFormField implements AfterViewInit, AfterContentInit, AfterContentChecked {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In public_api.ts, we should re-export this as MdInputContainer to stay backwards compatible with anyone importing it (about 18 instances within Google)

MdSuffix,
// TODO(mmalerba): We import and re-export the form field module since all existing users of
// `MdInput` will need this to continue using `md-input-container`. We may want to keep this
// long term since the `MdInput` directive will almost always be used with `md-form-field`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, long-term I think the fact that form-field is its own thing is an implementation detail (similar to mdLine) that the users don't need to care about

Copy link
Contributor Author

@mmalerba mmalerba Aug 8, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok so then input, select, and any other components that wind up using it should all re-export it in their respective modules?

Updated the comment to indicate that we expect to keep this long term



/** An interface which allows a control to work inside of a `MdFormField`. */
export abstract class MdFormFieldControl {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make this an interface since it doesn't have any default implementations? I recall Misko mentioning that abstract classes should be avoided for payload size reasons

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did this because I need to use the class itself as the injection token so it can be used with @ViewChild (something like InjectionToken<MdFormFieldControl> causes a type error). It doesn't have to be abstract though, I could use a concrete class with no-op methods.



/** An interface which allows a control to work inside of a `MdFormField`. */
export abstract class MdFormFieldControl {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move this to its own file? Now that this is its own thing, we could probably break it up even more (prefix, suffix, error, and hint in their own files). That would bring this file down to that sweet, sweet 200 - 300 line range.

@mmalerba
Copy link
Contributor Author

mmalerba commented Aug 8, 2017

comments addressed

@jelbourn
Copy link
Member

jelbourn commented Aug 8, 2017

There are failures in the aot and e2e tests. Potentially need to regenerate the example module

@mmalerba
Copy link
Contributor Author

mmalerba commented Aug 8, 2017

@jelbourn Those failures appear to be due to the re-export of MdFormField as MdInputContainer in public_api.ts. Perhaps because I'm trying to export it under 2 different names?

edit: removed alias since it's problematic. I can update google's code when it's synced

$is-dark-theme: map-get($theme, is-dark);

// Placeholder colors. Required is used for the `*` star shown in the placeholder.
$form-field-placeholder-color: mat-color($foreground, secondary-text);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since these are local variables, you can get rid of the form-field- prefix.

value: any;

/** Gets the element ID for this control. */
abstract getId(): string;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps this, getPlaceholder and getNgControl should be properties instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just didn't want anyone trying to set them...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could use readonly

stateChanges: Observable<void>;

/** The value of the control. */
value: any;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of having any here, the MdFormFieldControl could be generic.

* Stream that emits whenever the state of the control changes such that the parent `MdFormField`
* needs to run change detection.
*/
stateChanges: Observable<void>;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps allow this to be a Subject as well so we don't have to add asObservable?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe a Subject is a type of Observable? Just for the purposes of this interface we only care about its Observable features.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having a Subject on the concrete class would satisfy it being an Observable

abstract getPlaceholder(): string;

/** Gets the NgControl for this control. */
abstract getNgControl(): NgControl | null;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of NgControl | null this could be an optional property/method instead.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mmm, I think anyone who wants to implement this interface will want to include this method, its just that the method may sometimes return null if angular/forms isn't being used. (same rationale as above for not wanting a property).

// MdInput.
styleUrls: ['form-field.css', '../input/input.css'],
animations: [
trigger('transitionMessages', [
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know that this is just a refactoring, but maybe we should consider getting the placeholder animation to go through Angular as well? This allows users to disable it a bit easier.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 added a TODO

@mmalerba
Copy link
Contributor Author

mmalerba commented Aug 9, 2017

comments addressed

Copy link
Member

@jelbourn jelbourn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@jelbourn jelbourn added pr: lgtm action: merge The PR is ready for merge by the caretaker and removed pr: needs review labels Aug 9, 2017
Copy link
Member

@crisbeto crisbeto left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@mmalerba mmalerba merged commit 0754320 into angular:master Aug 10, 2017
danieleds added a commit to danieleds/material2 that referenced this pull request Sep 3, 2017
@mmalerba mmalerba deleted the input-select2 branch April 3, 2018 15:19
@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 8, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
action: merge The PR is ready for merge by the caretaker cla: yes PR author has agreed to Google's Contributor License Agreement
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants