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

fix(portal): detect changes for portal hostview while before attaching. #4370

Merged
merged 1 commit into from
Jun 7, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 3 additions & 7 deletions src/lib/core/portal/dom-portal-host.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,21 +29,17 @@ export class DomPortalHost extends BasePortalHost {
*/
attachComponentPortal<T>(portal: ComponentPortal<T>): ComponentRef<T> {
let componentFactory = this._componentFactoryResolver.resolveComponentFactory(portal.component);
let componentRef: ComponentRef<T>;
let componentRef = componentFactory.create(portal.injector || this._defaultInjector);
componentRef.hostView.detectChanges();
Copy link
Member

Choose a reason for hiding this comment

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

Are you able to create a unit test that enforces this behavior?


// 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) {
componentRef = portal.viewContainerRef.createComponent(
componentFactory,
portal.viewContainerRef.length,
portal.injector || portal.viewContainerRef.parentInjector);

portal.viewContainerRef.insert(componentRef.hostView);
this.setDisposeFn(() => componentRef.destroy());
} else {
componentRef = componentFactory.create(portal.injector || this._defaultInjector);
this._appRef.attachView(componentRef.hostView);
this.setDisposeFn(() => {
this._appRef.detachView(componentRef.hostView);
Expand Down
22 changes: 21 additions & 1 deletion src/lib/core/portal/portal.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,12 @@ 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');
});
});
});

Expand Down Expand Up @@ -404,6 +410,15 @@ 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({
Expand Down Expand Up @@ -453,7 +468,12 @@ 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];
const TEST_COMPONENTS = [
PortalTestApp,
ArbitraryViewContainerRefComponent,
PizzaMsg,
ComponentWithBoundVariable
];
@NgModule({
imports: [CommonModule, PortalModule],
exports: TEST_COMPONENTS,
Expand Down
16 changes: 8 additions & 8 deletions src/lib/datepicker/datepicker-content.html
Original file line number Diff line number Diff line change
@@ -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>
2 changes: 1 addition & 1 deletion src/lib/datepicker/datepicker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,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,
Expand Down