SlideShare a Scribd company logo
How to start SPEAK3
development
MIHÁLY ÁRVAI
Introduction
 Mihály Árvai
 Senior Sitecore Developer @ Mirum
 Hackathon Winner 2019
 7 SPEAK3 applications
 https://github.com/Mitya88
 Twitter
 @mitya_198812
 Medium
 @mitya_198812
 Slack
 Mitya88
Agenda
 How to create custom applications in Sitecore
 SPEAK 3 Basics
 Angular 4 basic
 Building a sample application
 My SPEAK3 applications
Twitter: @mitya_198812
Custom applications in
Sitecore
WHEN & HOW?
Options
 ASPX
 Classic way, still working, easy to setup, a lot of implementation
 Sitecore PowerShell Extensions
 Extra module, super powerful
 SPEAK (v1-v2)
 Sitecore Process Enablement & Accelator Kit
 A framework for building Sitecore Applications
 Enforces consistent look and feel
 Databinding
 Sitecore Rocks – You have to be connected to a Sitecore Instance
Twitter: @mitya_198812
Sitecore SPEAK3 presentation
 Introduced in Sitecore 9 (https://doc.sitecore.com/developers/speak/90/speak/en/speak-3.html)
 SPEAK3 = Single Page Application within Sitecore
 Based on Angular 4
 JavaScript libraries are delivered as NPM Packages
 Sitecore styling is available
 Role-based authorization
 Restricting access of SPEAK3 components using Sitecore security roles
 Handles expired sessions and unauthorized requests
 Supports logout process
SPEAK3
Twitter: @mitya_198812
 Protects again CSRF attacks
 Translations mechanism is provided for SPEAK3 components
 Disconnected mode
 Special stub server to handle all relevant request
 Mocks Sitecore Context, Dictionary items, your API endpoints
 Develop UI, API calls, etc. without Sitecore instance
SPEAK3
Twitter: @mitya_198812
Where to start?
 Clean Angular Project
 https://himynameistim.com/2018/02/27/sitecore-speak-3-
creating-an-application/
 Official SPEAK3 reference application
 https://webdevcms.home.blog/2019/01/21/quickstart-speak-3/
 Starter application (available on GitHub)
 https://medium.com/@mitya_1988/speed-up-your-sitecore-
speak3-development-fb1cc5af262c
 UI components application (available on GitHub)
 https://medium.com/@mitya_1988/sitecore-speak-3-ui-
collection-8515c04bf499
 Content Editor Toolbox (available on GitHub)
 Winner in best admin UI module@2019
Twitter: @mitya_198812
• integration between Angular and Sitecore
Integration Library
• post build steps, converts index.html to index.aspx
SPEAK3 Angular CLI Tool
• provides consisent look for Sitecore applications
Business Component Library
• implementations for Sitecore Design
Styling Library
• Sitecore Icons
Icons Library
npm
packages
Twitter: @mitya_198812
Tools &
commands
Twitter: @mitya_198812
Angular &
TypeScript
 Do I need to know them?
 https://angular.io/guide/architecture
 https://www.typescriptlang.org/
 Databinding
 https://medium.com/@venkateshece110
5/different-types-of-data-binding-in-
angular-8-0-f84c17ca7eb0
Twitter: @mitya_198812
https://www.code-sample.com/2018/01/angular-4-and-5-architecture-overview.html
Twitter: @mitya_198812
Project structure
 Index.html – the default page, Angular applications is loaded
into this html
 SPEAK3 CLI creates .aspx
 Inherited from Sitecore.Speak.Integration.Spa.SecureSpaPage
 App.module.ts – defines the AppModule (root module). It tells
angular how to assemble the application
 Modules, components(pages), services, routes, etc should be
registered here
 App.component.*.* - the parent component, in our example it
will act as a master page or layout
 Start-page.component.*
 Its a component rather than a page
 Its registered for /startpage route.
Twitter: @mitya_198812
SPEAK 3 Components
 https://github.com/Mitya88/SitecoreSpeakUILibrary
Twitter: @mitya_198812
 pppp
Buttons
<button scButton="primary">Primary</button>
<button scButton="secondary">Secondary</button>
<button scButton="info">Info</button>
<button scButton="link">Link</button>
<button scButton="chromeless">Chromeless</button>
<button scIconButton><sc-icon icon="apple"></sc-icon>
</button>
<sc-back-button>Back</sc-back-button>
 pppp
Metadata
<sc-icon icon="about" title="about" size="small">about</sc-icon>
<sc-icon icon="about" title="about" size="medium">about</sc-icon>
<sc-icon icon="about" title="about" size="large">about</sc-icon>
<sc-icon icon="about" title="about" size="xlarge">about</sc-icon>
<sc-icon icon="about" title="about" size="xxlarge">about</sc-icon>
<sc-icon icon="about" title="about" size="xxxlarge">about</sc-icon>
<sc-icon icon="about" title="about" size="xxxxlarge">about</sc-icon>
<sc-icon icon="about" title="about" size="xxxxxlarge">about</sc-icon>
<sc-progress-indicator-panel [show]="true">

<p>Lorem ipsum dolor sit amet consectetur adipisicing elit.</p>
</sc-progress-indicator-panel>
<sc-tab-group variant="switch">
<sc-tab label="Tab 1">
<sc-icon icon="about" title="about" size="xxxlarge">about</sc-icon><br />
</sc-tab>
<sc-tab label="Tab 2">
<sc-progress-indicator-panel [show]="true">

<p>Lorem ipsum dolor sit amet consectetur adipisicing elit.</p>
</sc-progress-indicator-panel>
</sc-tab>
<sc-tab label="Disabled tab" [disabled]="true">
<p>Disabled tab.</p>
</sc-tab>
</sc-tab-group>
<table scTable>
<thead>
<tr>
<th>#</th>
<th>First Name</th>
<th>Last Name</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Mark</td>
<td>Otto</td>
</tr>
</tbody>
</table>
<nav scPageNav>
<sc-menu>
<sc-menu-category icon="cake_slice" text="Closed by Default" [open]="false">
<sc-menu-item>
<a scMenuItemLink routerLink="lorem">Not active</a>
</sc-menu-item>
<sc-menu-item>
<a scMenuItemLink routerLink="ipsum" [active]="true">Active</a>
</sc-menu-item>
</sc-menu-category>
</sc-menu>
</nav>
<template #basicUsageDialog>
<sc-dialog>
<sc-dialog-header>
<h4>Demo Dialog Title</h4>
</sc-dialog-header>
<sc-dialog-body>
<h2>Add you components here</h2>
</sc-dialog-body>
<sc-dialog-footer>
<button scButton scDialogClose>Close</button>
<button scButton="primary" (click)="alertAndClose()">Save</button>
</sc-dialog-footer>
</sc-dialog>
</template>
<button scButton (click)="dialogService.open(basicUsageDialog)">Open a dialog</button>
It’s time to build something!
The old XPath builder
Twitter: @mitya_198812
 Remember: the presentation supports your story, not the other way around. Keep it clean, don’t overkill the
bullet points and throw in an animated gif if necessary.
 Many chapter slides offer placeholders to simply select background images. Who likes white slides anyway,
especially in the morning? :)
 Remember: the presentation supports your story, not the other way around. Keep it clean, don’t overkill the
bullet points and throw in an animated gif if necessary.
 Many chapter slides offer placeholders to simply select background images. Who likes white slides anyway,
especially in the morning? :)
Twitter: @mitya_198812
Twitter: @mitya_198812
Npm run start
Twitter: @mitya_198812
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Hello SUGCON2020!</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
<link href="https://fonts.googleapis.com/css?family=Open+Sans:ic,800,800italic" rel="styles
heet" type="text/css">
<link rel="stylesheet" href="/sitecore/shell/Themes/Speak/sitecore-icons.css">
</head>
<body>
<app-root></app-root>
</body>
</html>
Index.Html
@RenderBody() 
@Html.Sitecore().Placeholder("main") 
Twitter: @mitya_198812
App.component.ts
import { Component, OnInit } from '@angular/core';
import { NgScService } from '@speak/ng-sc';
import { SciLogoutService } from '@speak/ng-sc/logout';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {
isNavigationShown : boolean;
isActive:boolean;
constructor(
private ngScService: NgScService,
public logoutService: SciLogoutService
) { }
ngOnInit() {
// Call init to first fetch context, then translations
this.ngScService.init();
}
}
Twitter: @mitya_198812
App.component.html
<sc-page [showNav]="isNavigationShown">
<div scPageHeader>
<sc-global-header appName="Hello SUGCON2020!" [(show)]="isNavigationShown">
<a href="/sitecore/shell/sitecore/client/Applications/Launchpad" scGlobalLogo></a>
<sc-account-information (logout)="logoutService.logout()"></sc-account-information>
</sc-global-header>
</div>
<aside scPageNav>
<nav>
<sc-menu>
<sc-menu-category icon="cake_slice" text="Components" [open]="true">
<sc-menu-item>
<a scMenuItemLink routerLink="" routerLinkActive="active">Home</a>
</sc-menu-item> </sc-menu-category>
</sc-menu>
</nav>
</aside>
<div scPageAppHeader>
<sc-application-header text="Starter Template"></sc-application-header>
</div>
<article scPageContent class="p-4">
<router-outlet></router-outlet>
</article>
</sc-page>
Twitter: @mitya_198812
ng generate component xpathbuilder
Twitter: @mitya_198812
TS & html
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-xpathbuilder',
templateUrl: './xpathbuilder.component.html',
styleUrls: ['./xpathbuilder.component.scss']
})
export class XpathbuilderComponent implements OnInit {
constructor() { }
ngOnInit() {
}
}
<p>
xpathbuilder works!
</p>
Twitter: @mitya_198812
Displaying the component
<div class="card mb-3">
<div class="card-block">
<h1 class="card-title">Sitecore Starter Template</h1>
<app-xpathbuilder></app-xpathbuilder>
</div>
</div>
RouterModule.forRoot([
{ path: '', component: StartPageComponent, pathMatch: 'full' },
{ path: 'servicesample', component: ServiceSamplePageComponent },
{ path: 'xpath', component: XpathbuilderComponent}
]),
Twitter: @mitya_198812
app.module.ts
Displaying the component
ng generate service query
import { Injectable } from '@angular/core';
@Injectable()
export class QueryService {
constructor() { }
}
providers: [
SampleService, SciLogoutService, QueryService
],
app.module.ts
Twitter: @mitya_198812
Adding HttpClient
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
@Injectable()
export class QueryService {
constructor(private httpClient: HttpClient) {
}
baseUrl = "/sitecore/api/ssc/xpath/";
queryItems(body: any) {
return this.httpClient.post(this.baseUrl + 'query', body);
}
}
Twitter: @mitya_198812
Create Mock Query Service
module.exports = {
'POST /sitecore/api/ssc/xpath/query': function (req, res) {
res.json([
{
"Name": "Folder",
"Path": "/sitecore/templates/Common/Folder",
"Icon": "https://via.placeholder.com/32x32"
},
{
"Name": "Sample Item",
"Path": "/sitecore/templates/Sample/Sample Item",
"Icon": "/temp/iconcache/applications/32x32/document.png",
},
{
"Name": "Folder",
"Path": "/sitecore/templates/Common/Folder2",
"Icon": "/temp/iconcache/applications/32x32/folder.png"
}
])
}
};
Twitter: @mitya_198812
Create Mock Query Service
Twitter: @mitya_198812
Inject query service
import { Component, OnInit } from '@angular/core';
import { QueryService } from '../query.service';
@Component({
selector: 'app-xpathbuilder',
templateUrl: './xpathbuilder.component.html',
styleUrls: ['./xpathbuilder.component.scss']
})
export class XpathbuilderComponent implements OnInit {
constructor(private queryService: QueryService) { }
ngOnInit() {
var result = this.queryService.queryItems({ query: '/sitecore/conten
t/home’ })
.subscribe({
next: response => {
console.log(response);
}
});
}
}
Twitter: @mitya_198812
Verify the request
Twitter: @mitya_198812
Adding input
<div class="card mb-3">
<div class="card-block">
<h1 class="card-title">XPath Builder</h1>
<div class="row">
<div class="col-10">
<input type="text" class="form-control" [(ngModel)]="query"/>
<h2>{{query}}</h2>
</div>
<div class="col-1"></div>
</div>
<br>
<div class="row"></div>
<br>
<div class="row"></div>
</div>
</div>
@query<!—MVC - cshtml -->
@Html.TextBoxFor...
export class XpathbuilderComponent implements OnInit {
query:any;
Twitter: @mitya_198812
Databinding
Demo
Adding DatabaseSelector
<select id="database" [(ngModel)]="selectedDatabase" class="form-control">
<option *ngFor="let db of databases" [value]=„db">{{ db }}</option>
</select>
<select class="form-control">
@foreach (var db in databases)
{
<option value="@db">@db</option>
}
</select>
selectedDatabase = "master";
databases = ["master","web","core"];
Twitter: @mitya_198812
Adding Button
result: any;
isLoading:boolean;
errorMessage:any;
queryItems() {
this.isLoading = true;
this.errorMessage = null;
this.queryService.queryItems(
{
query: this.query,
database: this.selectedDatabase
}).subscribe({
next: response => {
this.result = response;
this.isLoading = false;
},
error: error =>{
this.isLoading = false;
this.errorMessage = error;
}
});
}
<button scButton="primary" (click)="queryItems()">Execute</button>
Twitter: @mitya_198812
Displaying the result
<div *ngIf="errorMessage" class="errorMessage">
{{errorMessage.Message}}
</div>
<table *ngIf="!isLoading && result" scTable>
<thead>
<tr>
<th>Name</th>
<th>Path</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let item of result">
<td><img src="{{item.Icon}}" width="10" height="10" />
&nbsp;{{item.Name}}
</td>
<td>{{item.Path}}</td>
</tr>
</tbody>
</table>
<sc-progress-indicator-panel [show]="isLoading">
</sc-progress-indicator-panel>
Twitter: @mitya_198812
Adding text to Dictionary
xpathTitle: string;
constructor(
private queryService: QueryService,
private dictionaryService: DictionarySe
rvice)
<h1 class="card-
title">{{dictionaryService.get(xpathT
itle, 'XPATHTITLE') | async}}</h1>
Twitter: @mitya_198812
In SitecoreTODO: VIDEO
Running application in Sitecore
Shortcut
Adding shortcut to the LaunchPad
Let’s recap  SPEAK3 & Angular basics
 Created a simple SPEAK3 app
 Used starter template
 Read data from inputs
 Created mock services
 Fetching data from an API
 Used built-in Dictionary service
 Added shortcut to Launchpad
 Other samples
 https://github.com/Mitya88
XPath Builder
Item Commander
Advanced Healthcheck
Forms Data Viewer
Thank you!

More Related Content

Sitecore SPEAK3 presentation

  • 1. How to start SPEAK3 development MIHÁLY ÁRVAI
  • 2. Introduction  Mihály Árvai  Senior Sitecore Developer @ Mirum  Hackathon Winner 2019  7 SPEAK3 applications  https://github.com/Mitya88  Twitter  @mitya_198812  Medium  @mitya_198812  Slack  Mitya88
  • 3. Agenda  How to create custom applications in Sitecore  SPEAK 3 Basics  Angular 4 basic  Building a sample application  My SPEAK3 applications Twitter: @mitya_198812
  • 5. Options  ASPX  Classic way, still working, easy to setup, a lot of implementation  Sitecore PowerShell Extensions  Extra module, super powerful  SPEAK (v1-v2)  Sitecore Process Enablement & Accelator Kit  A framework for building Sitecore Applications  Enforces consistent look and feel  Databinding  Sitecore Rocks – You have to be connected to a Sitecore Instance Twitter: @mitya_198812
  • 7.  Introduced in Sitecore 9 (https://doc.sitecore.com/developers/speak/90/speak/en/speak-3.html)  SPEAK3 = Single Page Application within Sitecore  Based on Angular 4  JavaScript libraries are delivered as NPM Packages  Sitecore styling is available  Role-based authorization  Restricting access of SPEAK3 components using Sitecore security roles  Handles expired sessions and unauthorized requests  Supports logout process SPEAK3 Twitter: @mitya_198812
  • 8.  Protects again CSRF attacks  Translations mechanism is provided for SPEAK3 components  Disconnected mode  Special stub server to handle all relevant request  Mocks Sitecore Context, Dictionary items, your API endpoints  Develop UI, API calls, etc. without Sitecore instance SPEAK3 Twitter: @mitya_198812
  • 9. Where to start?  Clean Angular Project  https://himynameistim.com/2018/02/27/sitecore-speak-3- creating-an-application/  Official SPEAK3 reference application  https://webdevcms.home.blog/2019/01/21/quickstart-speak-3/  Starter application (available on GitHub)  https://medium.com/@mitya_1988/speed-up-your-sitecore- speak3-development-fb1cc5af262c  UI components application (available on GitHub)  https://medium.com/@mitya_1988/sitecore-speak-3-ui- collection-8515c04bf499  Content Editor Toolbox (available on GitHub)  Winner in best admin UI module@2019 Twitter: @mitya_198812
  • 10. • integration between Angular and Sitecore Integration Library • post build steps, converts index.html to index.aspx SPEAK3 Angular CLI Tool • provides consisent look for Sitecore applications Business Component Library • implementations for Sitecore Design Styling Library • Sitecore Icons Icons Library npm packages Twitter: @mitya_198812
  • 12. Angular & TypeScript  Do I need to know them?  https://angular.io/guide/architecture  https://www.typescriptlang.org/  Databinding  https://medium.com/@venkateshece110 5/different-types-of-data-binding-in- angular-8-0-f84c17ca7eb0 Twitter: @mitya_198812
  • 14. Project structure  Index.html – the default page, Angular applications is loaded into this html  SPEAK3 CLI creates .aspx  Inherited from Sitecore.Speak.Integration.Spa.SecureSpaPage  App.module.ts – defines the AppModule (root module). It tells angular how to assemble the application  Modules, components(pages), services, routes, etc should be registered here  App.component.*.* - the parent component, in our example it will act as a master page or layout  Start-page.component.*  Its a component rather than a page  Its registered for /startpage route. Twitter: @mitya_198812
  • 15. SPEAK 3 Components  https://github.com/Mitya88/SitecoreSpeakUILibrary Twitter: @mitya_198812
  • 16.  pppp Buttons <button scButton="primary">Primary</button> <button scButton="secondary">Secondary</button> <button scButton="info">Info</button> <button scButton="link">Link</button> <button scButton="chromeless">Chromeless</button> <button scIconButton><sc-icon icon="apple"></sc-icon> </button> <sc-back-button>Back</sc-back-button>
  • 17.  pppp Metadata <sc-icon icon="about" title="about" size="small">about</sc-icon> <sc-icon icon="about" title="about" size="medium">about</sc-icon> <sc-icon icon="about" title="about" size="large">about</sc-icon> <sc-icon icon="about" title="about" size="xlarge">about</sc-icon> <sc-icon icon="about" title="about" size="xxlarge">about</sc-icon> <sc-icon icon="about" title="about" size="xxxlarge">about</sc-icon> <sc-icon icon="about" title="about" size="xxxxlarge">about</sc-icon> <sc-icon icon="about" title="about" size="xxxxxlarge">about</sc-icon>
  • 18. <sc-progress-indicator-panel [show]="true"> <!-- Content goes here --> <p>Lorem ipsum dolor sit amet consectetur adipisicing elit.</p> </sc-progress-indicator-panel>
  • 19. <sc-tab-group variant="switch"> <sc-tab label="Tab 1"> <sc-icon icon="about" title="about" size="xxxlarge">about</sc-icon><br /> </sc-tab> <sc-tab label="Tab 2"> <sc-progress-indicator-panel [show]="true"> <!-- Content goes here --> <p>Lorem ipsum dolor sit amet consectetur adipisicing elit.</p> </sc-progress-indicator-panel> </sc-tab> <sc-tab label="Disabled tab" [disabled]="true"> <p>Disabled tab.</p> </sc-tab> </sc-tab-group>
  • 20. <table scTable> <thead> <tr> <th>#</th> <th>First Name</th> <th>Last Name</th> </tr> </thead> <tbody> <tr> <td>1</td> <td>Mark</td> <td>Otto</td> </tr> </tbody> </table>
  • 21. <nav scPageNav> <sc-menu> <sc-menu-category icon="cake_slice" text="Closed by Default" [open]="false"> <sc-menu-item> <a scMenuItemLink routerLink="lorem">Not active</a> </sc-menu-item> <sc-menu-item> <a scMenuItemLink routerLink="ipsum" [active]="true">Active</a> </sc-menu-item> </sc-menu-category> </sc-menu> </nav>
  • 22. <template #basicUsageDialog> <sc-dialog> <sc-dialog-header> <h4>Demo Dialog Title</h4> </sc-dialog-header> <sc-dialog-body> <h2>Add you components here</h2> </sc-dialog-body> <sc-dialog-footer> <button scButton scDialogClose>Close</button> <button scButton="primary" (click)="alertAndClose()">Save</button> </sc-dialog-footer> </sc-dialog> </template> <button scButton (click)="dialogService.open(basicUsageDialog)">Open a dialog</button>
  • 23. It’s time to build something!
  • 24. The old XPath builder Twitter: @mitya_198812
  • 25.  Remember: the presentation supports your story, not the other way around. Keep it clean, don’t overkill the bullet points and throw in an animated gif if necessary.  Many chapter slides offer placeholders to simply select background images. Who likes white slides anyway, especially in the morning? :)
  • 26.  Remember: the presentation supports your story, not the other way around. Keep it clean, don’t overkill the bullet points and throw in an animated gif if necessary.  Many chapter slides offer placeholders to simply select background images. Who likes white slides anyway, especially in the morning? :) Twitter: @mitya_198812
  • 28. Npm run start Twitter: @mitya_198812
  • 29. <!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>Hello SUGCON2020!</title> <base href="/"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="icon" type="image/x-icon" href="favicon.ico"> <link href="https://fonts.googleapis.com/css?family=Open+Sans:ic,800,800italic" rel="styles heet" type="text/css"> <link rel="stylesheet" href="/sitecore/shell/Themes/Speak/sitecore-icons.css"> </head> <body> <app-root></app-root> </body> </html> Index.Html @RenderBody() <!--MVC --> @Html.Sitecore().Placeholder("main") <!-- Sitecore --> Twitter: @mitya_198812
  • 30. App.component.ts import { Component, OnInit } from '@angular/core'; import { NgScService } from '@speak/ng-sc'; import { SciLogoutService } from '@speak/ng-sc/logout'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.scss'] }) export class AppComponent implements OnInit { isNavigationShown : boolean; isActive:boolean; constructor( private ngScService: NgScService, public logoutService: SciLogoutService ) { } ngOnInit() { // Call init to first fetch context, then translations this.ngScService.init(); } } Twitter: @mitya_198812
  • 31. App.component.html <sc-page [showNav]="isNavigationShown"> <div scPageHeader> <sc-global-header appName="Hello SUGCON2020!" [(show)]="isNavigationShown"> <a href="/sitecore/shell/sitecore/client/Applications/Launchpad" scGlobalLogo></a> <sc-account-information (logout)="logoutService.logout()"></sc-account-information> </sc-global-header> </div> <aside scPageNav> <nav> <sc-menu> <sc-menu-category icon="cake_slice" text="Components" [open]="true"> <sc-menu-item> <a scMenuItemLink routerLink="" routerLinkActive="active">Home</a> </sc-menu-item> </sc-menu-category> </sc-menu> </nav> </aside> <div scPageAppHeader> <sc-application-header text="Starter Template"></sc-application-header> </div> <article scPageContent class="p-4"> <router-outlet></router-outlet> </article> </sc-page> Twitter: @mitya_198812
  • 32. ng generate component xpathbuilder Twitter: @mitya_198812
  • 33. TS & html import { Component, OnInit } from '@angular/core'; @Component({ selector: 'app-xpathbuilder', templateUrl: './xpathbuilder.component.html', styleUrls: ['./xpathbuilder.component.scss'] }) export class XpathbuilderComponent implements OnInit { constructor() { } ngOnInit() { } } <p> xpathbuilder works! </p> Twitter: @mitya_198812
  • 34. Displaying the component <div class="card mb-3"> <div class="card-block"> <h1 class="card-title">Sitecore Starter Template</h1> <app-xpathbuilder></app-xpathbuilder> </div> </div> RouterModule.forRoot([ { path: '', component: StartPageComponent, pathMatch: 'full' }, { path: 'servicesample', component: ServiceSamplePageComponent }, { path: 'xpath', component: XpathbuilderComponent} ]), Twitter: @mitya_198812 app.module.ts
  • 36. ng generate service query import { Injectable } from '@angular/core'; @Injectable() export class QueryService { constructor() { } } providers: [ SampleService, SciLogoutService, QueryService ], app.module.ts Twitter: @mitya_198812
  • 37. Adding HttpClient import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; @Injectable() export class QueryService { constructor(private httpClient: HttpClient) { } baseUrl = "/sitecore/api/ssc/xpath/"; queryItems(body: any) { return this.httpClient.post(this.baseUrl + 'query', body); } } Twitter: @mitya_198812
  • 38. Create Mock Query Service module.exports = { 'POST /sitecore/api/ssc/xpath/query': function (req, res) { res.json([ { "Name": "Folder", "Path": "/sitecore/templates/Common/Folder", "Icon": "https://via.placeholder.com/32x32" }, { "Name": "Sample Item", "Path": "/sitecore/templates/Sample/Sample Item", "Icon": "/temp/iconcache/applications/32x32/document.png", }, { "Name": "Folder", "Path": "/sitecore/templates/Common/Folder2", "Icon": "/temp/iconcache/applications/32x32/folder.png" } ]) } }; Twitter: @mitya_198812
  • 39. Create Mock Query Service Twitter: @mitya_198812
  • 40. Inject query service import { Component, OnInit } from '@angular/core'; import { QueryService } from '../query.service'; @Component({ selector: 'app-xpathbuilder', templateUrl: './xpathbuilder.component.html', styleUrls: ['./xpathbuilder.component.scss'] }) export class XpathbuilderComponent implements OnInit { constructor(private queryService: QueryService) { } ngOnInit() { var result = this.queryService.queryItems({ query: '/sitecore/conten t/home’ }) .subscribe({ next: response => { console.log(response); } }); } } Twitter: @mitya_198812
  • 42. Adding input <div class="card mb-3"> <div class="card-block"> <h1 class="card-title">XPath Builder</h1> <div class="row"> <div class="col-10"> <input type="text" class="form-control" [(ngModel)]="query"/> <h2>{{query}}</h2> </div> <div class="col-1"><!-- TODO Database selector--></div> </div> <br> <div class="row"><!-- TODO: Button --></div> <br> <div class="row"><!-- TODO: Result Table --></div> </div> </div> @query<!—MVC - cshtml --> @Html.TextBoxFor... export class XpathbuilderComponent implements OnInit { query:any; Twitter: @mitya_198812
  • 44. Adding DatabaseSelector <select id="database" [(ngModel)]="selectedDatabase" class="form-control"> <option *ngFor="let db of databases" [value]=„db">{{ db }}</option> </select> <select class="form-control"> @foreach (var db in databases) { <option value="@db">@db</option> } </select> selectedDatabase = "master"; databases = ["master","web","core"]; Twitter: @mitya_198812
  • 45. Adding Button result: any; isLoading:boolean; errorMessage:any; queryItems() { this.isLoading = true; this.errorMessage = null; this.queryService.queryItems( { query: this.query, database: this.selectedDatabase }).subscribe({ next: response => { this.result = response; this.isLoading = false; }, error: error =>{ this.isLoading = false; this.errorMessage = error; } }); } <button scButton="primary" (click)="queryItems()">Execute</button> Twitter: @mitya_198812
  • 46. Displaying the result <div *ngIf="errorMessage" class="errorMessage"> {{errorMessage.Message}} </div> <table *ngIf="!isLoading && result" scTable> <thead> <tr> <th>Name</th> <th>Path</th> </tr> </thead> <tbody> <tr *ngFor="let item of result"> <td><img src="{{item.Icon}}" width="10" height="10" /> &nbsp;{{item.Name}} </td> <td>{{item.Path}}</td> </tr> </tbody> </table> <sc-progress-indicator-panel [show]="isLoading"> </sc-progress-indicator-panel> Twitter: @mitya_198812
  • 47. Adding text to Dictionary xpathTitle: string; constructor( private queryService: QueryService, private dictionaryService: DictionarySe rvice) <h1 class="card- title">{{dictionaryService.get(xpathT itle, 'XPATHTITLE') | async}}</h1> Twitter: @mitya_198812
  • 48. In SitecoreTODO: VIDEO Running application in Sitecore
  • 50. Let’s recap  SPEAK3 & Angular basics  Created a simple SPEAK3 app  Used starter template  Read data from inputs  Created mock services  Fetching data from an API  Used built-in Dictionary service  Added shortcut to Launchpad  Other samples  https://github.com/Mitya88

Editor's Notes

  1. Hi My name is Mihály Árvai and I’m really happy to be here, and today I’m going to talk about SPEAK3
  2. Just a quick introduction. I’m a senior sitecore developer at Mirum, I created 7 SPEAK3 application so far and all of them are available on my GitHub. If you have any question later regarding SPEAK3, you can find me many social channels.
  3. Today, we will check what kind of other options are available to create a Sitecore application. After that I’m going to introduce the SPEAK3 and we will have a super solid Angular introduction. Once we have the basics, I’m going to show how to build your first SPEAK3 application Finally, I would like to show my existing speak3 applications
  4. So lets check what kind of options we have to create modules in Sitecore. There are many case when you need a custom module in your sitecore, e.g you have to manage some none sitecore data or your clients wants some custom dashboard, and there are many other case.
  5. The first option is the classic old way, using ASPX pages. This is still working, many admin applications are still using it. (e.g usermanager, dbbrowser, etc..) If you choose this way, you have to implement your own design, implement the authentication and authorization and probably it wont look like than any other Sitecore applications (CLICK) The second options is using the super powerfull PowerShell extension. I’m pretty sure this module can cover the most of the cases when you have to implement any custom report or application. Personally, I really like it (CLICK) The third option is using SPEAK version 2, which stands for Sitecore Process Enablement and accelator Kit. Its a framework for building sitecore applications within sitecore. It has reusable elements, enforces consistent look and databinding is support out of box. Unfortunatelly, you need to use Sitecore rocks, which means, you have to be connected to a sitecore instance. (and This is true for the other options too) I think the learnig curve is a bit high for the previous version of SPEAK frameworks, even throught you are an experienced developer. I had to implement a very simple SPEAK3 application to one of our clients and well.. It wasn’t so easy.
  6. I have a good news. Its time to forget everything about the previous version of SPEAK frameworks, because SPEAK3 is completelly different
  7. This was introduced in Sitecore 9 and e.g Commerce business tools is written in Speak3 too. It is basically a single page application with in Sitecore and Its based on angular 4, which is not the latest version of angular but its quite powerful. Yes, this means you have to use angular 4 and typescripts but lets talk about them later. Sitecore styling is available so your application will look like any built-in sitecore application. It supports role-based authorizations for components which means you may can limit access on different component for different user roles. E.g some roles cannot see some buttons or components in the application). The SPEAK3 application can handle the expired sessions and the unauthorized requests, which means if you open the application as anonymous user, you will be automatically redirected to the login page. And it has a built in process to handle logouts so you can logout the users from the Sitecore.
  8. It protects again CSRF attacks and there is a builtin dictionary service. So your application can be a multilanguage Sitecore app. One of the coolest thing about SPEAK3 is the disconnected mode. It means, you or your frontend developer do not need to be connected to a Sitecore instance when developing the UI. There is a special stub server which handles relevant request and mocks the sitecore context or your API requests. So creating the UI part of your application will be faster compared to Speak2 where you had to put toghet different controls in Sitecore Rocks
  9. Where should you start? There are many options. You can start with a clean angular application, there is a blogpost how to set it up from scracth. You can download the official reference application from sitecore. Or you can use my starter template which will be used later in this session. I prepared the a UI library for SPEAK3, which show the most of the components and styling. And of course you can check my github repo for other samples, e.g the hackathon winner application from lastyear
  10. There are some npm packages which you should know, like integration library which provides integration between angular and sitecore, a CLI tool which converts index.html to ASPX page, a component and styling library which enforces the consistent look and many icons can be found in the icons library which you can use easily iuse n your speak application
  11. The tools. You will need a nodejs. Its working fine with version 8. I prefer to use VS code, but it can be anything else. (VisualStudio or webstorm) As I mentioned previously, you dont need a siteore instance, so you can develop the UI on your mac There are a few commands which you should know. NPM install to install the dependencies, run start starts the application in disconnected mode, Build command build the application. Npm run deploy command can be only found in my starter projects. It builds and deployes to application into the predefined sitecore instance
  12. Do I need to know them? Its definitelly worth to check out angular architecture and typescript, but its really not impossible to build application without real life angular experience. There is a good article about the different databindings in angular. But lets check the most important things in Angular before we jump into SPEAK3.
  13. Angular is a platform and framework for building single-page client applications using HTML and TypeScript. And it is written in TypeScript.  The basic building blocks are the NgModules, which provide a compilation context for components. an Angular app is defined by a set of these NgModules and An app always has at least a root module that enables bootstrapping, and typically has many more feature modules. Components define views (or templates if you watc the diagram), which are HTML files. A template combines ordinary HTML with Angular directives and binding markup that allow Angular to modify the HTML before rendering it for display. Angular directives can modify the rendered DOM based on some logic. Components can use services, which provide specific functionality not directly related to views. The metadata for a component class associates it with a template that defines a view. The metadata for a service class provides the information Angular needs to make it available to components through dependency injection (DI). Lets see how the project stucture looks like based on this architecture
  14. A SPEAK3 projet looks like an Angular project. It has a index.html where the application will be loaded. That html will be converted to an ASPX which page, which inherited fro SecureSPAPage class. This handles the authoticatoin The app.module is the root of your application it tells angular how to assembly the application. Here you should register your components and services. If you register here your services, it can be injected to component an angular will be able to resolve it. App.component is the parent component, it will act as a masterpage or layout in our case. Finally, there are the different component files which may can handle different features and you can embed them into eachother.
  15. Lets quickly go through some SPEAK3 components before we start our application. Unfortunatelly, the official documentation is a bit poor about the available components so I created an application which displays and demonstrates how to use the most of the components and it also includes the avialable css classes which can be used in the application out-of-box
  16. SPEAk3 has many predefined/pre styled buttons like primary, secondary, or some buttons has some some default behavior, like the built-in backbutton component (which is an Angular component) which redirects the application back to the previous page.
  17. Many icons are available by default in the applications in 8 predefined sizes. You can embed this icons into other components, like we showed previously in case of the icon-button.
  18. There is a built-in progress indicator. You can control the visibility of the indicator via the show property.
  19. We have a tab – tabgroup components where you can define multiple tabs and add different content to different tabs.
  20. Built-in table with some stylingand there is an option to implement sorting on the rendered table.
  21. We can create sitecore branded navigations easily by using the built-in sc menu component. The navigation can have multiple group and each group can have their own icon, text, link elements.
  22. There is a built-in way to create dialog windows. You can define the content of the dialog in an angular template and you can open/close the dialog by using the built-in dialogservice. I think these are the most important components and we are going to use some of them now. If you check the UI library project, you will see other things such as the avialable css classes for background and text color, some text and containers formatting.
  23. Lets build our beloved admin page, the Xpath builder in sPEAK3!
  24. This is the old version of Xpath builder which we will build. I picked this one, because I really loved this tool when I started working as a Sitecore developer. Unfortunatelly, you can only access via direct urls in Sitecore 8 and it seems completelly broken in version 9.
  25. First step, clone my starter application from github. This repository contains the readme markdown file which has instruction about the initial project setup.
  26. There is an init powershell script in the project root. There are 4 variables which should be set before you start anything. This script going to replace special tokens here and there Application name is used as application name. This will be used in the URL Application title will go into the title tag Instancewebroot and instancehost is used by the npm run deploy command.
  27. If you run the PS1 script, the previously shown tokens will be replaced, e.g in the packages.json file, now you run can npm install command.
  28. If you run npm run start command, you will see the starter application on localhost, and there is no real sitecore behind it Its hosted on a local node server . Lets go through now the project and see what we have there
  29. Index.Html act as a master page or layout. It refers some extra css, sets the title and meta tags. There is an app-root tag in the indexhtml (CLICK), this is where the application (or the root component will be loaded) Its working like RenderBody in MVC world or Sitecore Placeholder in sitecore world.
  30. This is the typescript file for the root component. There is the selector app-root. Basically it tells angular if there is a tag with app-root this component should be loaded there. And also the component has a html template, app.component.html. This is basically almost the same when you defines a view path in your controller action.
  31. This is the app.component, our root component’s html. You can see many components and directives with sc prefix. scPageNav is an angular directive, sc-menu tag is component. I’ve already mentioned that directives can manipulate the dom where they placed. (e.g it adds or removes DOM elements, changes the stlying, etc) If you check the <router-outlet> tag, Acts as a placeholder that Angular dynamically fills based on the current router state. This means, you can tell angular which component should be loaded here on which path but the outter html will remain same on all path
  32. First of all, I need to generteate a new component. This component will contain everything what we need (inputs, result view, etc) If I use the ng generate component xpathbuilder command, It will create the html, the typescript file, and the stylesheet. It also registers this component in the app.module file. Basically its same if you create a new controller and view in an ASP MVC application.
  33. If we open the newly generated typescript file, we can see that Its a bit empty right now. Check the selector property (CLICK), it set to app-xpathbuilder, so we can use this tag to display our component in a different component or we can assign a route to XpathBuilderComponent class (CLICK). Lets see how to do that
  34. As I mentioned previously, we can embed our component to an existing component. The first block shows how to use the component on the start-page component. (We need to just add the <app-xpathbuilder> tag to the HTML where we want to display. In our case, this will be the startpage component. (We saw that this selector is defined by the newly generated xpathbuildercomponent) The second block shows, how to register the component on a new path. You see that the startpage component on the root path, ServiceSamplePageComponent on the servicessample path and xpathbuildercomponent on the xpath route
  35. The first screenshot was made on the homepage (Startpage component is registered for the root path) and we added the new component into the StartPage component the second made on the /xpath page, and you can see that there is no html which related to the startpagecomponent.
  36. Lets create a new service by using ng generate service command. This service will be used to call an API. The Service class marked with InjectAble decorator. If this decorator applied AND its is registered into the providers section), this service class can be injected into other classes.
  37. We should add httpClient, because we have to make api calls to sitecore to run sitecore queries. Httpclient is injectable out of box. We will post our sitecore queries to this URL. QueryItems functions will receive the post body and this will be posted to the given url. (CLICK) I just want to mention that you can use the injected parameter name from constructor accros the whole class in TypeScript and you dont have to initialize every prop/fieldin the constructor.
  38. But we are working in disconnected mode, so we need to define a mock responses. We can add the following javascript files to the mock folder and nodejs will serve this url with this response
  39. This is the result, if we made a post request in postman to our mock endpoint on the node server. Its working so its ready to use in disconnected mode
  40. Lets go back to the xpathbuilder component (CLICK)and lets inject the QueryService. You may have seen the NgOnInit method previously. (CLICK) NgOnInit is part of the angular lifecycle, which means method called everytime when the component loaded. So Right now, there will be an API call, with the following query when the component loads. This means, our services will be called when the XPathComponent loaded and the response will be logged to the browser’s console. On the righthand side, you can see different methods in angular lifecycle in order.
  41. After starting our application, we can see in the console the result of the request because xpathcomponent has been loaded properly
  42. Its time to add aninput to our component, where you will be able to type your Sitecore Query. You can add a simple input and define a variable in the typescript file. You can bind this variable to the input with the ngModel attribute. This means any typed character will be binded immediately to query variable Moreover you can display the variable with with curly braces. Its same like in razor view the at sign.
  43. Because of the databinding, any typed value displayed immediatelly on where we display the value.
  44. Lets create a database selector in our component. We can create a variable to store the selected values and an array for the available databases in the typescript file. We should bind selectedDatabase property to the select tag via ngModel attribute. To render the option, we can use *ngFor directive, which will iterate through the databases array and will render an option tag for each database. We learned a few slides ago that angular directives can manipulate the dom. If we changed the select’s value, in will be binded into the selectedDatabase variable. The last block is the eqvivalent implementation with razor engine
  45. We have input and a database selector, we need a button which will call the API with the typed query and the selected database and displays the result. We can bind a click event to the button by click attribute. In the typescript file, I created a few variables. (CLICK) Result will hold the API response, isLoading will be used to display a progress indicator. These variables are available in the html file too. The query items functions shows how to call your API service and retrieve the response or handle any errors. We will post the quest and the database parameters (CLICK) On the right hand side, you can see the different events and how to bind them to html elements
  46. And finally, we can render the result. (CLICK) ngIf directive means that the given dom element will be only rendered if the condition is true. So errorMessage div element will be rendered if the errorMessage variable has any value (CLICK) the table will be rendered if result variable has value and isloading is false (CLICK) And finally, the progress indicator will be displayed only if isloading variable set to true. This is also an out-of-box component in SPEAK3
  47. And finally, just a minor cosmatic change. , lets add the some text to Sitecore dictionary. The following code demonstrate how to use the built-in dictionary service. We need to inject where we want to use it, and we need to define a variable for each dictionary entry. (CLICK) the services are also available in the Typescript file Dictionary items for speak3 is located in Core database, under business componentlibrary, version 3 node
  48. After I deployed the application into the sitecore, we can run it there by opening the application on the direct url. (if you remembed, you can see this url in the package.json file). I haven’t showed but I created a simple API which can run Sitecore queries and returns the response
  49. Finally, we can add a shortcut to the launchpad in the core database. We need only set the Text, Icon, and Link field on the ShortCut item and it will be displayed on the Launchpad.
  50. So today we checked the basics of SPEAK3 and Angular and we created a simple application where we used my starter template, and we covered many topics which should be enough to start your SPEAK3 apllication. And finally, let me show my SPEAK applications which are available on GitHub so you can check the source codes
  51. First of all, I enhanced a little bit today’s sample application, which looks like the old XpathBuilder. I included the the famous Sitecore Query Cheatsheet document too. It supports relative queries too but the context node switcher was a bit tricky. You can check the full sourcecode on github and you can download sitecore install package too.
  52. My very first SPEAK3 application is the item commander. It looks like a file based commander and the main purpose of this module to select and manipulate multiple items in the same time. So you can select multiple items by rightclick, you can copy/move/delete them. There is a batch rename feature, or you can open the selected item directly in Experience or Content editor, you can search for items and displays a progress bar when you are manipulating multiple items. And it has many other greate feature which speed ups your work
  53. One of my biggest module is the Advanced healthcheck module. Thismodule can check your Sitecore services and any 3rd service/dependency which you have in Sitecore Solution and this module has a dashboard, written in SPEAK3. This application uses ChartJs so if you need to use charts in your application you can check it how to use it.
  54. And finally, my latest module is the Forms Data Viewer, which gives you ability to display and export Forms saved data in browser. This also uses ChartJS library and this is still in progress