In my previous article, we have added an empty angular element to the SharePoint page. And now we are ready to move forward and add some functionality to our elements.
Before we begin
First of all, let's create in SharePoint Announcements list with the name "Announcements" and add a couple of items with some text. We will access data in our list via the SharePoint REST API, calling "/_api/web/lists/getbytitle('Announcements')/Items" endpoint.
Angular project
Now, open the angular elements project which we have created in the previous article in VS Code.
For convenience let's create an interface to work with our data model. Create the "data" folder wonder the "src/app" and create a new file named Announcement.ts.
Add this code to it:
export interface Announcement {
ID: number;
Title: string;
Body: string;
}
We will use the service to get the data from our list. Type in terminal
ng g s services/announcements Angular will generate a new empty service for us. Let's add a code to get the data:
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { Announcement } from '../data/Announcement';
@Injectable({
providedIn: 'root'
})
export class AnnouncementsService {
constructor(private http: HttpClient) { }
getAnnouncements(): Observable<Announcement[]> {
const pageContext: any = window[<any>'_spPageContextInfo'];
const requestUri =
pageContext.webAbsoluteUrl +
"/_api/web/lists/getbytitle('Announcements')/Items";
return this.http
.get(
requestUri,
{
headers: {
Accept: 'application/json;odata=verbose',
'odata-version': '',
},
}
)
.pipe(
map(
(itemsResult: any) => {
return itemsResult.d.results as Announcement[];
}
)
)
}
}
Before we move forward, I want to add a bootstrap 5 support to our project to use it for nice formatting. To do so, type in terminal:
npm i bootstrap --save After installation is completed, we have to modify angular.json file to add bootstrap support. Add the following references to styles and scripts sections:
Good, it's UI time. To create a new component, type in terminal:
ng g c components/announcements-component
Angular will generate a new component for us. First, open the announcements-component.component.ts and add this code:
import { DOCUMENT } from '@angular/common';
import { Component, Inject, OnInit } from '@angular/core';
import { AnnouncementsService } from 'src/app/services/announcements.service';
import {Announcement} from "../../data/Announcement";
@Component({
selector: 'app-announcements-component',
templateUrl: './announcements-component.component.html',
styleUrls: ['./announcements-component.component.css']
})
export class AnnouncementsComponentComponent implements OnInit {
announcements: Announcement[] = [];
constructor(private service: AnnouncementsService,
@Inject(DOCUMENT) private document: Document) { }
ngOnInit(): void {
this.initIcons();
this.service.getAnnouncements()
.subscribe(
(result) => {
this.announcements = result;
});
}
initIcons(){
const head = this.document.getElementsByTagName('head')[0];
const style = this.document.createElement('link');
style.id = 'boottrap-icons';
style.rel = 'stylesheet';
style.href = `https://cdn.jsdelivr.net/npm/bootstrap-icons@1.3.0/font/bootstrap-icons.css`;
head.appendChild(style);
}
}
Now, open the HTML file and add the following markup:
<ul class="nav nav-tabs" id="tabsHeader" role="tablist">
<li class="nav-item" role="presentation" *ngFor="let item of announcements; let i = index">
<button [class]="'nav-link ' + ((i===0) ? 'active': '')" [id]="'btn-' + item.ID"
data-bs-toggle="tab" [attr.data-bs-target]="'#tab-' + item.ID"
type="button" role="tab"
[attr.aria-controls]="'#tab-' + item.ID" aria-selected="true">
<i class="bi bi-newspaper"></i> {{item.Title}}
</button>
</li>
</ul>
<div class="tab-content" id="tabsContent">
<div [class]="'tab-pane fade show p-2 ' + ((i===0) ? 'active': '')" [id]="'tab-' + item.ID"
role="tabpanel" [attr.aria-labelledby]="'btn-' + item.ID"
*ngFor="let item of announcements; let i = index">
<div [innerHTML]="item.Body"></div>
</div>
</div>
And finally, we will add some styles to announcements-component.component.css
.tab-content {
border-left: 1px solid #ddd;
border-right: 1px solid #ddd;
border-bottom: 1px solid #ddd;
padding: 10px;
}
.nav-tabs {
margin-bottom: 0;
}
Ok, we have done with the component. Let's register it in app.module.ts
import { Injector, NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { HttpClientModule } from '@angular/common/http';
import { FirstComponentComponent } from './components/first-component/first-component.component';
import { createCustomElement } from '@angular/elements';
import { AnnouncementsComponentComponent } from
'./components/announcements-component/announcements-component.component';
@NgModule({
declarations: [
FirstComponentComponent,
AnnouncementsComponentComponent
],
imports: [
BrowserModule,
HttpClientModule
],
entryComponents: [FirstComponentComponent],
providers: [],
bootstrap: []
})
export class AppModule {
constructor(private injector: Injector) {}
ngDoBootstrap() {
const firstElment = createCustomElement(FirstComponentComponent, {
injector: this.injector,
});
const announcementsElment = createCustomElement(AnnouncementsComponentComponent, {
injector: this.injector,
});
customElements.define('first-element', firstElment);
customElements.define('announcements-element', announcementsElment);
}
}
After this we are good to go, just need to build our project. For this type in terminal:
ng build --prod --output-hashing=none This time, as we have added bootstrap support and some styles, we will have 2 more files - scripts.js and styles.js - we will copy them to our SharePoint's Site Assets library.

SharePoint part
Ok, now when we have all the required files, let's open SharePoint designer and copy all of them to Site Assets/sharepoint-angular folder:
Now, go to the Site Pages library and create a new test.aspx file. Right-click -> "Edit file in advanced mode" and past the following code:
<%@ Page Language="C#" masterpagefile="~masterurl/default.master"
inherits="Microsoft.SharePoint.WebPartPages.WebPartPage, Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"
meta:progid="SharePoint.WebPartPage.Document" meta:webpartpageexpansion="full" %>
<%@ Register tagprefix="WebControls" namespace="Microsoft.SharePoint.WebControls"
assembly="Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<asp:Content ContentPlaceHolderId="PlaceHolderPageTitle" runat="server">
Announcements
</asp:Content>
<asp:Content ContentPlaceHolderId="PlaceHolderPageTitleInTitleArea" runat="server">
Announcements page
</asp:Content>
<asp:Content id="Content1" runat="server" contentplaceholderid="PlaceHolderMain">
<link rel="stylesheet" type="text/css" href="../SiteAssets/sharepoint-angular/styles.css" />
<script src="../SiteAssets/sharepoint-angular/polyfills.js"></script>
<script src="../SiteAssets/sharepoint-angular/runtime.js"></script>
<script src="../SiteAssets/sharepoint-angular/scripts.js"></script>
<script src="../SiteAssets/sharepoint-angular/main.js"></script>
<div class="p-4">
<announcements-element></announcements-element>
</div>
</asp:Content>
Save the page and open it browser

Cool! We have created an angular element, which reads data from our SharePoint list and displays it using bootstrap 5. You can get the final project
code here.
In the next article, we will try to use our component in SPFx project and add it to SharePoint modern pages.
Stay tuned :)
Comments
Post a Comment