Skip to content

Commit

Permalink
fix: image re-rendering for movie details
Browse files Browse the repository at this point in the history
  • Loading branch information
jgelin committed Jul 18, 2023
1 parent 366ad56 commit d0f2278
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 30 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<article class="movie-detail-wrapper">
<ng-container *rxLet="movie$; let movie">
<ui-detail-grid [style.opacity]="!!movie ? 1 : 0">
<div detailGridMedia>
<ui-detail-grid [style.opacity]="!!movie ? 1 : 0" [rerenderDetailGridMedia]="movie.imgSrc">
<ng-template #detailGridMedia>
<img
class="aspectRatio-2-3 fit-cover"
[ngSrc]="movie.imgSrc"
Expand All @@ -14,8 +14,8 @@
[title]="movie.title"
data-uf="hero-img"
/>
</div>
<div detailGridDescription>
</ng-template>
<ng-template #detailGridDescription>
<header>
<h1 data-uf="header-main">{{ movie.title }}</h1>
<h2 data-uf="header-sub">{{ movie.tagline }}</h2>
Expand Down Expand Up @@ -166,7 +166,7 @@ <h3>The Cast</h3>
>&nbsp;Back
</button>
</section>
</div>
</ng-template>
</ui-detail-grid>
<div class="loader" *ngIf="!movie"></div>
</ng-container>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {select, selectSlice} from '@rx-angular/state/selections';
import {Location, NgFor, NgIf, NgOptimizedImage} from '@angular/common';
import { select, selectSlice } from '@rx-angular/state/selections';
import { Location, NgFor, NgIf, NgOptimizedImage } from '@angular/common';
import {
ChangeDetectionStrategy,
Component,
Expand All @@ -9,21 +9,20 @@ import {
ViewChild,
ViewEncapsulation,
} from '@angular/core';
import {filter, map, mergeWith, tap} from 'rxjs';
import {TMDBMovieGenreModel} from '../../data-access/api/model/movie-genre.model';

import {MovieCast, MovieDetailAdapter} from './movie-detail-page.adapter';
import {RxActionFactory} from '@rx-angular/state/actions';
import {RxEffects} from '@rx-angular/state/effects';
import {DetailGridComponent} from '../../ui/component/detail-grid/detail-grid.component';
import {StarRatingComponent} from '../../ui/pattern/star-rating/star-rating.component';
import {MovieListComponent} from '../../ui/pattern/movie-list/movie-list.component';
import {RxLet} from '@rx-angular/template/let';
import {BypassSrcDirective} from '../../shared/cdk/bypass-src.directive';
import {RxFor} from '@rx-angular/template/for';
import {FastSvgComponent} from '@push-based/ngx-fast-svg';
import {RxIf} from '@rx-angular/template/if';
import {RouterLink} from '@angular/router';
import { filter, map, mergeWith, tap } from 'rxjs';
import { TMDBMovieGenreModel } from '../../data-access/api/model/movie-genre.model';
import { MovieCast, MovieDetailAdapter } from './movie-detail-page.adapter';
import { RxActionFactory } from '@rx-angular/state/actions';
import { RxEffects } from '@rx-angular/state/effects';
import { DetailGridComponent } from '../../ui/component/detail-grid/detail-grid.component';
import { StarRatingComponent } from '../../ui/pattern/star-rating/star-rating.component';
import { MovieListComponent } from '../../ui/pattern/movie-list/movie-list.component';
import { RxLet } from '@rx-angular/template/let';
import { BypassSrcDirective } from '../../shared/cdk/bypass-src.directive';
import { RxFor } from '@rx-angular/template/for';
import { FastSvgComponent } from '@push-based/ngx-fast-svg';
import { RxIf } from '@rx-angular/template/if';
import { RouterLink } from '@angular/router';

@Component({
standalone: true,
Expand Down Expand Up @@ -87,7 +86,10 @@ export default class MovieDetailPageComponent {
}>
) {
this.effects.register(
this.ui.dialog$.pipe(map((v) => v === 'show'), tap(console.log)),
this.ui.dialog$.pipe(
map((v) => v === 'show'),
tap(console.log)
),
(openDialog) =>
openDialog
? this.trailerDialog?.nativeElement?.showModal()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<article *rxLet="personCtx$; let personCtx">
<ng-container *ngIf="personCtx?.value as person; else loading">
<ui-detail-grid>
<div detailGridMedia>
<ng-template #detailGridMedia>
<img
class="aspectRatio-2-3 fit-cover"
[ngSrc]="person.imgSrc"
Expand All @@ -14,8 +14,8 @@
[title]="person?.name"
data-uf="hero-img"
/>
</div>
<div detailGridDescription>
</ng-template>
<ng-template #detailGridDescription>
<header>
<h1>{{ person.name }}</h1>
<h2>{{ person.birthday }}</h2>
Expand All @@ -39,7 +39,7 @@ <h3>The Biography</h3>
<fast-svg name="back" size="1em"></fast-svg>&nbsp; Back
</button>
</section>
</div>
</ng-template>
</ui-detail-grid>
</ng-container>
<ng-template #loading>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,65 @@
import {
ChangeDetectionStrategy,
Component,
ContentChild,
Input,
OnChanges,
SimpleChanges,
TemplateRef,
ViewChild,
ViewContainerRef,
ViewEncapsulation,
} from '@angular/core';
import { NgTemplateOutlet } from '@angular/common';

@Component({
standalone: true,
selector: 'ui-detail-grid',
template: `
<div class="grid--item gradient">
<ng-content select="[detailGridMedia]"></ng-content>
<ng-container
#detailGridMediaOutlet
[ngTemplateOutlet]="detailGridMediaRef"
></ng-container>
</div>
<div class="grid--item media">
<ng-content select="[detailGridDescription]"></ng-content>
<ng-container [ngTemplateOutlet]="detailGridDescription"></ng-container>
</div>
`,
styleUrls: ['./detail-grid.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
encapsulation: ViewEncapsulation.Emulated,
imports: [NgTemplateOutlet],
})
export class DetailGridComponent {}
export class DetailGridComponent implements OnChanges {
@ContentChild('detailGridMedia', { read: TemplateRef })
detailGridMediaRef!: TemplateRef<unknown>;
@ContentChild('detailGridDescription', { read: TemplateRef })
detailGridDescription!: TemplateRef<unknown>;

/**
* Each time a new value is set to the input rerenderDetailGridMedia (any type), rerender the block `detailGridMedia` (usually the img)
* Hacky way to solve issue https://github.com/angular/angular/issues/47813
*/
@Input() rerenderDetailGridMedia: unknown;
@ViewChild('detailGridMediaOutlet', { read: ViewContainerRef })
outletRef!: ViewContainerRef;

ngOnChanges(changes: SimpleChanges): void {
if (
changes['rerenderDetailGridMedia'] &&
!changes['rerenderDetailGridMedia'].isFirstChange()
) {
this.doRerenderDetailGridMedia();
}
}

private doRerenderDetailGridMedia(): void {
if (!this.outletRef) {
return;
}

this.outletRef.clear();
this.outletRef.createEmbeddedView(this.detailGridMediaRef);
}
}

0 comments on commit d0f2278

Please sign in to comment.