Angular
This section describes how to integrate user preferences functionality in Angular Applications.
This document will cover the methods to integrate User Preferences in your Angular Applications. Your users will be able to specify their notification preferences using this page. With SuprSend, the user can set preferences at 3 levels - communication channel, notification category, and selected channels inside a category. We'll cover methods to read and update data at all 3 levels.
There's an example code to add our pre-defined UI at the end of this documentation. This is how a typical preference page will look like
All the data points and functions are same as Javascript application
Pre-requisites
- Integrate Javascript SDK
- Identify user on login and reset on logout to ensure that preference changes are tagged to the correct user
- Configure notification categories on SuprSend dashboard
- Understanding of the preference data structure and methods
Integration
All preference methods and properties are available under suprsend.user.preferences instance. Here's a reference of all the properties and methods available in this instance. Please read to javascript documentation to understand all these methods and properties in detail
Read Preferences data
There will be 3 components: preference, channel-level-preferences, and category-level-preferences. preference will be the main component and inside it, there will be an instance property that contains user preference data. Whenever there's an update we will update the latest preference data in the same state for the component to rerender.
import suprsend from "@suprsend/web-sdk";
// this is main component
@Component({
selector: 'app-preference',
templateUrl: './preference.component.html',
styleUrls: ['./preference.component.css'],
})
export class PreferenceComponent implements OnInit {
preferencesData: any = null;
...
}
Step 1. Get Preference data
After adding the component, call suprsend.user.preferences.get_preferences() method to get the preferences data for the already identified user. This method is used to get full user preferences data from the SuprSend. This method should be called first before any update methods. Calling this method will make an API call and returns a preference response, which you can store in your instance property preferenceData if there is no error.
Step 2. Configure Event Listeners
After calling get_preferences, call these 2 event listeners
- preferences_updated - This event is fired when you get a successful response after calling
get_preferences
method. In the callback, you will get the latest preference data as a parameter. You can use this data to update the latest preference data in the existing instance property preferenceData for the component to render. - preferences_error - When there are validation errors or API errors SDK will fire preferences_error event. In the callback, you will then get error-related information as a parameter.
@Component({...})
export class PreferenceComponent implements OnInit {
preferencesData: any = null;
ngOnInit(): void {
suprsend.user.preferences.get_preferences().then((resp) => {
if (resp.error) {
console.log(resp.message);
} else {
this.preferencesData = resp;
}
});
// listen for update in preferences data
suprsend.emitter.on('preferences_updated', (preferenceData) => {
this.preferencesData = { ...preferenceData };
});
// listen for errors
suprsend.emitter.on('preferences_error', (error) => {
console.log('ERROR:', error);
});
}
}
Show Preference data on the UI
Preferences data is of 2 types:
- Category Preference - User can set preferences at overall category level or select specific channels in a category from this section.
- Channel Preferences - User can set preferences at overall channel level from this section.
Code block to Render Header and Blank state
Our Main component preference has 2 child components one for each type of preference.
<p *ngIf="!this.preferencesData">Loading...</p>
<div *ngIf="this.preferencesData" class="main-div">
<h3 class="main-header">Notification Preferences</h3>
<!-- notification category level preferences -->
<app-category-level-preferences [preferencesData]="this.preferencesData"></app-category-level-preferences>
<!-- channel level preferences -->
<app-channel-level-preferences [preferencesData]="this.preferencesData"></app-channel-level-preferences>
</div>
Show Category level Preference section on the UI
In category-level preferences, you'll have to fetch the data from 3 parts:
- Section - to show sections like "Product Updates" in below example
- Category - to show categories and their overall status like "Refunds" in below example
- CategoryChannel - to show communication channels inside the category and their status
Below are the steps to render category preference UI:
- Loop through the property preferenceData.sections for showing sections, show sub-categories inside each section, and show subcategory's channels inside each sub-category.
- Add a switch button next to each sub-category for opting in and out of the category. Add checkbox components in sub-category channels for opting in and out of category-channel. You can use any third-party npm package to import these components or design your own component.
- To update category preference on the click of the switch button, call update_category_preference method and if no error is received in response, update the latest data in the instance property. For preference state
opt-in
set the switch state as on and off for theopt-out
state.
- To update category-channel preference on the click of checkbox next to each channel, call the update_channel_preference_in_category method. Update the latest data in the instance property if no error is received in response. For preference state
opt-in
set the checkbox state as checked and unchecked for theopt-out
state.
Code block to Render Category section
import { Component, Input } from '@angular/core';
import suprsend, { PreferenceOptions } from '@suprsend/web-sdk';
@Component({
selector: 'app-category-level-preferences',
templateUrl: './category-level-preferences.component.html',
styleUrls: ['./category-level-preferences.component.css'],
})
export class CategoryLevelPreferencesComponent {
@Input() public preferencesData: any;
handleCategoryPreferenceChange(e: boolean, subcategory: string) {
const resp = suprsend.user.preferences.update_category_preference(
subcategory,
e ? PreferenceOptions.OPT_IN : PreferenceOptions.OPT_OUT
);
if (resp.error) {
console.log(resp.message);
} else {
this.preferencesData = { ...resp };
}
}
handleChannelPreferenceInCategoryChange(channel: any, category: string) {
if (!channel.is_editable) return;
const resp =
suprsend.user.preferences.update_channel_preference_in_category(
channel.channel,
channel.preference === PreferenceOptions.OPT_IN
? PreferenceOptions.OPT_OUT
: PreferenceOptions.OPT_IN,
category
);
if (resp.error) {
console.log(resp.message);
} else {
this.preferencesData = { ...resp };
}
}
}
<div
*ngFor="let section of this.preferencesData.sections"
class="cat-container"
>
<div *ngIf="section.name">
<div class="section-name-container">
<p class="section-name-text">{{ section.name }}</p>
<p class="section-description-text">{{ section.description }}</p>
</div>
</div>
<div *ngFor="let subcategory of section.subcategories">
<div class="subcategory-container">
<div class="subcategory-top-div">
<div>
<p class="subcategory-name">{{ subcategory.name }}</p>
<p class="subcategory-description">{{ subcategory.description }}</p>
</div>
<ui-switch
size="small"
color="#2463eb"
[disabled]="!subcategory.is_editable"
[checked]="subcategory.preference === 'opt_in'"
(change)="
handleCategoryPreferenceChange($event, subcategory.category)
"
></ui-switch>
</div>
<div class="subcategory-channel-container">
<div
*ngFor="let channel of subcategory.channels"
class="category-channel-checkbox"
>
<input
type="checkbox"
[id]="subcategory.category + '-' + channel.channel"
[disabled]="!channel.is_editable"
[checked]="channel.preference === 'opt_in'"
(change)="
handleChannelPreferenceInCategoryChange(
channel,
subcategory.category
)
"
/>
<label
class="category-channel-label"
[for]="subcategory.category + '-' + channel.channel"
>{{ channel.channel }}</label
>
</div>
</div>
</div>
</div>
</div>
Show Channel level Preference section on the UI
Below are the steps to render channel preference UI:
- Loop through the property preferenceData.channel_preferences for showing channels and for every channel item we will show an option to select preference using radio buttons.
- Add a radio button next, against channel level options for switching from
all
torequired
preference in channel. - To update channel preference on the click of the radio button, call update_overall_channel_preference method, and if no error is received in response, update the latest data in the state.
Code block to Render Channel section
import { Component, Input } from '@angular/core';
import suprsend, { ChannelLevelPreferenceOptions } from '@suprsend/web-sdk';
@Component({
selector: 'app-channel-level-preferences',
templateUrl: './channel-level-preferences.component.html',
styleUrls: ['./channel-level-preferences.component.css'],
})
export class ChannelLevelPreferencesComponent {
@Input() public preferencesData: any;
handleChange(channel: string, preference: string) {
const preferenceStatus =
preference === 'ALL'
? ChannelLevelPreferenceOptions.ALL
: ChannelLevelPreferenceOptions.REQUIRED;
const resp = suprsend.user.preferences.update_overall_channel_preference(
channel,
preferenceStatus
);
if (resp.error) {
console.log(resp.message);
} else {
this.preferencesData = { ...resp };
}
}
}
<div>
<div class="channel-header-div">
<p class="channel-header-p">What notifications to allow for channel?</p>
</div>
<div>
<div *ngFor="let channel of this.preferencesData.channel_preferences">
<div class="channel-container">
<p class="channel-channel-text">{{ channel.channel }}</p>
<p
class="channel-help-text"
*ngIf="channel.is_restricted; else allText"
>
Allow required notifications only
</p>
<ng-template #allText
><p class="channel-help-text">Allow all notifications</p>
</ng-template>
<div class="channel-radio-container">
<p class="channel-radio-pref-text">
{{ channel.channel }} Preferences
</p>
<div class="radio-grp">
<div class="radio-grp-2">
<div class="radio-grp-container">
<div>
<input
type="radio"
[checked]="!channel.is_restricted"
name="all-{{ channel.channel }}"
id="all-{{ channel.channel }}"
(change)="handleChange(channel.channel, 'ALL')"
/>
</div>
<label class="all-label" for="all-{{ channel.channel }}">
All
</label>
</div>
<p class="channel-radiohelp-text">
Allow All Notifications, except the ones that I have turned off
</p>
</div>
<div>
<div class="radio-grp-container">
<div>
<input
type="radio"
name="required-{{ channel.channel }}"
id="required-{{ channel.channel }}"
[checked]="channel.is_restricted"
(change)="handleChange(channel.channel, 'REQUIRED')"
/>
</div>
<label
class="required-label"
for="required-{{ channel.channel }}"
>
Required
</label>
</div>
<p class="channel-radiohelp-text">
Allow only important notifications related to account and
security settings
</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
Example Code to Render Full Preference Page
You can refer to our angular-example GitHub repository to get check the full code.
Updated 2 months ago