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

feat(dialog): support minWidth, minHeight, maxWidth and maxHeight #7488

Merged
merged 8 commits into from
Oct 9, 2017
18 changes: 18 additions & 0 deletions src/demo-app/dialog/dialog-demo.html
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,24 @@ <h2>Dialog dimensions</h2>
</mat-form-field>
</p>

<p>
<mat-form-field>
<input matInput [(ngModel)]="config.minWidth" placeholder="Min Width">
</mat-form-field>
<mat-form-field>
<input matInput [(ngModel)]="config.minHeight" placeholder="Min Height">
</mat-form-field>
</p>

<p>
<mat-form-field>
<input matInput [(ngModel)]="config.maxWidth" placeholder="Max Width">
</mat-form-field>
<mat-form-field>
<input matInput [(ngModel)]="config.maxHeight" placeholder="Max Height">
</mat-form-field>
</p>

<h2>Dialog position</h2>

<p>
Expand Down
20 changes: 17 additions & 3 deletions src/demo-app/dialog/dialog-demo.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,21 @@
import {Component, Inject, ViewChild, TemplateRef} from '@angular/core';
import {DOCUMENT} from '@angular/platform-browser';
import {MatDialog, MatDialogRef, MAT_DIALOG_DATA} from '@angular/material';

import {
DialogPosition,
MatDialog,
MatDialogConfig,
MatDialogRef,
MAT_DIALOG_DATA
} from '@angular/material';

/**
* Appeases the AOT type checker for the template by extending `MatDialogConfig`
Copy link
Member

Choose a reason for hiding this comment

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

I would rather not add a separate type just for the sake of AoT. You can remove the type from the config. It'll still be type-checked when it's passed in to dialog.open.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Correct, dialog.open would type-check, but not having type results in AOT errors because the template would only have the inferred type to go off from:
Error at /home/travis/build/angular/material2/dist/packages/demo-app/dialog/dialog-demo.ngfactory.ts:526:51: Property 'minWidth' does not exist on type '{ disableClose: boolean; panelClass: string; hasBackdrop: boolean; backdropClass: string; width: ...'.
See https://travis-ci.org/angular/material2/jobs/282614008.

Copy link
Member

Choose a reason for hiding this comment

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

You can get it to play nice if you initialize the minWidth to something.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@crisbeto another alternative would be to just type with MatDialogConfig without extending, but given strictNullChecks, AOT will complain in the template about config.property possibly being undefined, so something like the below could be done. Let me know your thoughts.

<ng-template [ngIf]="config.position">
  <p>
    <mat-form-field>
      <input matInput [(ngModel)]="config.position.top" (change)="config.position.bottom = ''" placeholder="Top">
    </mat-form-field>
    <mat-form-field>
      <input matInput [(ngModel)]="config.position.bottom" (change)="config.position.top = ''" placeholder="Bottom">
    </mat-form-field>
  </p>

  <p>
    <mat-form-field>
      <input matInput [(ngModel)]="config.position.left" (change)="config.position.right = ''" placeholder="Left">
    </mat-form-field>
    <mat-form-field>
      <input matInput [(ngModel)]="config.position.right" (change)="config.position.left = ''" placeholder="Right">
    </mat-form-field>
  </p>
</ng-template>

Copy link
Member

Choose a reason for hiding this comment

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

I think that's over-complicating it. Initializing the new properties to empty strings should be fine.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Agreed re: initializing the config props. The only question I'd have is around setting the value for maxWidth since I'm initializing with 80vw on DialogConfig. Initializing it to something neutral like an empty string would override the value.

To your point about initializing, it could be as simple as initializing all min/max values with an empty string and initializing maxWidth with the 80vw, or extracting the default value out of a new DialogConfig and setting that in the maxWidth init.

Copy link
Member

Choose a reason for hiding this comment

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

Initializing all of them to an empty string (only in the demo) and the maxWidth to the same as the default is fine by me.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Cool. Addressed in 2b1c733

* to disallow `position` from being undefined, given that it’s optional.
* Guards cannot be set on the template because the values are bound to NgModel.
*/
interface MatDemoDialogConfig extends MatDialogConfig {
position: DialogPosition;
}

@Component({
moduleId: module.id,
Expand All @@ -14,7 +28,7 @@ export class DialogDemo {
lastAfterClosedResult: string;
lastBeforeCloseResult: string;
actionsAlignment: string;
config = {
config: MatDemoDialogConfig = {
disableClose: false,
panelClass: 'custom-overlay-pane-class',
hasBackdrop: true,
Expand Down
20 changes: 20 additions & 0 deletions src/lib/dialog/dialog-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,26 @@ export class MatDialogConfig {
/** Height of the dialog. */
height?: string = '';

/** Min-width of the dialog. */
minWidth?: string = '';

/**
* Min-height of the dialog.
* For this value to be effectively applied, `height` may also need to be defined.
* See https://www.w3.org/TR/CSS2/visudet.html#min-max-widths
Copy link
Member

Choose a reason for hiding this comment

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

I don't think that this needs to link to the CSS spec. Something along the lines of /** min-height of the dialog */ should suffice. Same goes for the maxHeight.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

*/
minHeight?: string = '';
Copy link
Member

Choose a reason for hiding this comment

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

These don't need to be initialized.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Addressed. What are your thoughts on initializing maxWidth? I left that initialized for the time being.


/** Max-width of the dialog. */
Copy link
Member

Choose a reason for hiding this comment

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

This comment should include Defaults to 80vw

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

maxWidth?: string = '80vw';

/**
* Max-height of the dialog.
* For this value to be effectively applied, `height` may also need to be defined.
* See https://www.w3.org/TR/CSS2/visudet.html#min-max-widths
*/
maxHeight?: string = '';

/** Position overrides. */
position?: DialogPosition;

Expand Down
2 changes: 0 additions & 2 deletions src/lib/dialog/dialog.scss
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@

$mat-dialog-padding: 24px !default;
$mat-dialog-border-radius: 2px !default;
$mat-dialog-max-width: 80vw !default;
$mat-dialog-max-height: 65vh !default;
$mat-dialog-button-margin: 8px !default;

Expand All @@ -17,7 +16,6 @@ $mat-dialog-button-margin: 8px !default;
border-radius: $mat-dialog-border-radius;
box-sizing: border-box;
overflow: auto;
max-width: $mat-dialog-max-width;
outline: 0;

// The dialog container should completely fill its parent overlay element.
Expand Down
63 changes: 63 additions & 0 deletions src/lib/dialog/dialog.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,69 @@ describe('MatDialog', () => {
expect(overlayPane.style.height).toBe('100px');
});

it('should should override the min-width of the overlay pane', () => {
dialog.open(PizzaMsg, {
minWidth: '500px'
});

viewContainerFixture.detectChanges();

let overlayPane = overlayContainerElement.querySelector('.cdk-overlay-pane') as HTMLElement;

expect(overlayPane.style.minWidth).toBe('500px');
});

it('should should override the max-width of the overlay pane', fakeAsync(() => {
let dialogRef = dialog.open(PizzaMsg);

viewContainerFixture.detectChanges();

let overlayPane = overlayContainerElement.querySelector('.cdk-overlay-pane') as HTMLElement;

expect(overlayPane.style.maxWidth).toBe('80vw',
'Expected dialog to set a default max-width on overlay pane');

dialogRef.close();

tick(500);
viewContainerFixture.detectChanges();
flushMicrotasks();

dialogRef = dialog.open(PizzaMsg, {
maxWidth: '100px'
});

viewContainerFixture.detectChanges();

overlayPane = overlayContainerElement.querySelector('.cdk-overlay-pane') as HTMLElement;

expect(overlayPane.style.maxWidth).toBe('100px');
}));

it('should should override the min-height of the overlay pane', () => {
dialog.open(PizzaMsg, {
minHeight: '300px'
});

viewContainerFixture.detectChanges();

let overlayPane = overlayContainerElement.querySelector('.cdk-overlay-pane') as HTMLElement;

expect(overlayPane.style.minHeight).toBe('300px');
});

it('should should override the max-height of the overlay pane', () => {
dialog.open(PizzaMsg, {
maxHeight: '100px'
});

viewContainerFixture.detectChanges();

let overlayPane = overlayContainerElement.querySelector('.cdk-overlay-pane') as HTMLElement;

expect(overlayPane.style.maxHeight).toBe('100px');
});

it('should should override the top offset of the overlay pane', () => {
dialog.open(PizzaMsg, {
position: {
Expand Down
6 changes: 5 additions & 1 deletion src/lib/dialog/dialog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,11 @@ export class MatDialog {
scrollStrategy: this._scrollStrategy(),
panelClass: dialogConfig.panelClass,
hasBackdrop: dialogConfig.hasBackdrop,
direction: dialogConfig.direction
direction: dialogConfig.direction,
minWidth: dialogConfig.minWidth,
minHeight: dialogConfig.minHeight,
maxWidth: dialogConfig.maxWidth,
maxHeight: dialogConfig.maxHeight
});

if (dialogConfig.backdropClass) {
Expand Down