Skip to content

Commit ed4aeae

Browse files
committed
✨ update dom on page changes
1 parent 1bbf511 commit ed4aeae

File tree

4 files changed

+67
-27
lines changed

4 files changed

+67
-27
lines changed

client/page.js

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,22 @@ delete state.page
1111

1212
const pageProxyHandler = {
1313
set(target, name, value, receiver) {
14-
if (name === 'title') {
15-
document.title = value
16-
}
1714
const result = Reflect.set(target, name, value, receiver)
1815
if (name === 'title') {
16+
document.title = value
17+
document.querySelector('head > meta[property="og:title"]').setAttribute('content', value)
1918
windowEvent('page')
19+
} else if (name === 'description') {
20+
document.querySelector('head > meta[name="description"]').setAttribute('content', value)
21+
document.querySelector('head > meta[property="og:description"]').setAttribute('content', value)
22+
} else if (name === 'locale') {
23+
document.querySelector('html').setAttribute('lang', value)
24+
document.querySelector('head > meta[property="og:locale"]').setAttribute('content', value)
25+
} else if (name === 'image') {
26+
document.querySelector('head > meta[property="og:image"]').setAttribute('content', value)
27+
} else if (name === 'canonical') {
28+
canonical = (path.indexOf('//') === -1) ? router.base + value : value
29+
document.querySelector('head > link[rel="canonical"]').setAttribute('href', canonical)
2030
}
2131
client.update()
2232
return result

server/template.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,20 +39,20 @@ export default function ({ head, body, nextBody, context, instances }) {
3939
context: environment.mode === 'spa' ? {} : serializableContext,
4040
}
4141
return `<!DOCTYPE html>
42-
<html${page.locale ? ` lang="${page.locale}"` : ''}>
42+
<html lang="${page.locale || ''}">
4343
<head>
4444
<meta charset="utf-8">
4545
<meta name="generator" content="Created with Nullstack - https://nullstack.app" />
46-
${page.title ? `<title>${page.title}</title>` : ''}
46+
<title>${page.title || ''}</title>
4747
<meta property="og:image" content="${image}">
48-
${page.description ? `<meta property="og:description" content="${page.description}">` : ''}
49-
${page.description ? `<meta name="description" content="${page.description}">` : ''}
50-
${page.title ? `<meta property="og:title" content="${page.title}">` : ''}
48+
<meta property="og:description" content="${page.description || ''}">
49+
<meta name="description" content="${page.description || ''}">
50+
<meta property="og:title" content="${page.title || ''}">
5151
${project.type ? `<meta property="og:type" content="${project.type}">` : ''}
5252
${project.name ? `<meta property="og:site_name" content="${project.name}">` : ''}
5353
<meta property="og:url" content="${canonical}">
5454
<link rel="canonical" href="${canonical}">
55-
${page.locale ? `<meta property="og:locale" content="${page.locale}">` : ''}
55+
<meta property="og:locale" content="${page.locale || ''}">
5656
<link rel="shortcut icon" href="${cdn(project.favicon)}" type="image/png">
5757
<link rel="icon" href="${cdn(project.favicon)}" type="image/png">
5858
<link rel="manifest" href="/manifest.webmanifest" integrity="${integrities['manifest.webmanifest'] || ''}">

tests/src/ContextPage.njs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,20 +35,25 @@ class ContextPage extends Nullstack {
3535
await this.raiseStatus({ status })
3636
}
3737

38+
updateHead({ page }) {
39+
page.title = 'Nullstack Tests Updated'
40+
page.image = '/image-updated.jpg'
41+
page.description = 'Nullstack tests page that tests the context page updated'
42+
page.locale = 'en-US'
43+
}
44+
3845
render({ page }) {
3946
return (
4047
<div>
4148
<div data-event-triggered={this.eventTriggered} />
4249
<div data-page={!!page} />
4350
<div data-changes={page.changes} />
4451
<div data-priority={page.priority} />
45-
<button source={page} onclick={{ title: 'Nullstack Tested' }}>
46-
{' '}
47-
title{' '}
52+
<button onclick={this.requestStatus} data-request-status>
53+
401
4854
</button>
49-
<button onclick={this.requestStatus} status={401}>
50-
{' '}
51-
401{' '}
55+
<button source={page} onclick={this.updateHead} data-update-head>
56+
title
5257
</button>
5358
</div>
5459
)

tests/src/ContextPage.test.js

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
beforeAll(async () => {
2-
await page.goto('http://localhost:6969/context-page')
3-
})
4-
51
describe('ContextPage', () => {
2+
beforeAll(async () => {
3+
await page.goto('http://localhost:6969/context-page')
4+
})
5+
66
test('is part of the client context', async () => {
77
const element = await page.$('[data-page]')
88
expect(element).toBeTruthy()
@@ -73,17 +73,42 @@ describe('ContextPage', () => {
7373
expect(element).toBeTruthy()
7474
})
7575

76-
test('a custom event is triggered when the title changes', async () => {
77-
await page.click('button')
78-
await page.waitForSelector('[data-event-triggered]')
79-
const element = await page.$('[data-event-triggered]')
80-
expect(element).toBeTruthy()
81-
})
82-
8376
test('the page reacts to a server function status', async () => {
84-
await page.click('[status="401"]')
77+
await page.click('[data-request-status]')
8578
await page.waitForSelector('[data-page-status="401"]')
8679
const element = await page.$('[data-page-status="401"]')
8780
expect(element).toBeTruthy()
8881
})
8982
})
83+
84+
describe('ContextPage updated', () => {
85+
beforeAll(async () => {
86+
await page.waitForSelector('[data-application-hydrated]')
87+
await page.goto('http://localhost:6969/context-page')
88+
await page.click('[data-update-head]')
89+
})
90+
91+
test('updates meta og:title', async () => {
92+
await page.waitForSelector('meta[property="og:title"][content="Nullstack Tests Updated"]')
93+
const element = await page.$('meta[property="og:title"][content="Nullstack Tests Updated"]')
94+
expect(element).toBeTruthy()
95+
})
96+
97+
test('updates meta og:description', async () => {
98+
await page.waitForSelector('meta[property="og:description"][content="Nullstack tests page that tests the context page updated"]')
99+
const element = await page.$('meta[property="og:description"][content="Nullstack tests page that tests the context page updated"]')
100+
expect(element).toBeTruthy()
101+
})
102+
103+
test('updates meta description', async () => {
104+
await page.waitForSelector('meta[name="description"][content="Nullstack tests page that tests the context page updated"]')
105+
const element = await page.$('meta[name="description"][content="Nullstack tests page that tests the context page updated"]')
106+
expect(element).toBeTruthy()
107+
})
108+
109+
test('a custom event is triggered when the title changes', async () => {
110+
await page.waitForSelector('[data-event-triggered]')
111+
const element = await page.$('[data-event-triggered]')
112+
expect(element).toBeTruthy()
113+
})
114+
})

0 commit comments

Comments
 (0)