Skip to content

Commit ddeef60

Browse files
crisbetoAndrewKushnir
authored andcommitted
refactor(compiler): support viewport trigger options in pipeline (angular#64130)
Updates the template pipeline to support options for the `viewport` triggers. PR Close angular#64130
1 parent e2367c8 commit ddeef60

File tree

12 files changed

+276
-11
lines changed

12 files changed

+276
-11
lines changed

packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_deferred/GOLDEN_PARTIAL.js

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1291,3 +1291,128 @@ export declare class TestCmp {
12911291
static ɵcmp: i0.ɵɵComponentDeclaration<TestCmp, "test-cmp", never, {}, {}, never, never, true, never>;
12921292
}
12931293

1294+
/****************************************************************************************************
1295+
* PARTIAL FILE: deferred_on_viewport_with_options.js
1296+
****************************************************************************************************/
1297+
import { Component } from '@angular/core';
1298+
import * as i0 from "@angular/core";
1299+
export class MyApp {
1300+
constructor() {
1301+
this.message = 'hello';
1302+
}
1303+
}
1304+
MyApp.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDER", ngImport: i0, type: MyApp, deps: [], target: i0.ɵɵFactoryTarget.Component });
1305+
MyApp.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "0.0.0-PLACEHOLDER", type: MyApp, isStandalone: true, selector: "ng-component", ngImport: i0, template: `
1306+
{{message}}
1307+
@defer (on viewport({trigger: button, rootMargin: '123px', threshold: 59})) {
1308+
{{message}}
1309+
} @placeholder {
1310+
<button #button>Click me</button>
1311+
}
1312+
`, isInline: true });
1313+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDER", ngImport: i0, type: MyApp, decorators: [{
1314+
type: Component,
1315+
args: [{
1316+
template: `
1317+
{{message}}
1318+
@defer (on viewport({trigger: button, rootMargin: '123px', threshold: 59})) {
1319+
{{message}}
1320+
} @placeholder {
1321+
<button #button>Click me</button>
1322+
}
1323+
`,
1324+
}]
1325+
}] });
1326+
1327+
/****************************************************************************************************
1328+
* PARTIAL FILE: deferred_on_viewport_with_options.d.ts
1329+
****************************************************************************************************/
1330+
import * as i0 from "@angular/core";
1331+
export declare class MyApp {
1332+
message: string;
1333+
static ɵfac: i0.ɵɵFactoryDeclaration<MyApp, never>;
1334+
static ɵcmp: i0.ɵɵComponentDeclaration<MyApp, "ng-component", never, {}, {}, never, never, true, never>;
1335+
}
1336+
1337+
/****************************************************************************************************
1338+
* PARTIAL FILE: deferred_prefetch_on_viewport_with_options.js
1339+
****************************************************************************************************/
1340+
import { Component } from '@angular/core';
1341+
import * as i0 from "@angular/core";
1342+
export class MyApp {
1343+
constructor() {
1344+
this.message = 'hello';
1345+
}
1346+
}
1347+
MyApp.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDER", ngImport: i0, type: MyApp, deps: [], target: i0.ɵɵFactoryTarget.Component });
1348+
MyApp.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "0.0.0-PLACEHOLDER", type: MyApp, isStandalone: true, selector: "ng-component", ngImport: i0, template: `
1349+
{{message}}
1350+
@defer (prefetch on viewport({trigger: button, rootMargin: '123px', threshold: 59})) {
1351+
{{message}}
1352+
} @placeholder {
1353+
<button #button>Click me</button>
1354+
}
1355+
`, isInline: true });
1356+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDER", ngImport: i0, type: MyApp, decorators: [{
1357+
type: Component,
1358+
args: [{
1359+
template: `
1360+
{{message}}
1361+
@defer (prefetch on viewport({trigger: button, rootMargin: '123px', threshold: 59})) {
1362+
{{message}}
1363+
} @placeholder {
1364+
<button #button>Click me</button>
1365+
}
1366+
`,
1367+
}]
1368+
}] });
1369+
1370+
/****************************************************************************************************
1371+
* PARTIAL FILE: deferred_prefetch_on_viewport_with_options.d.ts
1372+
****************************************************************************************************/
1373+
import * as i0 from "@angular/core";
1374+
export declare class MyApp {
1375+
message: string;
1376+
static ɵfac: i0.ɵɵFactoryDeclaration<MyApp, never>;
1377+
static ɵcmp: i0.ɵɵComponentDeclaration<MyApp, "ng-component", never, {}, {}, never, never, true, never>;
1378+
}
1379+
1380+
/****************************************************************************************************
1381+
* PARTIAL FILE: deferred_hydrate_on_viewport_with_options.js
1382+
****************************************************************************************************/
1383+
import { Component } from '@angular/core';
1384+
import * as i0 from "@angular/core";
1385+
export class MyApp {
1386+
constructor() {
1387+
this.message = 'hello';
1388+
}
1389+
}
1390+
MyApp.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDER", ngImport: i0, type: MyApp, deps: [], target: i0.ɵɵFactoryTarget.Component });
1391+
MyApp.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "0.0.0-PLACEHOLDER", type: MyApp, isStandalone: true, selector: "ng-component", ngImport: i0, template: `
1392+
{{message}}
1393+
@defer (hydrate on viewport({rootMargin: '123px', threshold: 59})) {
1394+
{{message}}
1395+
}
1396+
`, isInline: true });
1397+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDER", ngImport: i0, type: MyApp, decorators: [{
1398+
type: Component,
1399+
args: [{
1400+
template: `
1401+
{{message}}
1402+
@defer (hydrate on viewport({rootMargin: '123px', threshold: 59})) {
1403+
{{message}}
1404+
}
1405+
`,
1406+
}]
1407+
}] });
1408+
1409+
/****************************************************************************************************
1410+
* PARTIAL FILE: deferred_hydrate_on_viewport_with_options.d.ts
1411+
****************************************************************************************************/
1412+
import * as i0 from "@angular/core";
1413+
export declare class MyApp {
1414+
message: string;
1415+
static ɵfac: i0.ɵɵFactoryDeclaration<MyApp, never>;
1416+
static ɵcmp: i0.ɵɵComponentDeclaration<MyApp, "ng-component", never, {}, {}, never, never, true, never>;
1417+
}
1418+

packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_deferred/TEST_CASES.json

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,51 @@
329329
"failureMessage": "Defer block output with import alias does not match deferred_import_alias.js (possible alias resolution regression)"
330330
}
331331
]
332+
},
333+
{
334+
"description": "should generate a defer block with a `on viewport` trigger that has options",
335+
"inputFiles": ["deferred_on_viewport_with_options.ts"],
336+
"expectations": [
337+
{
338+
"files": [
339+
{
340+
"expected": "deferred_on_viewport_with_options_template.js",
341+
"generated": "deferred_on_viewport_with_options.js"
342+
}
343+
],
344+
"failureMessage": "Incorrect template"
345+
}
346+
]
347+
},
348+
{
349+
"description": "should generate a defer block with a `prefetch on viewport` trigger that has options",
350+
"inputFiles": ["deferred_prefetch_on_viewport_with_options.ts"],
351+
"expectations": [
352+
{
353+
"files": [
354+
{
355+
"expected": "deferred_prefetch_on_viewport_with_options_template.js",
356+
"generated": "deferred_prefetch_on_viewport_with_options.js"
357+
}
358+
],
359+
"failureMessage": "Incorrect template"
360+
}
361+
]
362+
},
363+
{
364+
"description": "should generate a defer block with a `hydrate on viewport` trigger that has options",
365+
"inputFiles": ["deferred_hydrate_on_viewport_with_options.ts"],
366+
"expectations": [
367+
{
368+
"files": [
369+
{
370+
"expected": "deferred_hydrate_on_viewport_with_options_template.js",
371+
"generated": "deferred_hydrate_on_viewport_with_options.js"
372+
}
373+
],
374+
"failureMessage": "Incorrect template"
375+
}
376+
]
332377
}
333378
]
334379
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import {Component} from '@angular/core';
2+
3+
@Component({
4+
template: `
5+
{{message}}
6+
@defer (hydrate on viewport({rootMargin: '123px', threshold: 59})) {
7+
{{message}}
8+
}
9+
`,
10+
})
11+
export class MyApp {
12+
message = 'hello';
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
function MyApp_Template(rf, ctx) {
2+
if (rf & 1) {
3+
$r3$.ɵɵtext(0);
4+
$r3$.ɵɵdomTemplate(1, MyApp_Defer_1_Template, 1, 1);
5+
$r3$.ɵɵdefer(2, 1, null, null, null, null, null, null, null, 1);
6+
$r3$.ɵɵdeferHydrateOnViewport({rootMargin: "123px", threshold: 59});
7+
$r3$.ɵɵdeferOnIdle();
8+
}
9+
if (rf & 2) {
10+
$r3$.ɵɵtextInterpolate1(" ", ctx.message, " ");
11+
}
12+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import {Component} from '@angular/core';
2+
3+
@Component({
4+
template: `
5+
{{message}}
6+
@defer (on viewport({trigger: button, rootMargin: '123px', threshold: 59})) {
7+
{{message}}
8+
} @placeholder {
9+
<button #button>Click me</button>
10+
}
11+
`,
12+
})
13+
export class MyApp {
14+
message = 'hello';
15+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
function MyApp_Template(rf, ctx) {
2+
if (rf & 1) {
3+
$r3$.ɵɵtext(0);
4+
$r3$.ɵɵdomTemplate(1, MyApp_Defer_1_Template, 1, 1)(2, MyApp_DeferPlaceholder_2_Template, 3, 0);
5+
$r3$.ɵɵdefer(3, 1, null, null, 2);
6+
$r3$.ɵɵdeferOnViewport(0, -1, {rootMargin: "123px", threshold: 59});
7+
}
8+
if (rf & 2) {
9+
$r3$.ɵɵtextInterpolate1(" ", ctx.message, " ");
10+
}
11+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import {Component} from '@angular/core';
2+
3+
@Component({
4+
template: `
5+
{{message}}
6+
@defer (prefetch on viewport({trigger: button, rootMargin: '123px', threshold: 59})) {
7+
{{message}}
8+
} @placeholder {
9+
<button #button>Click me</button>
10+
}
11+
`,
12+
})
13+
export class MyApp {
14+
message = 'hello';
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
function MyApp_Template(rf, ctx) {
2+
if (rf & 1) {
3+
$r3$.ɵɵtext(0);
4+
$r3$.ɵɵdomTemplate(1, MyApp_Defer_1_Template, 1, 1)(2, MyApp_DeferPlaceholder_2_Template, 3, 0);
5+
$r3$.ɵɵdefer(3, 1, null, null, 2);
6+
$r3$.ɵɵdeferPrefetchOnViewport(0, -1, {rootMargin: "123px", threshold: 59});
7+
$r3$.ɵɵdeferOnIdle();
8+
}
9+
if (rf & 2) {
10+
$r3$.ɵɵtextInterpolate1(" ", ctx.message, " ");
11+
}
12+
}

packages/compiler/src/template/pipeline/ir/src/ops/create.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1408,6 +1408,7 @@ interface DeferInteractionTrigger extends DeferTriggerWithTargetBase {
14081408

14091409
interface DeferViewportTrigger extends DeferTriggerWithTargetBase {
14101410
kind: DeferTriggerKind.Viewport;
1411+
options: o.Expression | null;
14111412
}
14121413

14131414
/**

packages/compiler/src/template/pipeline/src/ingest.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -849,6 +849,9 @@ function ingestDeferTriggers(
849849
targetSlot: null,
850850
targetView: null,
851851
targetSlotViewSteps: null,
852+
options: triggers.viewport.options
853+
? convertAst(triggers.viewport.options, unit.job, triggers.viewport.sourceSpan)
854+
: null,
852855
},
853856
modifier,
854857
triggers.viewport.sourceSpan,

0 commit comments

Comments
 (0)