function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Paul BarberPaul Barber 

Angular Integration

I'm trying to use the Canvas SDK with an Angular (6) app (not AngularJS), but I'm having trouble using the import.  I created a simple Hello World app using the Angular CLI command "ng new hello-world".  I installed the Canvas SDK using "npm install @salesforce/canvas-js-sdk" in the new hello-world folder.  I updated the app.component.js to import the Canvas SDK and use it, but I get an execution error.

app.comonent.ts:
import { Component } from '@angular/core';

import * as Sfdc from '@salesforce/canvas-js-sdk';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'hello-world';

  ngOnInit(): void {
    //Sample Signed Request
    const signedRequestJson = '{ "context": { "application": { "applicationId": "06Px000000003ed", "authType": "SIGNED_REQUEST", "canvasUrl": "http://instance.salesforce.com:8080/canvas_app_path/canvas_app.jsp", "developerName": "my_java_app", "isInstalledPersonalApp": false, "name": "My Java App", "namespace": "org_namespace", "options": [], "referenceId": "09HD00000000AUM", "samlInitiationMethod": "None", "version": "1.0.0" }, "user": { "accessibilityModeEnabled": false, "currencyISOCode": "USD", "email": "admin@6457617734813492.com", "firstName": "Sean", "fullName": "Sean Forbes", "isDefaultNetwork": false, "language": "en_US", "lastName": "Forbes", "locale": "en_US", "networkId": "0DBxx000000001r", "profileId": "00ex0000000jzpt", "profilePhotoUrl": "/profilephoto/005/F", "profileThumbnailUrl": "/profilephoto/005/T", "roleId": null, "siteUrl": "https://mydomain.force.com/", "siteUrlPrefix": "/mycommunity", "timeZone": "America/Los_Angeles", "userId": "005x0000001SyyEAAS", "userName": "admin@6457617734813492.com", "userType": "STANDARD" }, "environment": { "parameters": { "complex": { "key1": "value1", "key2": "value2" }, "integer": 10, "simple": "This is a simple string.", "boolean": true }, "dimensions": { "clientHeight": "50px", "clientWidth": "70px", "height": "900px", "width": "800px", "maxHeight": "2000px", "maxWidth": "1000px" }, "record": { "attributes": { "type": "Account", "url": "/services/data/v44.0/sobjects/Account/001xx000003DGWiAAO" }, "Id": "001xx000003DGWiAAO", "Phone": "(555) 555-5555", "Fax": "(555) 555-5555", "BillingCity": "Seattle" }, "displayLocation": "Chatter", "locationUrl": "http://www.salesforce.com/some/path/index.html", "subLocation": null, "uiTheme": "Theme3", "version": { "api": "44.0", "season": "SUMMER" } }, "organization": { "currencyIsoCode": "USD", "multicurrencyEnabled": true, "name": "Edge Communications", "namespacePrefix": "org_namespace", "organizationId": "00Dx00000001hxyEAA" }, "links": { "chatterFeedItemsUrl": "/services/data/v44.0/chatter/feed-items", "chatterFeedsUrl": "/services/data/v44.0/chatter/feeds", "chatterGroupsUrl": "/services/data/v44.0/chatter/groups", "chatterUsersUrl": "/services/data/v44.0/chatter/users", "enterpriseUrl": "/services/Soap/c/44.0/00Dx00000001hxy", "loginUrl": "http://login.salesforce.com", "metadataUrl": "/services/Soap/m/44.0/00Dx00000001hxy", "partnerUrl": "/services/Soap/u/44.0/00Dx00000001hxy", "queryUrl": "/services/data/v44.0/query/", "recentItemsUrl": "/services/data/v44.0/recent/", "restUrl": "/services/data/v44.0/", "searchUrl": "/services/data/v44.0/search/", "sobjectUrl": "/services/data/v44.0/sobjects/", "userUrl": "/005x0000001SyyEAAS" } }, "client": { "instanceId": "06Px000000002JZ", "instanceUrl": "http://instance.salesforce.com:8080", "oauthToken": "00Dx0000X00Or4J!ARQAQJ34YL8gKowP65p8FDHkvk.Uq5...", "refreshToken": "00DD0000000K1NM!ARAAQGJVGOyMjh1jjqvShRpLuAq0...", "targetOrigin": "http://instance.salesforce.com:8080" }, "algorithm": "HMACSHA256", "userId": "005x0000001SyyEAAS", "issuedAt": null }';
    const signedRequest: any = JSON.parse(signedRequestJson);
    const publishName = 'myPublishName';
    const payload: any = {
      name1: 'value1',
      name2: 'value2'
    };
    Sfdc.canvas.client.publish(signedRequest.client,
      { name: publishName, payload: payload }
    );

  }

}
Error encounted on the "Sfdc.canvas.client.publish" line:
ERROR TypeError: Cannot read property 'client' of undefined

I did also create a typings.d.ts file with the following, but I think that's just to make Visual Studio Code happy.
declare module '@salesforce/canvas-js-sdk';

In the Chrome debugger when it's executing the lines before the error, I can hover over the Sfdc import and see canvas.client.publish, but not on the actual execution line.  It seems it doesn't have a reference to Sfdc at this part of the code.  Is there something fundamentally wrong with how I'm referecing the import?
 
Paul BarberPaul Barber
Note:  On line 21, the actual code doesn't have the bold <b> </b> tags.  That was somehow added by this tool when I was trying to emphasis it.
Paul BarberPaul Barber
I found a solution, but I'm not sure it's the 'proper' solution.  It may also only apply to Angular 6 as I found these comments elsewhere:
 
Angular 6 has a dedicated place to declare js files within the dedicated arrays of your angular.json, under
/projects/$(youProjectName)/architect/build/options/scripts[]
and
/projects/$(youProjectName)/architect/test/options/scripts[]

So my angular.json now has this entry in scripts:
"scripts": [
     "node_modules/@salesforce/canvas-js-sdk/js/canvas-all.js"
 ]
Additionally, instead of using an import of the Canvas SDK like:
import * as Sfdc from '@salesforce/canvas-js-sdk';
I'm declaring a variable like:
declare var Sfdc: any;
So the updated app.component.ts now looks like:
import { Component } from '@angular/core';

declare var Sfdc: any;

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'hello-world-new';

  ngOnInit(): void {
    // Sample Signed Request JSON
    const signedRequestJson = '{ "context": { "application": { "applicationId": "06Px000000003ed", "authType": "SIGNED_REQUEST", "canvasUrl": "http://instance.salesforce.com:8080/canvas_app_path/canvas_app.jsp", "developerName": "my_java_app", "isInstalledPersonalApp": false, "name": "My Java App", "namespace": "org_namespace", "options": [], "referenceId": "09HD00000000AUM", "samlInitiationMethod": "None", "version": "1.0.0" }, "user": { "accessibilityModeEnabled": false, "currencyISOCode": "USD", "email": "admin@6457617734813492.com", "firstName": "Sean", "fullName": "Sean Forbes", "isDefaultNetwork": false, "language": "en_US", "lastName": "Forbes", "locale": "en_US", "networkId": "0DBxx000000001r", "profileId": "00ex0000000jzpt", "profilePhotoUrl": "/profilephoto/005/F", "profileThumbnailUrl": "/profilephoto/005/T", "roleId": null, "siteUrl": "https://mydomain.force.com/", "siteUrlPrefix": "/mycommunity", "timeZone": "America/Los_Angeles", "userId": "005x0000001SyyEAAS", "userName": "admin@6457617734813492.com", "userType": "STANDARD" }, "environment": { "parameters": { "complex": { "key1": "value1", "key2": "value2" }, "integer": 10, "simple": "This is a simple string.", "boolean": true }, "dimensions": { "clientHeight": "50px", "clientWidth": "70px", "height": "900px", "width": "800px", "maxHeight": "2000px", "maxWidth": "1000px" }, "record": { "attributes": { "type": "Account", "url": "/services/data/v44.0/sobjects/Account/001xx000003DGWiAAO" }, "Id": "001xx000003DGWiAAO", "Phone": "(555) 555-5555", "Fax": "(555) 555-5555", "BillingCity": "Seattle" }, "displayLocation": "Chatter", "locationUrl": "http://www.salesforce.com/some/path/index.html", "subLocation": null, "uiTheme": "Theme3", "version": { "api": "44.0", "season": "SUMMER" } }, "organization": { "currencyIsoCode": "USD", "multicurrencyEnabled": true, "name": "Edge Communications", "namespacePrefix": "org_namespace", "organizationId": "00Dx00000001hxyEAA" }, "links": { "chatterFeedItemsUrl": "/services/data/v44.0/chatter/feed-items", "chatterFeedsUrl": "/services/data/v44.0/chatter/feeds", "chatterGroupsUrl": "/services/data/v44.0/chatter/groups", "chatterUsersUrl": "/services/data/v44.0/chatter/users", "enterpriseUrl": "/services/Soap/c/44.0/00Dx00000001hxy", "loginUrl": "http://login.salesforce.com", "metadataUrl": "/services/Soap/m/44.0/00Dx00000001hxy", "partnerUrl": "/services/Soap/u/44.0/00Dx00000001hxy", "queryUrl": "/services/data/v44.0/query/", "recentItemsUrl": "/services/data/v44.0/recent/", "restUrl": "/services/data/v44.0/", "searchUrl": "/services/data/v44.0/search/", "sobjectUrl": "/services/data/v44.0/sobjects/", "userUrl": "/005x0000001SyyEAAS" } }, "client": { "instanceId": "06Px000000002JZ", "instanceUrl": "http://instance.salesforce.com:8080", "oauthToken": "00Dx0000X00Or4J!ARQAQJ34YL8gKowP65p8FDHkvk.Uq5...", "refreshToken": "00DD0000000K1NM!ARAAQGJVGOyMjh1jjqvShRpLuAq0...", "targetOrigin": "http://localhost:4200" }, "algorithm": "HMACSHA256", "userId": "005x0000001SyyEAAS", "issuedAt": null }';
    const signedRequest: any = JSON.parse(signedRequestJson);
    const publishName = 'myPublishName';
    const payload: any = {
      name1: 'value1',
      name2: 'value2'
    };
    Sfdc.canvas.client.publish(signedRequest.client,
      { name: publishName, payload: payload }
    );
  }

}
Now when executing Sfdc is not undefined and the canvas.client.publish() function executes.