mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
This commit is contained in:
@@ -37,17 +37,21 @@ export class DomPortalHost extends BasePortalHost {
|
||||
*/
|
||||
attachComponentPortal<T>(portal: ComponentPortal<T>): ComponentRef<T> {
|
||||
let componentFactory = this._componentFactoryResolver.resolveComponentFactory(portal.component);
|
||||
let componentRef = componentFactory.create(portal.injector || this._defaultInjector);
|
||||
componentRef.hostView.detectChanges();
|
||||
let componentRef: ComponentRef<T>;
|
||||
|
||||
// If the portal specifies a ViewContainerRef, we will use that as the attachment point
|
||||
// for the component (in terms of Angular's component tree, not rendering).
|
||||
// When the ViewContainerRef is missing, we use the factory to create the component directly
|
||||
// and then manually attach the view to the application.
|
||||
if (portal.viewContainerRef) {
|
||||
portal.viewContainerRef.insert(componentRef.hostView);
|
||||
componentRef = portal.viewContainerRef.createComponent(
|
||||
componentFactory,
|
||||
portal.viewContainerRef.length,
|
||||
portal.injector || portal.viewContainerRef.parentInjector);
|
||||
|
||||
this.setDisposeFn(() => componentRef.destroy());
|
||||
} else {
|
||||
componentRef = componentFactory.create(portal.injector || this._defaultInjector);
|
||||
this._appRef.attachView(componentRef.hostView);
|
||||
this.setDisposeFn(() => {
|
||||
this._appRef.detachView(componentRef.hostView);
|
||||
|
||||
@@ -368,12 +368,6 @@ describe('Portals', () => {
|
||||
|
||||
expect(spy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should run change detection in the created component when a ComponentPortal is attached',
|
||||
() => {
|
||||
host.attach(new ComponentPortal(ComponentWithBoundVariable, someViewContainerRef));
|
||||
expect(someDomElement.textContent).toContain('initial value');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -410,15 +404,6 @@ class ArbitraryViewContainerRefComponent {
|
||||
constructor(public viewContainerRef: ViewContainerRef, public injector: Injector) { }
|
||||
}
|
||||
|
||||
/** Simple component with a bound variable in the template */
|
||||
@Component({
|
||||
selector: 'bound-text',
|
||||
template: '<p>{{text}}</p>'
|
||||
})
|
||||
class ComponentWithBoundVariable {
|
||||
text: string = 'initial value';
|
||||
}
|
||||
|
||||
|
||||
/** Test-bed component that contains a portal host and a couple of template portals. */
|
||||
@Component({
|
||||
@@ -468,12 +453,7 @@ class PortalTestApp {
|
||||
|
||||
// Create a real (non-test) NgModule as a workaround for
|
||||
// https://github.com/angular/angular/issues/10760
|
||||
const TEST_COMPONENTS = [
|
||||
PortalTestApp,
|
||||
ArbitraryViewContainerRefComponent,
|
||||
PizzaMsg,
|
||||
ComponentWithBoundVariable
|
||||
];
|
||||
const TEST_COMPONENTS = [PortalTestApp, ArbitraryViewContainerRefComponent, PizzaMsg];
|
||||
@NgModule({
|
||||
imports: [CommonModule, PortalModule],
|
||||
exports: TEST_COMPONENTS,
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<md-calendar cdkTrapFocus
|
||||
[id]="datepicker?.id"
|
||||
[startAt]="datepicker?.startAt"
|
||||
[startView]="datepicker?.startView"
|
||||
[minDate]="datepicker?._minDate"
|
||||
[maxDate]="datepicker?._maxDate"
|
||||
[dateFilter]="datepicker?._dateFilter"
|
||||
[selected]="datepicker?._selected"
|
||||
(selectedChange)="datepicker?._selectAndClose($event)">
|
||||
[id]="datepicker.id"
|
||||
[startAt]="datepicker.startAt"
|
||||
[startView]="datepicker.startView"
|
||||
[minDate]="datepicker._minDate"
|
||||
[maxDate]="datepicker._maxDate"
|
||||
[dateFilter]="datepicker._dateFilter"
|
||||
[selected]="datepicker._selected"
|
||||
(selectedChange)="datepicker._selectAndClose($event)">
|
||||
</md-calendar>
|
||||
|
||||
@@ -34,7 +34,7 @@ describe('MdDatepicker', () => {
|
||||
let adapter = new NativeDateAdapter();
|
||||
adapter.setLocale('en-US');
|
||||
return adapter;
|
||||
}}
|
||||
}},
|
||||
],
|
||||
declarations: [
|
||||
DatepickerWithFilterAndValidation,
|
||||
@@ -42,6 +42,7 @@ describe('MdDatepicker', () => {
|
||||
DatepickerWithMinAndMaxValidation,
|
||||
DatepickerWithNgModel,
|
||||
DatepickerWithStartAt,
|
||||
DatepickerWithStartView,
|
||||
DatepickerWithToggle,
|
||||
InputContainerDatepicker,
|
||||
MultiInputDatepicker,
|
||||
@@ -203,6 +204,35 @@ describe('MdDatepicker', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('datepicker with startView', () => {
|
||||
let fixture: ComponentFixture<DatepickerWithStartView>;
|
||||
let testComponent: DatepickerWithStartView;
|
||||
|
||||
beforeEach(async(() => {
|
||||
fixture = TestBed.createComponent(DatepickerWithStartView);
|
||||
fixture.detectChanges();
|
||||
|
||||
testComponent = fixture.componentInstance;
|
||||
}));
|
||||
|
||||
afterEach(async(() => {
|
||||
testComponent.datepicker.close();
|
||||
fixture.detectChanges();
|
||||
}));
|
||||
|
||||
it('should start at the specified view', () => {
|
||||
testComponent.datepicker.open();
|
||||
fixture.detectChanges();
|
||||
|
||||
const firstCalendarCell = document.querySelector('.mat-calendar-body-cell');
|
||||
|
||||
// When the calendar is in year view, the first cell should be for a month rather than
|
||||
// for a date.
|
||||
expect(firstCalendarCell.textContent)
|
||||
.toBe('JAN', 'Expected the calendar to be in year-view');
|
||||
});
|
||||
});
|
||||
|
||||
describe('datepicker with ngModel', () => {
|
||||
let fixture: ComponentFixture<DatepickerWithNgModel>;
|
||||
let testComponent: DatepickerWithNgModel;
|
||||
@@ -698,6 +728,18 @@ class DatepickerWithStartAt {
|
||||
}
|
||||
|
||||
|
||||
@Component({
|
||||
template: `
|
||||
<input [mdDatepicker]="d" [value]="date">
|
||||
<md-datepicker #d startView="year"></md-datepicker>
|
||||
`,
|
||||
})
|
||||
class DatepickerWithStartView {
|
||||
date = new Date(2020, JAN, 1);
|
||||
@ViewChild('d') datepicker: MdDatepicker<Date>;
|
||||
}
|
||||
|
||||
|
||||
@Component({
|
||||
template: `<input [(ngModel)]="selected" [mdDatepicker]="d"><md-datepicker #d></md-datepicker>`,
|
||||
})
|
||||
|
||||
@@ -57,7 +57,7 @@ let datepickerUid = 0;
|
||||
styleUrls: ['datepicker-content.css'],
|
||||
host: {
|
||||
'class': 'mat-datepicker-content',
|
||||
'[class.mat-datepicker-content-touch]': 'datepicker?.touchUi',
|
||||
'[class.mat-datepicker-content-touch]': 'datepicker.touchUi',
|
||||
'(keydown)': '_handleKeydown($event)',
|
||||
},
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
|
||||
@@ -131,6 +131,11 @@ export class MdSnackBar {
|
||||
let containerRef: ComponentRef<MdSnackBarContainer> = overlayRef.attach(containerPortal);
|
||||
containerRef.instance.snackBarConfig = config;
|
||||
|
||||
// The snackbar animation needs the content to be resolved in order to transform the bar
|
||||
// out of the view initially (so it can slide in). To make the content resolve, we manually
|
||||
// detect changes.
|
||||
containerRef.changeDetectorRef.detectChanges();
|
||||
|
||||
return containerRef.instance;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user