Recipe 7.6
Specifying a Validation Pattern
Demo
URL does not match pattern
URL matches pattern
Match details:
Code
JavaScript
const form = document.querySelector('form');
const resultsContainer = document.querySelector('#results');
form.addEventListener('submit', event => {
event.preventDefault();
const data = new FormData(event.target);
const patterns = {};
if (data.get('hostname')) {
patterns.hostname = data.get('hostname');
}
if (data.get('pathname')) {
patterns.pathname = data.get('pathname');
}
const pattern = new window.URLPattern(patterns);
// Attempt to match our pattern against our URL.
const matcher = pattern.exec(data.get('url'));
// `matcher` is null if the URL doesn't match.
if (!matcher) {
console.log('URL does not match pattern')
const results = document.querySelector('#result-template-noMatch').content.cloneNode(true).firstElementChild;
results.querySelector('.url').textContent = data.get('url');
resultsContainer.replaceChildren(results);
} else {
console.log('URL matches pattern');
console.log('Matcher data:', matcher);
const results = document.querySelector('#result-template-match').content.cloneNode(true).firstElementChild;
results.querySelector('.url').textContent = data.get('url');
const details = results.querySelector('.details');
// The matcher has multiple groups for each placeholder, we'll render
// each separately.
details.appendChild(renderMatchGroup(matcher, 'hostname'));
details.appendChild(renderMatchGroup(matcher, 'pathname'));
resultsContainer.replaceChildren(results);
}
});
function renderMatchGroup(matcher, key) {
const groupList = document.createElement('ul');
const group = document.createElement('li');
group.innerHTML = `<strong>${key}</strong>: <span class="font-monospace">${matcher[key].input}</span>`;
groupList.appendChild(group);
const matchGroups = document.createElement('ul');
for (const groupKey of Object.keys(matcher[key].groups)) {
if (groupKey === '0') {
continue;
}
const item = document.createElement('li');
item.innerHTML = `<strong>${groupKey}</strong>: <code>${matcher[key].groups[groupKey]}`;
matchGroups.appendChild(item);
}
groupList.appendChild(matchGroups);
return groupList;
}
HTML
<!-- Template to render a URL that doesn't match -->
<template id="result-template-noMatch">
<div class="alert alert-danger mt-4">
<h4 class="url mb-2"></h4>
<div class="my-2">URL does not match pattern</div>
</div>
</template>
<!-- Template to render a matching URL -->
<template id="result-template-match">
<div class="alert alert-success mt-4">
<h4 class="url text-2xl mb-2"></h4>
<div class="my-2">URL matches pattern</div>
<div class="my-2 fw-bold">Match details:</div>
<ul class="details">
</ul>
</div>
</template>
<form>
<fieldset class="mb-3">
<legend>URL patterns</legend>
<div class="mb-3">
<label class="form-label" for="url">Host name</label>
<input class="form-control" id="hostname" type="text" name="hostname">
</div>
<div class="mb-3">
<label class="form-label" for="url">Path name</label>
<input class="form-control" id="pathname" type="text" name="pathname" value="/api/users/:userId">
</div>
</fieldset>
<div class="mb-3">
<label class="form-label" for="url">URL to match</label>
<input class="form-control" id="url" type="url" required name="url" value="https://example.com/api/users/sysadmin">
</div>
<button class="btn btn-primary">Check URL</button>
</form>
<div id="results"></div>