Transform View
The Transform View builds HTML by calling transform functions for each input element. This pattern is different from the Template View, which gets built from the final layout. We apply these transformations in a sequence or loop. The pattern encourages separation of concerns, testability, and logic-focused view layers.
Source Code Listing
code.ts
// Domain Model
const artists = [
{name: "Eminem", genre: "Rap", origin: "Detroit, MI"},
{name: "Deftones", genre: "Alternative Metal", origin: "Sacramento, CA"},
{name: "Sublime", genre: "Ska Punk", origin: "Long Beach, CA"},
];
export class Artist {
static findNamed(name: string | null): Artist | undefined {
if (!name) return undefined;
const artist = artists.find(
(x) => x.name.toLowerCase() === name.toLowerCase(),
);
return artist
? new Artist(artist.name, artist.genre, artist.origin)
: undefined;
}
constructor(
public name: string,
public genre: string,
public origin: string,
) {}
}
// Transform Logic
type ArtistProperty = keyof Artist;
const artistTransforms: Record<ArtistProperty, (value: string) => string> = {
name: (value) => `<h1>${value}</h1>`,
genre: (value) => `<p><strong>Genre:</strong> ${value}</p>`,
origin: (value) => `<p><strong>Origin:</strong> ${value}</p>`,
};
/**
* Implements the transform logic for rendering an artist's view.
* Assumes that we are using the Front Controller pattern.
*/
class ArtistCommand {
constructor(public artist: Artist) {}
renderArtistView(artist: Artist | undefined): string {
if (!artist) return "<p>Artist not found.</p>";
const html: string[] = ['<html><body style="font-family: sans-serif">'];
for (const key of Object.keys(artist) as ArtistProperty[]) {
const value = artist[key];
const transform = artistTransforms[key];
if (transform) {
html.push(transform(value));
}
}
html.push("</body></html>");
return html.join("\n");
}
}
if (import.meta.main) {
const artistName = "Eminem"; // Example artist name
const artist = Artist.findNamed(artistName);
if (!artist) {
console.error(`Artist "${artistName}" not found.`);
process.exit(1);
}
const command = new ArtistCommand(artist);
console.log(command.renderArtistView(artist));
}
[End]