Skip to main content

Interpolation

Angular template interpolation ({{ ... }}) is the way of telling Angular to use data from the component class in the view.

Angular will keep track of the expression inside the curly braces and update the view whenever it considers it necessary.

Back to our previous example:

@Component({
selector: 'mc-greetings',
template: `<h1>Hello, {{ name }}!</h1>`,
})
class Greetings {
protected readonly name = '๐Ÿ‘จโ€๐Ÿณ Younes';
}

Here, {{ name }} is an interpolation. If the value of name changes, Angular will automatically update the displayed text.

This is what we call one-way data binding. It's a binding from the component's state to the view.

Expressions use a limited subset of ECMAScript features

You cannot use more complex ones such as multiple statements or assignments or try/catch blocks etc.

Keep expressions simple

While expressions are powerful enough to express complex logic โ€” such as name && (friendlynessFactor ?? 0) > 0.5 ? name : 'Guest', I highly recommend to keep them simple and move complex logic out of templates.

What about security?โ€‹

The results or expressions are HTML-escaped, therefore they are safe by design.

The following example:

@Component({
selector: 'mc-greetings',
template: `<h1>Hello, {{ name }}!</h1>`,
})
class Greetings {
protected readonly name = '<b>๐Ÿ‘จโ€๐Ÿณ Younes</b>';
}

will produce the following output:

<h1>Hello &lt;b&gt;๐Ÿ‘จโ€๐Ÿณ Younes&lt;/b&gt;!</h1>
๐Ÿ”’ HTML-Escaping won't always save you

Interpolation does HTML-escaping, but depending on the context, you might need a different escaping.

Given the following unsafe example:

@Component({
selector: 'mc-user-profile-link',
template: `<a href="https://my-app.marmicode.io/users/{{ userId }}"
>Go to profile</a
>`,
})
class UserProfileLink {
/* ๐Ÿ‘น Assuming `userId` is somehow controlled by the attacker.. */
protected readonly userId =
'../redirect?url=https://evil.marmicode.io/gotcha';
}

The result will be:

<a
href="https://my-app.marmicode.io/users/../redirect?url=https://evil.marmicode.io/gotcha"
>Go to profile</a
>

Clicking on the link will redirect the victim to https://evil.marmicode.io/gotcha.

Escape depending on the context and prefer property binding

It is up to you to escape uncontrolled data when used in non-HTML contexts.

@Component({
selector: 'mc-user-profile-link',
template: `<a href="https://my-app.marmicode.io/users/{{ userId }}"
>Go to profile</a
>`,
})
class UserProfileLink {
/* ๐Ÿ‘น Assuming `userId` is somehow controlled by the attacker.. */
protected readonly userId = encodeURIComponent(
'../redirect?url=https://evil.marmicode.io/gotcha',
);
}

Also, prefer property binding over interpolation when applicable.

@Component({
selector: 'mc-user-profile-link',
template: `<a [href]="getProfileUrl()">Go to profile</a>`,
})
class UserProfileLink {
/* ๐Ÿ‘น Assuming `userId` is somehow controlled by the attacker.. */
protected readonly userId = encodeURIComponent(
'../redirect?url=https://evil.marmicode.io/gotcha',
);

getProfileUrl() {
return `https://my-app.marmicode.io/users/${encodeURIComponent(this.userId)}`;
}
}

This avoids simplifies the template, and guarantees proper escaping.

Pragmatic Angular Testing
๐Ÿ‘จ๐Ÿปโ€๐Ÿณ Let's cook some tests โ†’

๐Ÿ’ฐ 80โ‚ฌ ยท 170โ‚ฌ ยท Lifetime access

Learn how to write reliable tests that survive upgrades and refactorings.